')
+ } else {
+ _, _ = w.WriteString("")
+ }
+ } else {
+ _, _ = w.WriteString("")
+ }
+ return gast.WalkContinue, nil
+}
+
+type strikethrough struct {
+}
+
+// Strikethrough is an extension that allow you to use strikethrough expression like '~~text~~' .
+var Strikethrough = &strikethrough{}
+
+func (e *strikethrough) Extend(m goldmark.Markdown) {
+ m.Parser().AddOptions(parser.WithInlineParsers(
+ util.Prioritized(NewStrikethroughParser(), 500),
+ ))
+ m.Renderer().AddOptions(renderer.WithNodeRenderers(
+ util.Prioritized(NewStrikethroughHTMLRenderer(), 500),
+ ))
+}
diff --git a/vendor/github.com/yuin/goldmark/extension/table.go b/vendor/github.com/yuin/goldmark/extension/table.go
new file mode 100644
index 0000000..c637b99
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/table.go
@@ -0,0 +1,552 @@
+package extension
+
+import (
+ "bytes"
+ "fmt"
+ "regexp"
+
+ "github.com/yuin/goldmark"
+ gast "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/extension/ast"
+ "github.com/yuin/goldmark/parser"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+var escapedPipeCellListKey = parser.NewContextKey()
+
+type escapedPipeCell struct {
+ Cell *ast.TableCell
+ Pos []int
+ Transformed bool
+}
+
+// TableCellAlignMethod indicates how are table cells aligned in HTML format.indicates how are table cells aligned in HTML format.
+type TableCellAlignMethod int
+
+const (
+ // TableCellAlignDefault renders alignments by default method.
+ // With XHTML, alignments are rendered as an align attribute.
+ // With HTML5, alignments are rendered as a style attribute.
+ TableCellAlignDefault TableCellAlignMethod = iota
+
+ // TableCellAlignAttribute renders alignments as an align attribute.
+ TableCellAlignAttribute
+
+ // TableCellAlignStyle renders alignments as a style attribute.
+ TableCellAlignStyle
+
+ // TableCellAlignNone does not care about alignments.
+ // If you using classes or other styles, you can add these attributes
+ // in an ASTTransformer.
+ TableCellAlignNone
+)
+
+// TableConfig struct holds options for the extension.
+type TableConfig struct {
+ html.Config
+
+ // TableCellAlignMethod indicates how are table celss aligned.
+ TableCellAlignMethod TableCellAlignMethod
+}
+
+// TableOption interface is a functional option interface for the extension.
+type TableOption interface {
+ renderer.Option
+ // SetTableOption sets given option to the extension.
+ SetTableOption(*TableConfig)
+}
+
+// NewTableConfig returns a new Config with defaults.
+func NewTableConfig() TableConfig {
+ return TableConfig{
+ Config: html.NewConfig(),
+ TableCellAlignMethod: TableCellAlignDefault,
+ }
+}
+
+// SetOption implements renderer.SetOptioner.
+func (c *TableConfig) SetOption(name renderer.OptionName, value interface{}) {
+ switch name {
+ case optTableCellAlignMethod:
+ c.TableCellAlignMethod = value.(TableCellAlignMethod)
+ default:
+ c.Config.SetOption(name, value)
+ }
+}
+
+type withTableHTMLOptions struct {
+ value []html.Option
+}
+
+func (o *withTableHTMLOptions) SetConfig(c *renderer.Config) {
+ if o.value != nil {
+ for _, v := range o.value {
+ v.(renderer.Option).SetConfig(c)
+ }
+ }
+}
+
+func (o *withTableHTMLOptions) SetTableOption(c *TableConfig) {
+ if o.value != nil {
+ for _, v := range o.value {
+ v.SetHTMLOption(&c.Config)
+ }
+ }
+}
+
+// WithTableHTMLOptions is functional option that wraps goldmark HTMLRenderer options.
+func WithTableHTMLOptions(opts ...html.Option) TableOption {
+ return &withTableHTMLOptions{opts}
+}
+
+const optTableCellAlignMethod renderer.OptionName = "TableTableCellAlignMethod"
+
+type withTableCellAlignMethod struct {
+ value TableCellAlignMethod
+}
+
+func (o *withTableCellAlignMethod) SetConfig(c *renderer.Config) {
+ c.Options[optTableCellAlignMethod] = o.value
+}
+
+func (o *withTableCellAlignMethod) SetTableOption(c *TableConfig) {
+ c.TableCellAlignMethod = o.value
+}
+
+// WithTableCellAlignMethod is a functional option that indicates how are table cells aligned in HTML format.
+func WithTableCellAlignMethod(a TableCellAlignMethod) TableOption {
+ return &withTableCellAlignMethod{a}
+}
+
+func isTableDelim(bs []byte) bool {
+ for _, b := range bs {
+ if !(util.IsSpace(b) || b == '-' || b == '|' || b == ':') {
+ return false
+ }
+ }
+ return true
+}
+
+var tableDelimLeft = regexp.MustCompile(`^\s*\:\-+\s*$`)
+var tableDelimRight = regexp.MustCompile(`^\s*\-+\:\s*$`)
+var tableDelimCenter = regexp.MustCompile(`^\s*\:\-+\:\s*$`)
+var tableDelimNone = regexp.MustCompile(`^\s*\-+\s*$`)
+
+type tableParagraphTransformer struct {
+}
+
+var defaultTableParagraphTransformer = &tableParagraphTransformer{}
+
+// NewTableParagraphTransformer returns a new ParagraphTransformer
+// that can transform paragraphs into tables.
+func NewTableParagraphTransformer() parser.ParagraphTransformer {
+ return defaultTableParagraphTransformer
+}
+
+func (b *tableParagraphTransformer) Transform(node *gast.Paragraph, reader text.Reader, pc parser.Context) {
+ lines := node.Lines()
+ if lines.Len() < 2 {
+ return
+ }
+ for i := 1; i < lines.Len(); i++ {
+ alignments := b.parseDelimiter(lines.At(i), reader)
+ if alignments == nil {
+ continue
+ }
+ header := b.parseRow(lines.At(i-1), alignments, true, reader, pc)
+ if header == nil || len(alignments) != header.ChildCount() {
+ return
+ }
+ table := ast.NewTable()
+ table.Alignments = alignments
+ table.AppendChild(table, ast.NewTableHeader(header))
+ for j := i + 1; j < lines.Len(); j++ {
+ table.AppendChild(table, b.parseRow(lines.At(j), alignments, false, reader, pc))
+ }
+ node.Lines().SetSliced(0, i-1)
+ node.Parent().InsertAfter(node.Parent(), node, table)
+ if node.Lines().Len() == 0 {
+ node.Parent().RemoveChild(node.Parent(), node)
+ } else {
+ last := node.Lines().At(i - 2)
+ last.Stop = last.Stop - 1 // trim last newline(\n)
+ node.Lines().Set(i-2, last)
+ }
+ }
+}
+
+func (b *tableParagraphTransformer) parseRow(segment text.Segment, alignments []ast.Alignment, isHeader bool, reader text.Reader, pc parser.Context) *ast.TableRow {
+ source := reader.Source()
+ line := segment.Value(source)
+ pos := 0
+ pos += util.TrimLeftSpaceLength(line)
+ limit := len(line)
+ limit -= util.TrimRightSpaceLength(line)
+ row := ast.NewTableRow(alignments)
+ if len(line) > 0 && line[pos] == '|' {
+ pos++
+ }
+ if len(line) > 0 && line[limit-1] == '|' {
+ limit--
+ }
+ i := 0
+ for ; pos < limit; i++ {
+ alignment := ast.AlignNone
+ if i >= len(alignments) {
+ if !isHeader {
+ return row
+ }
+ } else {
+ alignment = alignments[i]
+ }
+
+ var escapedCell *escapedPipeCell
+ node := ast.NewTableCell()
+ node.Alignment = alignment
+ hasBacktick := false
+ closure := pos
+ for ; closure < limit; closure++ {
+ if line[closure] == '`' {
+ hasBacktick = true
+ }
+ if line[closure] == '|' {
+ if closure == 0 || line[closure-1] != '\\' {
+ break
+ } else if hasBacktick {
+ if escapedCell == nil {
+ escapedCell = &escapedPipeCell{node, []int{}, false}
+ escapedList := pc.ComputeIfAbsent(escapedPipeCellListKey,
+ func() interface{} {
+ return []*escapedPipeCell{}
+ }).([]*escapedPipeCell)
+ escapedList = append(escapedList, escapedCell)
+ pc.Set(escapedPipeCellListKey, escapedList)
+ }
+ escapedCell.Pos = append(escapedCell.Pos, segment.Start+closure-1)
+ }
+ }
+ }
+ seg := text.NewSegment(segment.Start+pos, segment.Start+closure)
+ seg = seg.TrimLeftSpace(source)
+ seg = seg.TrimRightSpace(source)
+ node.Lines().Append(seg)
+ row.AppendChild(row, node)
+ pos = closure + 1
+ }
+ for ; i < len(alignments); i++ {
+ row.AppendChild(row, ast.NewTableCell())
+ }
+ return row
+}
+
+func (b *tableParagraphTransformer) parseDelimiter(segment text.Segment, reader text.Reader) []ast.Alignment {
+ line := segment.Value(reader.Source())
+ if !isTableDelim(line) {
+ return nil
+ }
+ cols := bytes.Split(line, []byte{'|'})
+ if util.IsBlank(cols[0]) {
+ cols = cols[1:]
+ }
+ if len(cols) > 0 && util.IsBlank(cols[len(cols)-1]) {
+ cols = cols[:len(cols)-1]
+ }
+
+ var alignments []ast.Alignment
+ for _, col := range cols {
+ if tableDelimLeft.Match(col) {
+ alignments = append(alignments, ast.AlignLeft)
+ } else if tableDelimRight.Match(col) {
+ alignments = append(alignments, ast.AlignRight)
+ } else if tableDelimCenter.Match(col) {
+ alignments = append(alignments, ast.AlignCenter)
+ } else if tableDelimNone.Match(col) {
+ alignments = append(alignments, ast.AlignNone)
+ } else {
+ return nil
+ }
+ }
+ return alignments
+}
+
+type tableASTTransformer struct {
+}
+
+var defaultTableASTTransformer = &tableASTTransformer{}
+
+// NewTableASTTransformer returns a parser.ASTTransformer for tables.
+func NewTableASTTransformer() parser.ASTTransformer {
+ return defaultTableASTTransformer
+}
+
+func (a *tableASTTransformer) Transform(node *gast.Document, reader text.Reader, pc parser.Context) {
+ lst := pc.Get(escapedPipeCellListKey)
+ if lst == nil {
+ return
+ }
+ pc.Set(escapedPipeCellListKey, nil)
+ for _, v := range lst.([]*escapedPipeCell) {
+ if v.Transformed {
+ continue
+ }
+ _ = gast.Walk(v.Cell, func(n gast.Node, entering bool) (gast.WalkStatus, error) {
+ if !entering || n.Kind() != gast.KindCodeSpan {
+ return gast.WalkContinue, nil
+ }
+
+ for c := n.FirstChild(); c != nil; {
+ next := c.NextSibling()
+ if c.Kind() != gast.KindText {
+ c = next
+ continue
+ }
+ parent := c.Parent()
+ ts := &c.(*gast.Text).Segment
+ n := c
+ for _, v := range lst.([]*escapedPipeCell) {
+ for _, pos := range v.Pos {
+ if ts.Start <= pos && pos < ts.Stop {
+ segment := n.(*gast.Text).Segment
+ n1 := gast.NewRawTextSegment(segment.WithStop(pos))
+ n2 := gast.NewRawTextSegment(segment.WithStart(pos + 1))
+ parent.InsertAfter(parent, n, n1)
+ parent.InsertAfter(parent, n1, n2)
+ parent.RemoveChild(parent, n)
+ n = n2
+ v.Transformed = true
+ }
+ }
+ }
+ c = next
+ }
+ return gast.WalkContinue, nil
+ })
+ }
+}
+
+// TableHTMLRenderer is a renderer.NodeRenderer implementation that
+// renders Table nodes.
+type TableHTMLRenderer struct {
+ TableConfig
+}
+
+// NewTableHTMLRenderer returns a new TableHTMLRenderer.
+func NewTableHTMLRenderer(opts ...TableOption) renderer.NodeRenderer {
+ r := &TableHTMLRenderer{
+ TableConfig: NewTableConfig(),
+ }
+ for _, opt := range opts {
+ opt.SetTableOption(&r.TableConfig)
+ }
+ return r
+}
+
+// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
+func (r *TableHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
+ reg.Register(ast.KindTable, r.renderTable)
+ reg.Register(ast.KindTableHeader, r.renderTableHeader)
+ reg.Register(ast.KindTableRow, r.renderTableRow)
+ reg.Register(ast.KindTableCell, r.renderTableCell)
+}
+
+// TableAttributeFilter defines attribute names which table elements can have.
+var TableAttributeFilter = html.GlobalAttributeFilter.Extend(
+ []byte("align"), // [Deprecated]
+ []byte("bgcolor"), // [Deprecated]
+ []byte("border"), // [Deprecated]
+ []byte("cellpadding"), // [Deprecated]
+ []byte("cellspacing"), // [Deprecated]
+ []byte("frame"), // [Deprecated]
+ []byte("rules"), // [Deprecated]
+ []byte("summary"), // [Deprecated]
+ []byte("width"), // [Deprecated]
+)
+
+func (r *TableHTMLRenderer) renderTable(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
+ if entering {
+ _, _ = w.WriteString("\n")
+ } else {
+ _, _ = w.WriteString("
\n")
+ }
+ return gast.WalkContinue, nil
+}
+
+// TableHeaderAttributeFilter defines attribute names which elements can have.
+var TableHeaderAttributeFilter = html.GlobalAttributeFilter.Extend(
+ []byte("align"), // [Deprecated since HTML4] [Obsolete since HTML5]
+ []byte("bgcolor"), // [Not Standardized]
+ []byte("char"), // [Deprecated since HTML4] [Obsolete since HTML5]
+ []byte("charoff"), // [Deprecated since HTML4] [Obsolete since HTML5]
+ []byte("valign"), // [Deprecated since HTML4] [Obsolete since HTML5]
+)
+
+func (r *TableHTMLRenderer) renderTableHeader(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
+ if entering {
+ _, _ = w.WriteString("\n")
+ _, _ = w.WriteString("\n") // Header has no separate handle
+ } else {
+ _, _ = w.WriteString(" \n")
+ _, _ = w.WriteString(" \n")
+ if n.NextSibling() != nil {
+ _, _ = w.WriteString(" \n")
+ }
+ }
+ return gast.WalkContinue, nil
+}
+
+// TableRowAttributeFilter defines attribute names which elements can have.
+var TableRowAttributeFilter = html.GlobalAttributeFilter.Extend(
+ []byte("align"), // [Obsolete since HTML5]
+ []byte("bgcolor"), // [Obsolete since HTML5]
+ []byte("char"), // [Obsolete since HTML5]
+ []byte("charoff"), // [Obsolete since HTML5]
+ []byte("valign"), // [Obsolete since HTML5]
+)
+
+func (r *TableHTMLRenderer) renderTableRow(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
+ if entering {
+ _, _ = w.WriteString(" \n")
+ } else {
+ _, _ = w.WriteString(" \n")
+ if n.Parent().LastChild() == n {
+ _, _ = w.WriteString(" \n")
+ }
+ }
+ return gast.WalkContinue, nil
+}
+
+// TableThCellAttributeFilter defines attribute names which table cells can have.
+var TableThCellAttributeFilter = html.GlobalAttributeFilter.Extend(
+ []byte("abbr"), // [OK] Contains a short abbreviated description of the cell's content [NOT OK in ]
+
+ []byte("align"), // [Obsolete since HTML5]
+ []byte("axis"), // [Obsolete since HTML5]
+ []byte("bgcolor"), // [Not Standardized]
+ []byte("char"), // [Obsolete since HTML5]
+ []byte("charoff"), // [Obsolete since HTML5]
+
+ []byte("colspan"), // [OK] Number of columns that the cell is to span
+ []byte("headers"), // [OK] This attribute contains a list of space-separated strings, each corresponding to the id attribute of the elements that apply to this element
+
+ []byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5]
+
+ []byte("rowspan"), // [OK] Number of rows that the cell is to span
+ []byte("scope"), // [OK] This enumerated attribute defines the cells that the header (defined in the ) element relates to [NOT OK in ]
+
+ []byte("valign"), // [Obsolete since HTML5]
+ []byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
+)
+
+// TableTdCellAttributeFilter defines attribute names which table cells can have.
+var TableTdCellAttributeFilter = html.GlobalAttributeFilter.Extend(
+ []byte("abbr"), // [Obsolete since HTML5] [OK in ]
+ []byte("align"), // [Obsolete since HTML5]
+ []byte("axis"), // [Obsolete since HTML5]
+ []byte("bgcolor"), // [Not Standardized]
+ []byte("char"), // [Obsolete since HTML5]
+ []byte("charoff"), // [Obsolete since HTML5]
+
+ []byte("colspan"), // [OK] Number of columns that the cell is to span
+ []byte("headers"), // [OK] This attribute contains a list of space-separated strings, each corresponding to the id attribute of the elements that apply to this element
+
+ []byte("height"), // [Deprecated since HTML4] [Obsolete since HTML5]
+
+ []byte("rowspan"), // [OK] Number of rows that the cell is to span
+
+ []byte("scope"), // [Obsolete since HTML5] [OK in ]
+ []byte("valign"), // [Obsolete since HTML5]
+ []byte("width"), // [Deprecated since HTML4] [Obsolete since HTML5]
+)
+
+func (r *TableHTMLRenderer) renderTableCell(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
+ n := node.(*ast.TableCell)
+ tag := "td"
+ if n.Parent().Kind() == ast.KindTableHeader {
+ tag = "th"
+ }
+ if entering {
+ fmt.Fprintf(w, "<%s", tag)
+ if n.Alignment != ast.AlignNone {
+ amethod := r.TableConfig.TableCellAlignMethod
+ if amethod == TableCellAlignDefault {
+ if r.Config.XHTML {
+ amethod = TableCellAlignAttribute
+ } else {
+ amethod = TableCellAlignStyle
+ }
+ }
+ switch amethod {
+ case TableCellAlignAttribute:
+ if _, ok := n.AttributeString("align"); !ok { // Skip align render if overridden
+ fmt.Fprintf(w, ` align="%s"`, n.Alignment.String())
+ }
+ case TableCellAlignStyle:
+ v, ok := n.AttributeString("style")
+ var cob util.CopyOnWriteBuffer
+ if ok {
+ cob = util.NewCopyOnWriteBuffer(v.([]byte))
+ cob.AppendByte(';')
+ }
+ style := fmt.Sprintf("text-align:%s", n.Alignment.String())
+ cob.AppendString(style)
+ n.SetAttributeString("style", cob.Bytes())
+ }
+ }
+ if n.Attributes() != nil {
+ if tag == "td" {
+ html.RenderAttributes(w, n, TableTdCellAttributeFilter) //
+ } else {
+ html.RenderAttributes(w, n, TableThCellAttributeFilter) //
+ }
+ }
+ _ = w.WriteByte('>')
+ } else {
+ fmt.Fprintf(w, "%s>\n", tag)
+ }
+ return gast.WalkContinue, nil
+}
+
+type table struct {
+ options []TableOption
+}
+
+// Table is an extension that allow you to use GFM tables .
+var Table = &table{
+ options: []TableOption{},
+}
+
+// NewTable returns a new extension with given options.
+func NewTable(opts ...TableOption) goldmark.Extender {
+ return &table{
+ options: opts,
+ }
+}
+
+func (e *table) Extend(m goldmark.Markdown) {
+ m.Parser().AddOptions(
+ parser.WithParagraphTransformers(
+ util.Prioritized(NewTableParagraphTransformer(), 200),
+ ),
+ parser.WithASTTransformers(
+ util.Prioritized(defaultTableASTTransformer, 0),
+ ),
+ )
+ m.Renderer().AddOptions(renderer.WithNodeRenderers(
+ util.Prioritized(NewTableHTMLRenderer(e.options...), 500),
+ ))
+}
diff --git a/vendor/github.com/yuin/goldmark/extension/tasklist.go b/vendor/github.com/yuin/goldmark/extension/tasklist.go
new file mode 100644
index 0000000..1f3e52c
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/tasklist.go
@@ -0,0 +1,115 @@
+package extension
+
+import (
+ "github.com/yuin/goldmark"
+ gast "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/extension/ast"
+ "github.com/yuin/goldmark/parser"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+ "regexp"
+)
+
+var taskListRegexp = regexp.MustCompile(`^\[([\sxX])\]\s*`)
+
+type taskCheckBoxParser struct {
+}
+
+var defaultTaskCheckBoxParser = &taskCheckBoxParser{}
+
+// NewTaskCheckBoxParser returns a new InlineParser that can parse
+// checkboxes in list items.
+// This parser must take precedence over the parser.LinkParser.
+func NewTaskCheckBoxParser() parser.InlineParser {
+ return defaultTaskCheckBoxParser
+}
+
+func (s *taskCheckBoxParser) Trigger() []byte {
+ return []byte{'['}
+}
+
+func (s *taskCheckBoxParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
+ // Given AST structure must be like
+ // - List
+ // - ListItem : parent.Parent
+ // - TextBlock : parent
+ // (current line)
+ if parent.Parent() == nil || parent.Parent().FirstChild() != parent {
+ return nil
+ }
+
+ if _, ok := parent.Parent().(*gast.ListItem); !ok {
+ return nil
+ }
+ line, _ := block.PeekLine()
+ m := taskListRegexp.FindSubmatchIndex(line)
+ if m == nil {
+ return nil
+ }
+ value := line[m[2]:m[3]][0]
+ block.Advance(m[1])
+ checked := value == 'x' || value == 'X'
+ return ast.NewTaskCheckBox(checked)
+}
+
+func (s *taskCheckBoxParser) CloseBlock(parent gast.Node, pc parser.Context) {
+ // nothing to do
+}
+
+// TaskCheckBoxHTMLRenderer is a renderer.NodeRenderer implementation that
+// renders checkboxes in list items.
+type TaskCheckBoxHTMLRenderer struct {
+ html.Config
+}
+
+// NewTaskCheckBoxHTMLRenderer returns a new TaskCheckBoxHTMLRenderer.
+func NewTaskCheckBoxHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
+ r := &TaskCheckBoxHTMLRenderer{
+ Config: html.NewConfig(),
+ }
+ for _, opt := range opts {
+ opt.SetHTMLOption(&r.Config)
+ }
+ return r
+}
+
+// RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
+func (r *TaskCheckBoxHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
+ reg.Register(ast.KindTaskCheckBox, r.renderTaskCheckBox)
+}
+
+func (r *TaskCheckBoxHTMLRenderer) renderTaskCheckBox(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
+ if !entering {
+ return gast.WalkContinue, nil
+ }
+ n := node.(*ast.TaskCheckBox)
+
+ if n.IsChecked {
+ w.WriteString(` ")
+ } else {
+ w.WriteString("> ")
+ }
+ return gast.WalkContinue, nil
+}
+
+type taskList struct {
+}
+
+// TaskList is an extension that allow you to use GFM task lists.
+var TaskList = &taskList{}
+
+func (e *taskList) Extend(m goldmark.Markdown) {
+ m.Parser().AddOptions(parser.WithInlineParsers(
+ util.Prioritized(NewTaskCheckBoxParser(), 0),
+ ))
+ m.Renderer().AddOptions(renderer.WithNodeRenderers(
+ util.Prioritized(NewTaskCheckBoxHTMLRenderer(), 500),
+ ))
+}
diff --git a/vendor/github.com/yuin/goldmark/extension/typographer.go b/vendor/github.com/yuin/goldmark/extension/typographer.go
new file mode 100644
index 0000000..f56c06f
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/extension/typographer.go
@@ -0,0 +1,339 @@
+package extension
+
+import (
+ "unicode"
+
+ "github.com/yuin/goldmark"
+ gast "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/parser"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+var uncloseCounterKey = parser.NewContextKey()
+
+type unclosedCounter struct {
+ Single int
+ Double int
+}
+
+func (u *unclosedCounter) Reset() {
+ u.Single = 0
+ u.Double = 0
+}
+
+func getUnclosedCounter(pc parser.Context) *unclosedCounter {
+ v := pc.Get(uncloseCounterKey)
+ if v == nil {
+ v = &unclosedCounter{}
+ pc.Set(uncloseCounterKey, v)
+ }
+ return v.(*unclosedCounter)
+}
+
+// TypographicPunctuation is a key of the punctuations that can be replaced with
+// typographic entities.
+type TypographicPunctuation int
+
+const (
+ // LeftSingleQuote is '
+ LeftSingleQuote TypographicPunctuation = iota + 1
+ // RightSingleQuote is '
+ RightSingleQuote
+ // LeftDoubleQuote is "
+ LeftDoubleQuote
+ // RightDoubleQuote is "
+ RightDoubleQuote
+ // EnDash is --
+ EnDash
+ // EmDash is ---
+ EmDash
+ // Ellipsis is ...
+ Ellipsis
+ // LeftAngleQuote is <<
+ LeftAngleQuote
+ // RightAngleQuote is >>
+ RightAngleQuote
+ // Apostrophe is '
+ Apostrophe
+
+ typographicPunctuationMax
+)
+
+// An TypographerConfig struct is a data structure that holds configuration of the
+// Typographer extension.
+type TypographerConfig struct {
+ Substitutions [][]byte
+}
+
+func newDefaultSubstitutions() [][]byte {
+ replacements := make([][]byte, typographicPunctuationMax)
+ replacements[LeftSingleQuote] = []byte("‘")
+ replacements[RightSingleQuote] = []byte("’")
+ replacements[LeftDoubleQuote] = []byte("“")
+ replacements[RightDoubleQuote] = []byte("”")
+ replacements[EnDash] = []byte("–")
+ replacements[EmDash] = []byte("—")
+ replacements[Ellipsis] = []byte("…")
+ replacements[LeftAngleQuote] = []byte("«")
+ replacements[RightAngleQuote] = []byte("»")
+ replacements[Apostrophe] = []byte("’")
+
+ return replacements
+}
+
+// SetOption implements SetOptioner.
+func (b *TypographerConfig) SetOption(name parser.OptionName, value interface{}) {
+ switch name {
+ case optTypographicSubstitutions:
+ b.Substitutions = value.([][]byte)
+ }
+}
+
+// A TypographerOption interface sets options for the TypographerParser.
+type TypographerOption interface {
+ parser.Option
+ SetTypographerOption(*TypographerConfig)
+}
+
+const optTypographicSubstitutions parser.OptionName = "TypographicSubstitutions"
+
+// TypographicSubstitutions is a list of the substitutions for the Typographer extension.
+type TypographicSubstitutions map[TypographicPunctuation][]byte
+
+type withTypographicSubstitutions struct {
+ value [][]byte
+}
+
+func (o *withTypographicSubstitutions) SetParserOption(c *parser.Config) {
+ c.Options[optTypographicSubstitutions] = o.value
+}
+
+func (o *withTypographicSubstitutions) SetTypographerOption(p *TypographerConfig) {
+ p.Substitutions = o.value
+}
+
+// WithTypographicSubstitutions is a functional otpion that specify replacement text
+// for punctuations.
+func WithTypographicSubstitutions(values map[TypographicPunctuation][]byte) TypographerOption {
+ replacements := newDefaultSubstitutions()
+ for k, v := range values {
+ replacements[k] = v
+ }
+
+ return &withTypographicSubstitutions{replacements}
+}
+
+type typographerDelimiterProcessor struct {
+}
+
+func (p *typographerDelimiterProcessor) IsDelimiter(b byte) bool {
+ return b == '\'' || b == '"'
+}
+
+func (p *typographerDelimiterProcessor) CanOpenCloser(opener, closer *parser.Delimiter) bool {
+ return opener.Char == closer.Char
+}
+
+func (p *typographerDelimiterProcessor) OnMatch(consumes int) gast.Node {
+ return nil
+}
+
+var defaultTypographerDelimiterProcessor = &typographerDelimiterProcessor{}
+
+type typographerParser struct {
+ TypographerConfig
+}
+
+// NewTypographerParser return a new InlineParser that parses
+// typographer expressions.
+func NewTypographerParser(opts ...TypographerOption) parser.InlineParser {
+ p := &typographerParser{
+ TypographerConfig: TypographerConfig{
+ Substitutions: newDefaultSubstitutions(),
+ },
+ }
+ for _, o := range opts {
+ o.SetTypographerOption(&p.TypographerConfig)
+ }
+ return p
+}
+
+func (s *typographerParser) Trigger() []byte {
+ return []byte{'\'', '"', '-', '.', ',', '<', '>', '*', '['}
+}
+
+func (s *typographerParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
+ line, _ := block.PeekLine()
+ c := line[0]
+ if len(line) > 2 {
+ if c == '-' {
+ if s.Substitutions[EmDash] != nil && line[1] == '-' && line[2] == '-' { // ---
+ node := gast.NewString(s.Substitutions[EmDash])
+ node.SetCode(true)
+ block.Advance(3)
+ return node
+ }
+ } else if c == '.' {
+ if s.Substitutions[Ellipsis] != nil && line[1] == '.' && line[2] == '.' { // ...
+ node := gast.NewString(s.Substitutions[Ellipsis])
+ node.SetCode(true)
+ block.Advance(3)
+ return node
+ }
+ return nil
+ }
+ }
+ if len(line) > 1 {
+ if c == '<' {
+ if s.Substitutions[LeftAngleQuote] != nil && line[1] == '<' { // <<
+ node := gast.NewString(s.Substitutions[LeftAngleQuote])
+ node.SetCode(true)
+ block.Advance(2)
+ return node
+ }
+ return nil
+ } else if c == '>' {
+ if s.Substitutions[RightAngleQuote] != nil && line[1] == '>' { // >>
+ node := gast.NewString(s.Substitutions[RightAngleQuote])
+ node.SetCode(true)
+ block.Advance(2)
+ return node
+ }
+ return nil
+ } else if s.Substitutions[EnDash] != nil && c == '-' && line[1] == '-' { // --
+ node := gast.NewString(s.Substitutions[EnDash])
+ node.SetCode(true)
+ block.Advance(2)
+ return node
+ }
+ }
+ if c == '\'' || c == '"' {
+ before := block.PrecendingCharacter()
+ d := parser.ScanDelimiter(line, before, 1, defaultTypographerDelimiterProcessor)
+ if d == nil {
+ return nil
+ }
+ counter := getUnclosedCounter(pc)
+ if c == '\'' {
+ if s.Substitutions[Apostrophe] != nil {
+ // Handle decade abbrevations such as '90s
+ if d.CanOpen && !d.CanClose && len(line) > 3 && util.IsNumeric(line[1]) && util.IsNumeric(line[2]) && line[3] == 's' {
+ after := rune(' ')
+ if len(line) > 4 {
+ after = util.ToRune(line, 4)
+ }
+ if len(line) == 3 || util.IsSpaceRune(after) || util.IsPunctRune(after) {
+ node := gast.NewString(s.Substitutions[Apostrophe])
+ node.SetCode(true)
+ block.Advance(1)
+ return node
+ }
+ }
+ // special cases: 'twas, 'em, 'net
+ if len(line) > 1 && (unicode.IsPunct(before) || unicode.IsSpace(before)) && (line[1] == 't' || line[1] == 'e' || line[1] == 'n' || line[1] == 'l') {
+ node := gast.NewString(s.Substitutions[Apostrophe])
+ node.SetCode(true)
+ block.Advance(1)
+ return node
+ }
+ // Convert normal apostrophes. This is probably more flexible than necessary but
+ // converts any apostrophe in between two alphanumerics.
+ if len(line) > 1 && (unicode.IsDigit(before) || unicode.IsLetter(before)) && (unicode.IsLetter(util.ToRune(line, 1))) {
+ node := gast.NewString(s.Substitutions[Apostrophe])
+ node.SetCode(true)
+ block.Advance(1)
+ return node
+ }
+ }
+ if s.Substitutions[LeftSingleQuote] != nil && d.CanOpen && !d.CanClose {
+ nt := LeftSingleQuote
+ // special cases: Alice's, I'm, Don't, You'd
+ if len(line) > 1 && (line[1] == 's' || line[1] == 'm' || line[1] == 't' || line[1] == 'd') && (len(line) < 3 || util.IsPunct(line[2]) || util.IsSpace(line[2])) {
+ nt = RightSingleQuote
+ }
+ // special cases: I've, I'll, You're
+ if len(line) > 2 && ((line[1] == 'v' && line[2] == 'e') || (line[1] == 'l' && line[2] == 'l') || (line[1] == 'r' && line[2] == 'e')) && (len(line) < 4 || util.IsPunct(line[3]) || util.IsSpace(line[3])) {
+ nt = RightSingleQuote
+ }
+ if nt == LeftSingleQuote {
+ counter.Single++
+ }
+
+ node := gast.NewString(s.Substitutions[nt])
+ node.SetCode(true)
+ block.Advance(1)
+ return node
+ }
+ if s.Substitutions[RightSingleQuote] != nil {
+ // plural possesives and abbreviations: Smiths', doin'
+ if len(line) > 1 && unicode.IsSpace(util.ToRune(line, 0)) || unicode.IsPunct(util.ToRune(line, 0)) && (len(line) > 2 && !unicode.IsDigit(util.ToRune(line, 1))) {
+ node := gast.NewString(s.Substitutions[RightSingleQuote])
+ node.SetCode(true)
+ block.Advance(1)
+ return node
+ }
+ }
+ if s.Substitutions[RightSingleQuote] != nil && counter.Single > 0 {
+ isClose := d.CanClose && !d.CanOpen
+ maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && unicode.IsPunct(util.ToRune(line, 1)) && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2])))
+ if isClose || maybeClose {
+ node := gast.NewString(s.Substitutions[RightSingleQuote])
+ node.SetCode(true)
+ block.Advance(1)
+ counter.Single--
+ return node
+ }
+ }
+ }
+ if c == '"' {
+ if s.Substitutions[LeftDoubleQuote] != nil && d.CanOpen && !d.CanClose {
+ node := gast.NewString(s.Substitutions[LeftDoubleQuote])
+ node.SetCode(true)
+ block.Advance(1)
+ counter.Double++
+ return node
+ }
+ if s.Substitutions[RightDoubleQuote] != nil && counter.Double > 0 {
+ isClose := d.CanClose && !d.CanOpen
+ maybeClose := d.CanClose && d.CanOpen && len(line) > 1 && (unicode.IsPunct(util.ToRune(line, 1))) && (len(line) == 2 || (len(line) > 2 && util.IsPunct(line[2]) || util.IsSpace(line[2])))
+ if isClose || maybeClose {
+ // special case: "Monitor 21""
+ if len(line) > 1 && line[1] == '"' && unicode.IsDigit(before) {
+ return nil
+ }
+ node := gast.NewString(s.Substitutions[RightDoubleQuote])
+ node.SetCode(true)
+ block.Advance(1)
+ counter.Double--
+ return node
+ }
+ }
+ }
+ }
+ return nil
+}
+
+func (s *typographerParser) CloseBlock(parent gast.Node, pc parser.Context) {
+ getUnclosedCounter(pc).Reset()
+}
+
+type typographer struct {
+ options []TypographerOption
+}
+
+// Typographer is an extension that replaces punctuations with typographic entities.
+var Typographer = &typographer{}
+
+// NewTypographer returns a new Extender that replaces punctuations with typographic entities.
+func NewTypographer(opts ...TypographerOption) goldmark.Extender {
+ return &typographer{
+ options: opts,
+ }
+}
+
+func (e *typographer) Extend(m goldmark.Markdown) {
+ m.Parser().AddOptions(parser.WithInlineParsers(
+ util.Prioritized(NewTypographerParser(e.options...), 9999),
+ ))
+}
diff --git a/vendor/github.com/yuin/goldmark/markdown.go b/vendor/github.com/yuin/goldmark/markdown.go
new file mode 100644
index 0000000..86d12e2
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/markdown.go
@@ -0,0 +1,140 @@
+// Package goldmark implements functions to convert markdown text to a desired format.
+package goldmark
+
+import (
+ "github.com/yuin/goldmark/parser"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/renderer/html"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+ "io"
+)
+
+// DefaultParser returns a new Parser that is configured by default values.
+func DefaultParser() parser.Parser {
+ return parser.NewParser(parser.WithBlockParsers(parser.DefaultBlockParsers()...),
+ parser.WithInlineParsers(parser.DefaultInlineParsers()...),
+ parser.WithParagraphTransformers(parser.DefaultParagraphTransformers()...),
+ )
+}
+
+// DefaultRenderer returns a new Renderer that is configured by default values.
+func DefaultRenderer() renderer.Renderer {
+ return renderer.NewRenderer(renderer.WithNodeRenderers(util.Prioritized(html.NewRenderer(), 1000)))
+}
+
+var defaultMarkdown = New()
+
+// Convert interprets a UTF-8 bytes source in Markdown and
+// write rendered contents to a writer w.
+func Convert(source []byte, w io.Writer, opts ...parser.ParseOption) error {
+ return defaultMarkdown.Convert(source, w, opts...)
+}
+
+// A Markdown interface offers functions to convert Markdown text to
+// a desired format.
+type Markdown interface {
+ // Convert interprets a UTF-8 bytes source in Markdown and write rendered
+ // contents to a writer w.
+ Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error
+
+ // Parser returns a Parser that will be used for conversion.
+ Parser() parser.Parser
+
+ // SetParser sets a Parser to this object.
+ SetParser(parser.Parser)
+
+ // Parser returns a Renderer that will be used for conversion.
+ Renderer() renderer.Renderer
+
+ // SetRenderer sets a Renderer to this object.
+ SetRenderer(renderer.Renderer)
+}
+
+// Option is a functional option type for Markdown objects.
+type Option func(*markdown)
+
+// WithExtensions adds extensions.
+func WithExtensions(ext ...Extender) Option {
+ return func(m *markdown) {
+ m.extensions = append(m.extensions, ext...)
+ }
+}
+
+// WithParser allows you to override the default parser.
+func WithParser(p parser.Parser) Option {
+ return func(m *markdown) {
+ m.parser = p
+ }
+}
+
+// WithParserOptions applies options for the parser.
+func WithParserOptions(opts ...parser.Option) Option {
+ return func(m *markdown) {
+ m.parser.AddOptions(opts...)
+ }
+}
+
+// WithRenderer allows you to override the default renderer.
+func WithRenderer(r renderer.Renderer) Option {
+ return func(m *markdown) {
+ m.renderer = r
+ }
+}
+
+// WithRendererOptions applies options for the renderer.
+func WithRendererOptions(opts ...renderer.Option) Option {
+ return func(m *markdown) {
+ m.renderer.AddOptions(opts...)
+ }
+}
+
+type markdown struct {
+ parser parser.Parser
+ renderer renderer.Renderer
+ extensions []Extender
+}
+
+// New returns a new Markdown with given options.
+func New(options ...Option) Markdown {
+ md := &markdown{
+ parser: DefaultParser(),
+ renderer: DefaultRenderer(),
+ extensions: []Extender{},
+ }
+ for _, opt := range options {
+ opt(md)
+ }
+ for _, e := range md.extensions {
+ e.Extend(md)
+ }
+ return md
+}
+
+func (m *markdown) Convert(source []byte, writer io.Writer, opts ...parser.ParseOption) error {
+ reader := text.NewReader(source)
+ doc := m.parser.Parse(reader, opts...)
+ return m.renderer.Render(writer, source, doc)
+}
+
+func (m *markdown) Parser() parser.Parser {
+ return m.parser
+}
+
+func (m *markdown) SetParser(v parser.Parser) {
+ m.parser = v
+}
+
+func (m *markdown) Renderer() renderer.Renderer {
+ return m.renderer
+}
+
+func (m *markdown) SetRenderer(v renderer.Renderer) {
+ m.renderer = v
+}
+
+// An Extender interface is used for extending Markdown.
+type Extender interface {
+ // Extend extends the Markdown.
+ Extend(Markdown)
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/attribute.go b/vendor/github.com/yuin/goldmark/parser/attribute.go
new file mode 100644
index 0000000..f86c836
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/attribute.go
@@ -0,0 +1,328 @@
+package parser
+
+import (
+ "bytes"
+ "io"
+ "strconv"
+
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+var attrNameID = []byte("id")
+var attrNameClass = []byte("class")
+
+// An Attribute is an attribute of the markdown elements
+type Attribute struct {
+ Name []byte
+ Value interface{}
+}
+
+// An Attributes is a collection of attributes.
+type Attributes []Attribute
+
+// Find returns a (value, true) if an attribute correspond with given name is found, otherwise (nil, false).
+func (as Attributes) Find(name []byte) (interface{}, bool) {
+ for _, a := range as {
+ if bytes.Equal(a.Name, name) {
+ return a.Value, true
+ }
+ }
+ return nil, false
+}
+
+func (as Attributes) findUpdate(name []byte, cb func(v interface{}) interface{}) bool {
+ for i, a := range as {
+ if bytes.Equal(a.Name, name) {
+ as[i].Value = cb(a.Value)
+ return true
+ }
+ }
+ return false
+}
+
+// ParseAttributes parses attributes into a map.
+// ParseAttributes returns a parsed attributes and true if could parse
+// attributes, otherwise nil and false.
+func ParseAttributes(reader text.Reader) (Attributes, bool) {
+ savedLine, savedPosition := reader.Position()
+ reader.SkipSpaces()
+ if reader.Peek() != '{' {
+ reader.SetPosition(savedLine, savedPosition)
+ return nil, false
+ }
+ reader.Advance(1)
+ attrs := Attributes{}
+ for {
+ if reader.Peek() == '}' {
+ reader.Advance(1)
+ return attrs, true
+ }
+ attr, ok := parseAttribute(reader)
+ if !ok {
+ reader.SetPosition(savedLine, savedPosition)
+ return nil, false
+ }
+ if bytes.Equal(attr.Name, attrNameClass) {
+ if !attrs.findUpdate(attrNameClass, func(v interface{}) interface{} {
+ ret := make([]byte, 0, len(v.([]byte))+1+len(attr.Value.([]byte)))
+ ret = append(ret, v.([]byte)...)
+ return append(append(ret, ' '), attr.Value.([]byte)...)
+ }) {
+ attrs = append(attrs, attr)
+ }
+ } else {
+ attrs = append(attrs, attr)
+ }
+ reader.SkipSpaces()
+ if reader.Peek() == ',' {
+ reader.Advance(1)
+ reader.SkipSpaces()
+ }
+ }
+}
+
+func parseAttribute(reader text.Reader) (Attribute, bool) {
+ reader.SkipSpaces()
+ c := reader.Peek()
+ if c == '#' || c == '.' {
+ reader.Advance(1)
+ line, _ := reader.PeekLine()
+ i := 0
+ // HTML5 allows any kind of characters as id, but XHTML restricts characters for id.
+ // CommonMark is basically defined for XHTML(even though it is legacy).
+ // So we restrict id characters.
+ for ; i < len(line) && !util.IsSpace(line[i]) &&
+ (!util.IsPunct(line[i]) || line[i] == '_' || line[i] == '-' || line[i] == ':' || line[i] == '.'); i++ {
+ }
+ name := attrNameClass
+ if c == '#' {
+ name = attrNameID
+ }
+ reader.Advance(i)
+ return Attribute{Name: name, Value: line[0:i]}, true
+ }
+ line, _ := reader.PeekLine()
+ if len(line) == 0 {
+ return Attribute{}, false
+ }
+ c = line[0]
+ if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ c == '_' || c == ':') {
+ return Attribute{}, false
+ }
+ i := 0
+ for ; i < len(line); i++ {
+ c = line[i]
+ if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ c == '_' || c == ':' || c == '.' || c == '-') {
+ break
+ }
+ }
+ name := line[:i]
+ reader.Advance(i)
+ reader.SkipSpaces()
+ c = reader.Peek()
+ if c != '=' {
+ return Attribute{}, false
+ }
+ reader.Advance(1)
+ reader.SkipSpaces()
+ value, ok := parseAttributeValue(reader)
+ if !ok {
+ return Attribute{}, false
+ }
+ if bytes.Equal(name, attrNameClass) {
+ if _, ok = value.([]byte); !ok {
+ return Attribute{}, false
+ }
+ }
+ return Attribute{Name: name, Value: value}, true
+}
+
+func parseAttributeValue(reader text.Reader) (interface{}, bool) {
+ reader.SkipSpaces()
+ c := reader.Peek()
+ var value interface{}
+ ok := false
+ switch c {
+ case text.EOF:
+ return Attribute{}, false
+ case '{':
+ value, ok = ParseAttributes(reader)
+ case '[':
+ value, ok = parseAttributeArray(reader)
+ case '"':
+ value, ok = parseAttributeString(reader)
+ default:
+ if c == '-' || c == '+' || util.IsNumeric(c) {
+ value, ok = parseAttributeNumber(reader)
+ } else {
+ value, ok = parseAttributeOthers(reader)
+ }
+ }
+ if !ok {
+ return nil, false
+ }
+ return value, true
+}
+
+func parseAttributeArray(reader text.Reader) ([]interface{}, bool) {
+ reader.Advance(1) // skip [
+ ret := []interface{}{}
+ for i := 0; ; i++ {
+ c := reader.Peek()
+ comma := false
+ if i != 0 && c == ',' {
+ reader.Advance(1)
+ comma = true
+ }
+ if c == ']' {
+ if !comma {
+ reader.Advance(1)
+ return ret, true
+ }
+ return nil, false
+ }
+ reader.SkipSpaces()
+ value, ok := parseAttributeValue(reader)
+ if !ok {
+ return nil, false
+ }
+ ret = append(ret, value)
+ reader.SkipSpaces()
+ }
+}
+
+func parseAttributeString(reader text.Reader) ([]byte, bool) {
+ reader.Advance(1) // skip "
+ line, _ := reader.PeekLine()
+ i := 0
+ l := len(line)
+ var buf bytes.Buffer
+ for i < l {
+ c := line[i]
+ if c == '\\' && i != l-1 {
+ n := line[i+1]
+ switch n {
+ case '"', '/', '\\':
+ buf.WriteByte(n)
+ i += 2
+ case 'b':
+ buf.WriteString("\b")
+ i += 2
+ case 'f':
+ buf.WriteString("\f")
+ i += 2
+ case 'n':
+ buf.WriteString("\n")
+ i += 2
+ case 'r':
+ buf.WriteString("\r")
+ i += 2
+ case 't':
+ buf.WriteString("\t")
+ i += 2
+ default:
+ buf.WriteByte('\\')
+ i++
+ }
+ continue
+ }
+ if c == '"' {
+ reader.Advance(i + 1)
+ return buf.Bytes(), true
+ }
+ buf.WriteByte(c)
+ i++
+ }
+ return nil, false
+}
+
+func scanAttributeDecimal(reader text.Reader, w io.ByteWriter) {
+ for {
+ c := reader.Peek()
+ if util.IsNumeric(c) {
+ w.WriteByte(c)
+ } else {
+ return
+ }
+ reader.Advance(1)
+ }
+}
+
+func parseAttributeNumber(reader text.Reader) (float64, bool) {
+ sign := 1
+ c := reader.Peek()
+ if c == '-' {
+ sign = -1
+ reader.Advance(1)
+ } else if c == '+' {
+ reader.Advance(1)
+ }
+ var buf bytes.Buffer
+ if !util.IsNumeric(reader.Peek()) {
+ return 0, false
+ }
+ scanAttributeDecimal(reader, &buf)
+ if buf.Len() == 0 {
+ return 0, false
+ }
+ c = reader.Peek()
+ if c == '.' {
+ buf.WriteByte(c)
+ reader.Advance(1)
+ scanAttributeDecimal(reader, &buf)
+ }
+ c = reader.Peek()
+ if c == 'e' || c == 'E' {
+ buf.WriteByte(c)
+ reader.Advance(1)
+ c = reader.Peek()
+ if c == '-' || c == '+' {
+ buf.WriteByte(c)
+ reader.Advance(1)
+ }
+ scanAttributeDecimal(reader, &buf)
+ }
+ f, err := strconv.ParseFloat(buf.String(), 10)
+ if err != nil {
+ return 0, false
+ }
+ return float64(sign) * f, true
+}
+
+var bytesTrue = []byte("true")
+var bytesFalse = []byte("false")
+var bytesNull = []byte("null")
+
+func parseAttributeOthers(reader text.Reader) (interface{}, bool) {
+ line, _ := reader.PeekLine()
+ c := line[0]
+ if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ c == '_' || c == ':') {
+ return nil, false
+ }
+ i := 0
+ for ; i < len(line); i++ {
+ c := line[i]
+ if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ c == '_' || c == ':' || c == '.' || c == '-') {
+ break
+ }
+ }
+ value := line[:i]
+ reader.Advance(i)
+ if bytes.Equal(value, bytesTrue) {
+ return true, true
+ }
+ if bytes.Equal(value, bytesFalse) {
+ return false, true
+ }
+ if bytes.Equal(value, bytesNull) {
+ return nil, true
+ }
+ return value, true
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/atx_heading.go b/vendor/github.com/yuin/goldmark/parser/atx_heading.go
new file mode 100644
index 0000000..13a198b
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/atx_heading.go
@@ -0,0 +1,246 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+// A HeadingConfig struct is a data structure that holds configuration of the renderers related to headings.
+type HeadingConfig struct {
+ AutoHeadingID bool
+ Attribute bool
+}
+
+// SetOption implements SetOptioner.
+func (b *HeadingConfig) SetOption(name OptionName, value interface{}) {
+ switch name {
+ case optAutoHeadingID:
+ b.AutoHeadingID = true
+ case optAttribute:
+ b.Attribute = true
+ }
+}
+
+// A HeadingOption interface sets options for heading parsers.
+type HeadingOption interface {
+ Option
+ SetHeadingOption(*HeadingConfig)
+}
+
+// AutoHeadingID is an option name that enables auto IDs for headings.
+const optAutoHeadingID OptionName = "AutoHeadingID"
+
+type withAutoHeadingID struct {
+}
+
+func (o *withAutoHeadingID) SetParserOption(c *Config) {
+ c.Options[optAutoHeadingID] = true
+}
+
+func (o *withAutoHeadingID) SetHeadingOption(p *HeadingConfig) {
+ p.AutoHeadingID = true
+}
+
+// WithAutoHeadingID is a functional option that enables custom heading ids and
+// auto generated heading ids.
+func WithAutoHeadingID() HeadingOption {
+ return &withAutoHeadingID{}
+}
+
+type withHeadingAttribute struct {
+ Option
+}
+
+func (o *withHeadingAttribute) SetHeadingOption(p *HeadingConfig) {
+ p.Attribute = true
+}
+
+// WithHeadingAttribute is a functional option that enables custom heading attributes.
+func WithHeadingAttribute() HeadingOption {
+ return &withHeadingAttribute{WithAttribute()}
+}
+
+type atxHeadingParser struct {
+ HeadingConfig
+}
+
+// NewATXHeadingParser return a new BlockParser that can parse ATX headings.
+func NewATXHeadingParser(opts ...HeadingOption) BlockParser {
+ p := &atxHeadingParser{}
+ for _, o := range opts {
+ o.SetHeadingOption(&p.HeadingConfig)
+ }
+ return p
+}
+
+func (b *atxHeadingParser) Trigger() []byte {
+ return []byte{'#'}
+}
+
+func (b *atxHeadingParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ line, segment := reader.PeekLine()
+ pos := pc.BlockOffset()
+ if pos < 0 {
+ return nil, NoChildren
+ }
+ i := pos
+ for ; i < len(line) && line[i] == '#'; i++ {
+ }
+ level := i - pos
+ if i == pos || level > 6 {
+ return nil, NoChildren
+ }
+ if i == len(line) { // alone '#' (without a new line character)
+ return ast.NewHeading(level), NoChildren
+ }
+ l := util.TrimLeftSpaceLength(line[i:])
+ if l == 0 {
+ return nil, NoChildren
+ }
+ start := i + l
+ if start >= len(line) {
+ start = len(line) - 1
+ }
+ origstart := start
+ stop := len(line) - util.TrimRightSpaceLength(line)
+
+ node := ast.NewHeading(level)
+ parsed := false
+ if b.Attribute { // handles special case like ### heading ### {#id}
+ start--
+ closureClose := -1
+ closureOpen := -1
+ for j := start; j < stop; {
+ c := line[j]
+ if util.IsEscapedPunctuation(line, j) {
+ j += 2
+ } else if util.IsSpace(c) && j < stop-1 && line[j+1] == '#' {
+ closureOpen = j + 1
+ k := j + 1
+ for ; k < stop && line[k] == '#'; k++ {
+ }
+ closureClose = k
+ break
+ } else {
+ j++
+ }
+ }
+ if closureClose > 0 {
+ reader.Advance(closureClose)
+ attrs, ok := ParseAttributes(reader)
+ rest, _ := reader.PeekLine()
+ parsed = ok && util.IsBlank(rest)
+ if parsed {
+ for _, attr := range attrs {
+ node.SetAttribute(attr.Name, attr.Value)
+ }
+ node.Lines().Append(text.NewSegment(segment.Start+start+1-segment.Padding, segment.Start+closureOpen-segment.Padding))
+ }
+ }
+ }
+ if !parsed {
+ start = origstart
+ stop := len(line) - util.TrimRightSpaceLength(line)
+ if stop <= start { // empty headings like '##[space]'
+ stop = start
+ } else {
+ i = stop - 1
+ for ; line[i] == '#' && i >= start; i-- {
+ }
+ if i != stop-1 && !util.IsSpace(line[i]) {
+ i = stop - 1
+ }
+ i++
+ stop = i
+ }
+
+ if len(util.TrimRight(line[start:stop], []byte{'#'})) != 0 { // empty heading like '### ###'
+ node.Lines().Append(text.NewSegment(segment.Start+start-segment.Padding, segment.Start+stop-segment.Padding))
+ }
+ }
+ return node, NoChildren
+}
+
+func (b *atxHeadingParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ return Close
+}
+
+func (b *atxHeadingParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ if b.Attribute {
+ _, ok := node.AttributeString("id")
+ if !ok {
+ parseLastLineAttributes(node, reader, pc)
+ }
+ }
+
+ if b.AutoHeadingID {
+ id, ok := node.AttributeString("id")
+ if !ok {
+ generateAutoHeadingID(node.(*ast.Heading), reader, pc)
+ } else {
+ pc.IDs().Put(id.([]byte))
+ }
+ }
+}
+
+func (b *atxHeadingParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *atxHeadingParser) CanAcceptIndentedLine() bool {
+ return false
+}
+
+func generateAutoHeadingID(node *ast.Heading, reader text.Reader, pc Context) {
+ var line []byte
+ lastIndex := node.Lines().Len() - 1
+ if lastIndex > -1 {
+ lastLine := node.Lines().At(lastIndex)
+ line = lastLine.Value(reader.Source())
+ }
+ headingID := pc.IDs().Generate(line, ast.KindHeading)
+ node.SetAttribute(attrNameID, headingID)
+}
+
+func parseLastLineAttributes(node ast.Node, reader text.Reader, pc Context) {
+ lastIndex := node.Lines().Len() - 1
+ if lastIndex < 0 { // empty headings
+ return
+ }
+ lastLine := node.Lines().At(lastIndex)
+ line := lastLine.Value(reader.Source())
+ lr := text.NewReader(line)
+ var attrs Attributes
+ var ok bool
+ var start text.Segment
+ var sl int
+ var end text.Segment
+ for {
+ c := lr.Peek()
+ if c == text.EOF {
+ break
+ }
+ if c == '\\' {
+ lr.Advance(1)
+ if lr.Peek() == '{' {
+ lr.Advance(1)
+ }
+ continue
+ }
+ if c == '{' {
+ sl, start = lr.Position()
+ attrs, ok = ParseAttributes(lr)
+ _, end = lr.Position()
+ lr.SetPosition(sl, start)
+ }
+ lr.Advance(1)
+ }
+ if ok && util.IsBlank(line[end.Start:]) {
+ for _, attr := range attrs {
+ node.SetAttribute(attr.Name, attr.Value)
+ }
+ lastLine.Stop = lastLine.Start + start.Start
+ node.Lines().Set(lastIndex, lastLine)
+ }
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/auto_link.go b/vendor/github.com/yuin/goldmark/parser/auto_link.go
new file mode 100644
index 0000000..726a505
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/auto_link.go
@@ -0,0 +1,42 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type autoLinkParser struct {
+}
+
+var defaultAutoLinkParser = &autoLinkParser{}
+
+// NewAutoLinkParser returns a new InlineParser that parses autolinks
+// surrounded by '<' and '>' .
+func NewAutoLinkParser() InlineParser {
+ return defaultAutoLinkParser
+}
+
+func (s *autoLinkParser) Trigger() []byte {
+ return []byte{'<'}
+}
+
+func (s *autoLinkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
+ line, segment := block.PeekLine()
+ stop := util.FindEmailIndex(line[1:])
+ typ := ast.AutoLinkType(ast.AutoLinkEmail)
+ if stop < 0 {
+ stop = util.FindURLIndex(line[1:])
+ typ = ast.AutoLinkURL
+ }
+ if stop < 0 {
+ return nil
+ }
+ stop++
+ if stop >= len(line) || line[stop] != '>' {
+ return nil
+ }
+ value := ast.NewTextSegment(text.NewSegment(segment.Start+1, segment.Start+stop))
+ block.Advance(stop + 1)
+ return ast.NewAutoLink(typ, value)
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/blockquote.go b/vendor/github.com/yuin/goldmark/parser/blockquote.go
new file mode 100644
index 0000000..e7778dc
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/blockquote.go
@@ -0,0 +1,69 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type blockquoteParser struct {
+}
+
+var defaultBlockquoteParser = &blockquoteParser{}
+
+// NewBlockquoteParser returns a new BlockParser that
+// parses blockquotes.
+func NewBlockquoteParser() BlockParser {
+ return defaultBlockquoteParser
+}
+
+func (b *blockquoteParser) process(reader text.Reader) bool {
+ line, _ := reader.PeekLine()
+ w, pos := util.IndentWidth(line, reader.LineOffset())
+ if w > 3 || pos >= len(line) || line[pos] != '>' {
+ return false
+ }
+ pos++
+ if pos >= len(line) || line[pos] == '\n' {
+ reader.Advance(pos)
+ return true
+ }
+ if line[pos] == ' ' || line[pos] == '\t' {
+ pos++
+ }
+ reader.Advance(pos)
+ if line[pos-1] == '\t' {
+ reader.SetPadding(2)
+ }
+ return true
+}
+
+func (b *blockquoteParser) Trigger() []byte {
+ return []byte{'>'}
+}
+
+func (b *blockquoteParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ if b.process(reader) {
+ return ast.NewBlockquote(), HasChildren
+ }
+ return nil, NoChildren
+}
+
+func (b *blockquoteParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ if b.process(reader) {
+ return Continue | HasChildren
+ }
+ return Close
+}
+
+func (b *blockquoteParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ // nothing to do
+}
+
+func (b *blockquoteParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *blockquoteParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/code_block.go b/vendor/github.com/yuin/goldmark/parser/code_block.go
new file mode 100644
index 0000000..732f18c
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/code_block.go
@@ -0,0 +1,100 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type codeBlockParser struct {
+}
+
+// CodeBlockParser is a BlockParser implementation that parses indented code blocks.
+var defaultCodeBlockParser = &codeBlockParser{}
+
+// NewCodeBlockParser returns a new BlockParser that
+// parses code blocks.
+func NewCodeBlockParser() BlockParser {
+ return defaultCodeBlockParser
+}
+
+func (b *codeBlockParser) Trigger() []byte {
+ return nil
+}
+
+func (b *codeBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ line, segment := reader.PeekLine()
+ pos, padding := util.IndentPosition(line, reader.LineOffset(), 4)
+ if pos < 0 || util.IsBlank(line) {
+ return nil, NoChildren
+ }
+ node := ast.NewCodeBlock()
+ reader.AdvanceAndSetPadding(pos, padding)
+ _, segment = reader.PeekLine()
+ // if code block line starts with a tab, keep a tab as it is.
+ if segment.Padding != 0 {
+ preserveLeadingTabInCodeBlock(&segment, reader, 0)
+ }
+ node.Lines().Append(segment)
+ reader.Advance(segment.Len() - 1)
+ return node, NoChildren
+
+}
+
+func (b *codeBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ line, segment := reader.PeekLine()
+ if util.IsBlank(line) {
+ node.Lines().Append(segment.TrimLeftSpaceWidth(4, reader.Source()))
+ return Continue | NoChildren
+ }
+ pos, padding := util.IndentPosition(line, reader.LineOffset(), 4)
+ if pos < 0 {
+ return Close
+ }
+ reader.AdvanceAndSetPadding(pos, padding)
+ _, segment = reader.PeekLine()
+
+ // if code block line starts with a tab, keep a tab as it is.
+ if segment.Padding != 0 {
+ preserveLeadingTabInCodeBlock(&segment, reader, 0)
+ }
+
+ node.Lines().Append(segment)
+ reader.Advance(segment.Len() - 1)
+ return Continue | NoChildren
+}
+
+func (b *codeBlockParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ // trim trailing blank lines
+ lines := node.Lines()
+ length := lines.Len() - 1
+ source := reader.Source()
+ for length >= 0 {
+ line := lines.At(length)
+ if util.IsBlank(line.Value(source)) {
+ length--
+ } else {
+ break
+ }
+ }
+ lines.SetSliced(0, length+1)
+}
+
+func (b *codeBlockParser) CanInterruptParagraph() bool {
+ return false
+}
+
+func (b *codeBlockParser) CanAcceptIndentedLine() bool {
+ return true
+}
+
+func preserveLeadingTabInCodeBlock(segment *text.Segment, reader text.Reader, indent int) {
+ offsetWithPadding := reader.LineOffset() + indent
+ sl, ss := reader.Position()
+ reader.SetPosition(sl, text.NewSegment(ss.Start-1, ss.Stop))
+ if offsetWithPadding == reader.LineOffset() {
+ segment.Padding = 0
+ segment.Start--
+ }
+ reader.SetPosition(sl, ss)
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/code_span.go b/vendor/github.com/yuin/goldmark/parser/code_span.go
new file mode 100644
index 0000000..a74b09b
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/code_span.go
@@ -0,0 +1,84 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+)
+
+type codeSpanParser struct {
+}
+
+var defaultCodeSpanParser = &codeSpanParser{}
+
+// NewCodeSpanParser return a new InlineParser that parses inline codes
+// surrounded by '`' .
+func NewCodeSpanParser() InlineParser {
+ return defaultCodeSpanParser
+}
+
+func (s *codeSpanParser) Trigger() []byte {
+ return []byte{'`'}
+}
+
+func (s *codeSpanParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
+ line, startSegment := block.PeekLine()
+ opener := 0
+ for ; opener < len(line) && line[opener] == '`'; opener++ {
+ }
+ block.Advance(opener)
+ l, pos := block.Position()
+ node := ast.NewCodeSpan()
+ for {
+ line, segment := block.PeekLine()
+ if line == nil {
+ block.SetPosition(l, pos)
+ return ast.NewTextSegment(startSegment.WithStop(startSegment.Start + opener))
+ }
+ for i := 0; i < len(line); i++ {
+ c := line[i]
+ if c == '`' {
+ oldi := i
+ for ; i < len(line) && line[i] == '`'; i++ {
+ }
+ closure := i - oldi
+ if closure == opener && (i >= len(line) || line[i] != '`') {
+ segment = segment.WithStop(segment.Start + i - closure)
+ if !segment.IsEmpty() {
+ node.AppendChild(node, ast.NewRawTextSegment(segment))
+ }
+ block.Advance(i)
+ goto end
+ }
+ }
+ }
+ node.AppendChild(node, ast.NewRawTextSegment(segment))
+ block.AdvanceLine()
+ }
+end:
+ if !node.IsBlank(block.Source()) {
+ // trim first halfspace and last halfspace
+ segment := node.FirstChild().(*ast.Text).Segment
+ shouldTrimmed := true
+ if !(!segment.IsEmpty() && isSpaceOrNewline(block.Source()[segment.Start])) {
+ shouldTrimmed = false
+ }
+ segment = node.LastChild().(*ast.Text).Segment
+ if !(!segment.IsEmpty() && isSpaceOrNewline(block.Source()[segment.Stop-1])) {
+ shouldTrimmed = false
+ }
+ if shouldTrimmed {
+ t := node.FirstChild().(*ast.Text)
+ segment := t.Segment
+ t.Segment = segment.WithStart(segment.Start + 1)
+ t = node.LastChild().(*ast.Text)
+ segment = node.LastChild().(*ast.Text).Segment
+ t.Segment = segment.WithStop(segment.Stop - 1)
+ }
+
+ }
+ return node
+}
+
+func isSpaceOrNewline(c byte) bool {
+ return c == ' ' || c == '\n'
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/delimiter.go b/vendor/github.com/yuin/goldmark/parser/delimiter.go
new file mode 100644
index 0000000..eb843af
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/delimiter.go
@@ -0,0 +1,238 @@
+package parser
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+// A DelimiterProcessor interface provides a set of functions about
+// Delimiter nodes.
+type DelimiterProcessor interface {
+ // IsDelimiter returns true if given character is a delimiter, otherwise false.
+ IsDelimiter(byte) bool
+
+ // CanOpenCloser returns true if given opener can close given closer, otherwise false.
+ CanOpenCloser(opener, closer *Delimiter) bool
+
+ // OnMatch will be called when new matched delimiter found.
+ // OnMatch should return a new Node correspond to the matched delimiter.
+ OnMatch(consumes int) ast.Node
+}
+
+// A Delimiter struct represents a delimiter like '*' of the Markdown text.
+type Delimiter struct {
+ ast.BaseInline
+
+ Segment text.Segment
+
+ // CanOpen is set true if this delimiter can open a span for a new node.
+ // See https://spec.commonmark.org/0.30/#can-open-emphasis for details.
+ CanOpen bool
+
+ // CanClose is set true if this delimiter can close a span for a new node.
+ // See https://spec.commonmark.org/0.30/#can-open-emphasis for details.
+ CanClose bool
+
+ // Length is a remaining length of this delimiter.
+ Length int
+
+ // OriginalLength is a original length of this delimiter.
+ OriginalLength int
+
+ // Char is a character of this delimiter.
+ Char byte
+
+ // PreviousDelimiter is a previous sibling delimiter node of this delimiter.
+ PreviousDelimiter *Delimiter
+
+ // NextDelimiter is a next sibling delimiter node of this delimiter.
+ NextDelimiter *Delimiter
+
+ // Processor is a DelimiterProcessor associated with this delimiter.
+ Processor DelimiterProcessor
+}
+
+// Inline implements Inline.Inline.
+func (d *Delimiter) Inline() {}
+
+// Dump implements Node.Dump.
+func (d *Delimiter) Dump(source []byte, level int) {
+ fmt.Printf("%sDelimiter: \"%s\"\n", strings.Repeat(" ", level), string(d.Text(source)))
+}
+
+var kindDelimiter = ast.NewNodeKind("Delimiter")
+
+// Kind implements Node.Kind
+func (d *Delimiter) Kind() ast.NodeKind {
+ return kindDelimiter
+}
+
+// Text implements Node.Text
+func (d *Delimiter) Text(source []byte) []byte {
+ return d.Segment.Value(source)
+}
+
+// ConsumeCharacters consumes delimiters.
+func (d *Delimiter) ConsumeCharacters(n int) {
+ d.Length -= n
+ d.Segment = d.Segment.WithStop(d.Segment.Start + d.Length)
+}
+
+// CalcComsumption calculates how many characters should be used for opening
+// a new span correspond to given closer.
+func (d *Delimiter) CalcComsumption(closer *Delimiter) int {
+ if (d.CanClose || closer.CanOpen) && (d.OriginalLength+closer.OriginalLength)%3 == 0 && closer.OriginalLength%3 != 0 {
+ return 0
+ }
+ if d.Length >= 2 && closer.Length >= 2 {
+ return 2
+ }
+ return 1
+}
+
+// NewDelimiter returns a new Delimiter node.
+func NewDelimiter(canOpen, canClose bool, length int, char byte, processor DelimiterProcessor) *Delimiter {
+ c := &Delimiter{
+ BaseInline: ast.BaseInline{},
+ CanOpen: canOpen,
+ CanClose: canClose,
+ Length: length,
+ OriginalLength: length,
+ Char: char,
+ PreviousDelimiter: nil,
+ NextDelimiter: nil,
+ Processor: processor,
+ }
+ return c
+}
+
+// ScanDelimiter scans a delimiter by given DelimiterProcessor.
+func ScanDelimiter(line []byte, before rune, min int, processor DelimiterProcessor) *Delimiter {
+ i := 0
+ c := line[i]
+ j := i
+ if !processor.IsDelimiter(c) {
+ return nil
+ }
+ for ; j < len(line) && c == line[j]; j++ {
+ }
+ if (j - i) >= min {
+ after := rune(' ')
+ if j != len(line) {
+ after = util.ToRune(line, j)
+ }
+
+ canOpen, canClose := false, false
+ beforeIsPunctuation := util.IsPunctRune(before)
+ beforeIsWhitespace := util.IsSpaceRune(before)
+ afterIsPunctuation := util.IsPunctRune(after)
+ afterIsWhitespace := util.IsSpaceRune(after)
+
+ isLeft := !afterIsWhitespace &&
+ (!afterIsPunctuation || beforeIsWhitespace || beforeIsPunctuation)
+ isRight := !beforeIsWhitespace &&
+ (!beforeIsPunctuation || afterIsWhitespace || afterIsPunctuation)
+
+ if line[i] == '_' {
+ canOpen = isLeft && (!isRight || beforeIsPunctuation)
+ canClose = isRight && (!isLeft || afterIsPunctuation)
+ } else {
+ canOpen = isLeft
+ canClose = isRight
+ }
+ return NewDelimiter(canOpen, canClose, j-i, c, processor)
+ }
+ return nil
+}
+
+// ProcessDelimiters processes the delimiter list in the context.
+// Processing will be stop when reaching the bottom.
+//
+// If you implement an inline parser that can have other inline nodes as
+// children, you should call this function when nesting span has closed.
+func ProcessDelimiters(bottom ast.Node, pc Context) {
+ lastDelimiter := pc.LastDelimiter()
+ if lastDelimiter == nil {
+ return
+ }
+ var closer *Delimiter
+ if bottom != nil {
+ if bottom != lastDelimiter {
+ for c := lastDelimiter.PreviousSibling(); c != nil && c != bottom; {
+ if d, ok := c.(*Delimiter); ok {
+ closer = d
+ }
+ c = c.PreviousSibling()
+ }
+ }
+ } else {
+ closer = pc.FirstDelimiter()
+ }
+ if closer == nil {
+ pc.ClearDelimiters(bottom)
+ return
+ }
+ for closer != nil {
+ if !closer.CanClose {
+ closer = closer.NextDelimiter
+ continue
+ }
+ consume := 0
+ found := false
+ maybeOpener := false
+ var opener *Delimiter
+ for opener = closer.PreviousDelimiter; opener != nil && opener != bottom; opener = opener.PreviousDelimiter {
+ if opener.CanOpen && opener.Processor.CanOpenCloser(opener, closer) {
+ maybeOpener = true
+ consume = opener.CalcComsumption(closer)
+ if consume > 0 {
+ found = true
+ break
+ }
+ }
+ }
+ if !found {
+ next := closer.NextDelimiter
+ if !maybeOpener && !closer.CanOpen {
+ pc.RemoveDelimiter(closer)
+ }
+ closer = next
+ continue
+ }
+ opener.ConsumeCharacters(consume)
+ closer.ConsumeCharacters(consume)
+
+ node := opener.Processor.OnMatch(consume)
+
+ parent := opener.Parent()
+ child := opener.NextSibling()
+
+ for child != nil && child != closer {
+ next := child.NextSibling()
+ node.AppendChild(node, child)
+ child = next
+ }
+ parent.InsertAfter(parent, opener, node)
+
+ for c := opener.NextDelimiter; c != nil && c != closer; {
+ next := c.NextDelimiter
+ pc.RemoveDelimiter(c)
+ c = next
+ }
+
+ if opener.Length == 0 {
+ pc.RemoveDelimiter(opener)
+ }
+
+ if closer.Length == 0 {
+ next := closer.NextDelimiter
+ pc.RemoveDelimiter(closer)
+ closer = next
+ }
+ }
+ pc.ClearDelimiters(bottom)
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/emphasis.go b/vendor/github.com/yuin/goldmark/parser/emphasis.go
new file mode 100644
index 0000000..4886471
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/emphasis.go
@@ -0,0 +1,50 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+)
+
+type emphasisDelimiterProcessor struct {
+}
+
+func (p *emphasisDelimiterProcessor) IsDelimiter(b byte) bool {
+ return b == '*' || b == '_'
+}
+
+func (p *emphasisDelimiterProcessor) CanOpenCloser(opener, closer *Delimiter) bool {
+ return opener.Char == closer.Char
+}
+
+func (p *emphasisDelimiterProcessor) OnMatch(consumes int) ast.Node {
+ return ast.NewEmphasis(consumes)
+}
+
+var defaultEmphasisDelimiterProcessor = &emphasisDelimiterProcessor{}
+
+type emphasisParser struct {
+}
+
+var defaultEmphasisParser = &emphasisParser{}
+
+// NewEmphasisParser return a new InlineParser that parses emphasises.
+func NewEmphasisParser() InlineParser {
+ return defaultEmphasisParser
+}
+
+func (s *emphasisParser) Trigger() []byte {
+ return []byte{'*', '_'}
+}
+
+func (s *emphasisParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
+ before := block.PrecendingCharacter()
+ line, segment := block.PeekLine()
+ node := ScanDelimiter(line, before, 1, defaultEmphasisDelimiterProcessor)
+ if node == nil {
+ return nil
+ }
+ node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
+ block.Advance(node.OriginalLength)
+ pc.PushDelimiter(node)
+ return node
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/fcode_block.go b/vendor/github.com/yuin/goldmark/parser/fcode_block.go
new file mode 100644
index 0000000..5914138
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/fcode_block.go
@@ -0,0 +1,121 @@
+package parser
+
+import (
+ "bytes"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type fencedCodeBlockParser struct {
+}
+
+var defaultFencedCodeBlockParser = &fencedCodeBlockParser{}
+
+// NewFencedCodeBlockParser returns a new BlockParser that
+// parses fenced code blocks.
+func NewFencedCodeBlockParser() BlockParser {
+ return defaultFencedCodeBlockParser
+}
+
+type fenceData struct {
+ char byte
+ indent int
+ length int
+ node ast.Node
+}
+
+var fencedCodeBlockInfoKey = NewContextKey()
+
+func (b *fencedCodeBlockParser) Trigger() []byte {
+ return []byte{'~', '`'}
+}
+
+func (b *fencedCodeBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ line, segment := reader.PeekLine()
+ pos := pc.BlockOffset()
+ if pos < 0 || (line[pos] != '`' && line[pos] != '~') {
+ return nil, NoChildren
+ }
+ findent := pos
+ fenceChar := line[pos]
+ i := pos
+ for ; i < len(line) && line[i] == fenceChar; i++ {
+ }
+ oFenceLength := i - pos
+ if oFenceLength < 3 {
+ return nil, NoChildren
+ }
+ var info *ast.Text
+ if i < len(line)-1 {
+ rest := line[i:]
+ left := util.TrimLeftSpaceLength(rest)
+ right := util.TrimRightSpaceLength(rest)
+ if left < len(rest)-right {
+ infoStart, infoStop := segment.Start-segment.Padding+i+left, segment.Stop-right
+ value := rest[left : len(rest)-right]
+ if fenceChar == '`' && bytes.IndexByte(value, '`') > -1 {
+ return nil, NoChildren
+ } else if infoStart != infoStop {
+ info = ast.NewTextSegment(text.NewSegment(infoStart, infoStop))
+ }
+ }
+ }
+ node := ast.NewFencedCodeBlock(info)
+ pc.Set(fencedCodeBlockInfoKey, &fenceData{fenceChar, findent, oFenceLength, node})
+ return node, NoChildren
+
+}
+
+func (b *fencedCodeBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ line, segment := reader.PeekLine()
+ fdata := pc.Get(fencedCodeBlockInfoKey).(*fenceData)
+
+ w, pos := util.IndentWidth(line, reader.LineOffset())
+ if w < 4 {
+ i := pos
+ for ; i < len(line) && line[i] == fdata.char; i++ {
+ }
+ length := i - pos
+ if length >= fdata.length && util.IsBlank(line[i:]) {
+ newline := 1
+ if line[len(line)-1] != '\n' {
+ newline = 0
+ }
+ reader.Advance(segment.Stop - segment.Start - newline - segment.Padding)
+ return Close
+ }
+ }
+ pos, padding := util.IndentPositionPadding(line, reader.LineOffset(), segment.Padding, fdata.indent)
+ if pos < 0 {
+ pos = util.FirstNonSpacePosition(line)
+ if pos < 0 {
+ pos = 0
+ }
+ padding = 0
+ }
+ seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding)
+ // if code block line starts with a tab, keep a tab as it is.
+ if padding != 0 {
+ preserveLeadingTabInCodeBlock(&seg, reader, fdata.indent)
+ }
+ node.Lines().Append(seg)
+ reader.AdvanceAndSetPadding(segment.Stop-segment.Start-pos-1, padding)
+ return Continue | NoChildren
+}
+
+func (b *fencedCodeBlockParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ fdata := pc.Get(fencedCodeBlockInfoKey).(*fenceData)
+ if fdata.node == node {
+ pc.Set(fencedCodeBlockInfoKey, nil)
+ }
+}
+
+func (b *fencedCodeBlockParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *fencedCodeBlockParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/html_block.go b/vendor/github.com/yuin/goldmark/parser/html_block.go
new file mode 100644
index 0000000..380e723
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/html_block.go
@@ -0,0 +1,228 @@
+package parser
+
+import (
+ "bytes"
+ "regexp"
+ "strings"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+var allowedBlockTags = map[string]bool{
+ "address": true,
+ "article": true,
+ "aside": true,
+ "base": true,
+ "basefont": true,
+ "blockquote": true,
+ "body": true,
+ "caption": true,
+ "center": true,
+ "col": true,
+ "colgroup": true,
+ "dd": true,
+ "details": true,
+ "dialog": true,
+ "dir": true,
+ "div": true,
+ "dl": true,
+ "dt": true,
+ "fieldset": true,
+ "figcaption": true,
+ "figure": true,
+ "footer": true,
+ "form": true,
+ "frame": true,
+ "frameset": true,
+ "h1": true,
+ "h2": true,
+ "h3": true,
+ "h4": true,
+ "h5": true,
+ "h6": true,
+ "head": true,
+ "header": true,
+ "hr": true,
+ "html": true,
+ "iframe": true,
+ "legend": true,
+ "li": true,
+ "link": true,
+ "main": true,
+ "menu": true,
+ "menuitem": true,
+ "meta": true,
+ "nav": true,
+ "noframes": true,
+ "ol": true,
+ "optgroup": true,
+ "option": true,
+ "p": true,
+ "param": true,
+ "section": true,
+ "source": true,
+ "summary": true,
+ "table": true,
+ "tbody": true,
+ "td": true,
+ "tfoot": true,
+ "th": true,
+ "thead": true,
+ "title": true,
+ "tr": true,
+ "track": true,
+ "ul": true,
+}
+
+var htmlBlockType1OpenRegexp = regexp.MustCompile(`(?i)^[ ]{0,3}<(script|pre|style|textarea)(?:\s.*|>.*|/>.*|)(?:\r\n|\n)?$`)
+var htmlBlockType1CloseRegexp = regexp.MustCompile(`(?i)^.*(?:script|pre|style|textarea)>.*`)
+
+var htmlBlockType2OpenRegexp = regexp.MustCompile(`^[ ]{0,3}'}
+
+var htmlBlockType3OpenRegexp = regexp.MustCompile(`^[ ]{0,3}<\?`)
+var htmlBlockType3Close = []byte{'?', '>'}
+
+var htmlBlockType4OpenRegexp = regexp.MustCompile(`^[ ]{0,3}'}
+
+var htmlBlockType5OpenRegexp = regexp.MustCompile(`^[ ]{0,3}<\!\[CDATA\[`)
+var htmlBlockType5Close = []byte{']', ']', '>'}
+
+var htmlBlockType6Regexp = regexp.MustCompile(`^[ ]{0,3}<(?:/[ ]*)?([a-zA-Z]+[a-zA-Z0-9\-]*)(?:[ ].*|>.*|/>.*|)(?:\r\n|\n)?$`)
+
+var htmlBlockType7Regexp = regexp.MustCompile(`^[ ]{0,3}<(/[ ]*)?([a-zA-Z]+[a-zA-Z0-9\-]*)(` + attributePattern + `*)[ ]*(?:>|/>)[ ]*(?:\r\n|\n)?$`)
+
+type htmlBlockParser struct {
+}
+
+var defaultHTMLBlockParser = &htmlBlockParser{}
+
+// NewHTMLBlockParser return a new BlockParser that can parse html
+// blocks.
+func NewHTMLBlockParser() BlockParser {
+ return defaultHTMLBlockParser
+}
+
+func (b *htmlBlockParser) Trigger() []byte {
+ return []byte{'<'}
+}
+
+func (b *htmlBlockParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ var node *ast.HTMLBlock
+ line, segment := reader.PeekLine()
+ last := pc.LastOpenedBlock().Node
+ if pos := pc.BlockOffset(); pos < 0 || line[pos] != '<' {
+ return nil, NoChildren
+ }
+
+ if m := htmlBlockType1OpenRegexp.FindSubmatchIndex(line); m != nil {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType1)
+ } else if htmlBlockType2OpenRegexp.Match(line) {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType2)
+ } else if htmlBlockType3OpenRegexp.Match(line) {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType3)
+ } else if htmlBlockType4OpenRegexp.Match(line) {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType4)
+ } else if htmlBlockType5OpenRegexp.Match(line) {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType5)
+ } else if match := htmlBlockType7Regexp.FindSubmatchIndex(line); match != nil {
+ isCloseTag := match[2] > -1 && bytes.Equal(line[match[2]:match[3]], []byte("/"))
+ hasAttr := match[6] != match[7]
+ tagName := strings.ToLower(string(line[match[4]:match[5]]))
+ _, ok := allowedBlockTags[tagName]
+ if ok {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType6)
+ } else if tagName != "script" && tagName != "style" && tagName != "pre" && !ast.IsParagraph(last) && !(isCloseTag && hasAttr) { // type 7 can not interrupt paragraph
+ node = ast.NewHTMLBlock(ast.HTMLBlockType7)
+ }
+ }
+ if node == nil {
+ if match := htmlBlockType6Regexp.FindSubmatchIndex(line); match != nil {
+ tagName := string(line[match[2]:match[3]])
+ _, ok := allowedBlockTags[strings.ToLower(tagName)]
+ if ok {
+ node = ast.NewHTMLBlock(ast.HTMLBlockType6)
+ }
+ }
+ }
+ if node != nil {
+ reader.Advance(segment.Len() - 1)
+ node.Lines().Append(segment)
+ return node, NoChildren
+ }
+ return nil, NoChildren
+}
+
+func (b *htmlBlockParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ htmlBlock := node.(*ast.HTMLBlock)
+ lines := htmlBlock.Lines()
+ line, segment := reader.PeekLine()
+ var closurePattern []byte
+
+ switch htmlBlock.HTMLBlockType {
+ case ast.HTMLBlockType1:
+ if lines.Len() == 1 {
+ firstLine := lines.At(0)
+ if htmlBlockType1CloseRegexp.Match(firstLine.Value(reader.Source())) {
+ return Close
+ }
+ }
+ if htmlBlockType1CloseRegexp.Match(line) {
+ htmlBlock.ClosureLine = segment
+ reader.Advance(segment.Len() - 1)
+ return Close
+ }
+ case ast.HTMLBlockType2:
+ closurePattern = htmlBlockType2Close
+ fallthrough
+ case ast.HTMLBlockType3:
+ if closurePattern == nil {
+ closurePattern = htmlBlockType3Close
+ }
+ fallthrough
+ case ast.HTMLBlockType4:
+ if closurePattern == nil {
+ closurePattern = htmlBlockType4Close
+ }
+ fallthrough
+ case ast.HTMLBlockType5:
+ if closurePattern == nil {
+ closurePattern = htmlBlockType5Close
+ }
+
+ if lines.Len() == 1 {
+ firstLine := lines.At(0)
+ if bytes.Contains(firstLine.Value(reader.Source()), closurePattern) {
+ return Close
+ }
+ }
+ if bytes.Contains(line, closurePattern) {
+ htmlBlock.ClosureLine = segment
+ reader.Advance(segment.Len())
+ return Close
+ }
+
+ case ast.HTMLBlockType6, ast.HTMLBlockType7:
+ if util.IsBlank(line) {
+ return Close
+ }
+ }
+ node.Lines().Append(segment)
+ reader.Advance(segment.Len() - 1)
+ return Continue | NoChildren
+}
+
+func (b *htmlBlockParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ // nothing to do
+}
+
+func (b *htmlBlockParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *htmlBlockParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/link.go b/vendor/github.com/yuin/goldmark/parser/link.go
new file mode 100644
index 0000000..99583ac
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/link.go
@@ -0,0 +1,409 @@
+package parser
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+var linkLabelStateKey = NewContextKey()
+
+type linkLabelState struct {
+ ast.BaseInline
+
+ Segment text.Segment
+
+ IsImage bool
+
+ Prev *linkLabelState
+
+ Next *linkLabelState
+
+ First *linkLabelState
+
+ Last *linkLabelState
+}
+
+func newLinkLabelState(segment text.Segment, isImage bool) *linkLabelState {
+ return &linkLabelState{
+ Segment: segment,
+ IsImage: isImage,
+ }
+}
+
+func (s *linkLabelState) Text(source []byte) []byte {
+ return s.Segment.Value(source)
+}
+
+func (s *linkLabelState) Dump(source []byte, level int) {
+ fmt.Printf("%slinkLabelState: \"%s\"\n", strings.Repeat(" ", level), s.Text(source))
+}
+
+var kindLinkLabelState = ast.NewNodeKind("LinkLabelState")
+
+func (s *linkLabelState) Kind() ast.NodeKind {
+ return kindLinkLabelState
+}
+
+func linkLabelStateLength(v *linkLabelState) int {
+ if v == nil || v.Last == nil || v.First == nil {
+ return 0
+ }
+ return v.Last.Segment.Stop - v.First.Segment.Start
+}
+
+func pushLinkLabelState(pc Context, v *linkLabelState) {
+ tlist := pc.Get(linkLabelStateKey)
+ var list *linkLabelState
+ if tlist == nil {
+ list = v
+ v.First = v
+ v.Last = v
+ pc.Set(linkLabelStateKey, list)
+ } else {
+ list = tlist.(*linkLabelState)
+ l := list.Last
+ list.Last = v
+ l.Next = v
+ v.Prev = l
+ }
+}
+
+func removeLinkLabelState(pc Context, d *linkLabelState) {
+ tlist := pc.Get(linkLabelStateKey)
+ var list *linkLabelState
+ if tlist == nil {
+ return
+ }
+ list = tlist.(*linkLabelState)
+
+ if d.Prev == nil {
+ list = d.Next
+ if list != nil {
+ list.First = d
+ list.Last = d.Last
+ list.Prev = nil
+ pc.Set(linkLabelStateKey, list)
+ } else {
+ pc.Set(linkLabelStateKey, nil)
+ }
+ } else {
+ d.Prev.Next = d.Next
+ if d.Next != nil {
+ d.Next.Prev = d.Prev
+ }
+ }
+ if list != nil && d.Next == nil {
+ list.Last = d.Prev
+ }
+ d.Next = nil
+ d.Prev = nil
+ d.First = nil
+ d.Last = nil
+}
+
+type linkParser struct {
+}
+
+var defaultLinkParser = &linkParser{}
+
+// NewLinkParser return a new InlineParser that parses links.
+func NewLinkParser() InlineParser {
+ return defaultLinkParser
+}
+
+func (s *linkParser) Trigger() []byte {
+ return []byte{'!', '[', ']'}
+}
+
+var linkBottom = NewContextKey()
+
+func (s *linkParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
+ line, segment := block.PeekLine()
+ if line[0] == '!' {
+ if len(line) > 1 && line[1] == '[' {
+ block.Advance(1)
+ pc.Set(linkBottom, pc.LastDelimiter())
+ return processLinkLabelOpen(block, segment.Start+1, true, pc)
+ }
+ return nil
+ }
+ if line[0] == '[' {
+ pc.Set(linkBottom, pc.LastDelimiter())
+ return processLinkLabelOpen(block, segment.Start, false, pc)
+ }
+
+ // line[0] == ']'
+ tlist := pc.Get(linkLabelStateKey)
+ if tlist == nil {
+ return nil
+ }
+ last := tlist.(*linkLabelState).Last
+ if last == nil {
+ return nil
+ }
+ block.Advance(1)
+ removeLinkLabelState(pc, last)
+ // CommonMark spec says:
+ // > A link label can have at most 999 characters inside the square brackets.
+ if linkLabelStateLength(tlist.(*linkLabelState)) > 998 {
+ ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
+ return nil
+ }
+
+ if !last.IsImage && s.containsLink(last) { // a link in a link text is not allowed
+ ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
+ return nil
+ }
+
+ c := block.Peek()
+ l, pos := block.Position()
+ var link *ast.Link
+ var hasValue bool
+ if c == '(' { // normal link
+ link = s.parseLink(parent, last, block, pc)
+ } else if c == '[' { // reference link
+ link, hasValue = s.parseReferenceLink(parent, last, block, pc)
+ if link == nil && hasValue {
+ ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
+ return nil
+ }
+ }
+
+ if link == nil {
+ // maybe shortcut reference link
+ block.SetPosition(l, pos)
+ ssegment := text.NewSegment(last.Segment.Stop, segment.Start)
+ maybeReference := block.Value(ssegment)
+ // CommonMark spec says:
+ // > A link label can have at most 999 characters inside the square brackets.
+ if len(maybeReference) > 999 {
+ ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
+ return nil
+ }
+
+ ref, ok := pc.Reference(util.ToLinkReference(maybeReference))
+ if !ok {
+ ast.MergeOrReplaceTextSegment(last.Parent(), last, last.Segment)
+ return nil
+ }
+ link = ast.NewLink()
+ s.processLinkLabel(parent, link, last, pc)
+ link.Title = ref.Title()
+ link.Destination = ref.Destination()
+ }
+ if last.IsImage {
+ last.Parent().RemoveChild(last.Parent(), last)
+ return ast.NewImage(link)
+ }
+ last.Parent().RemoveChild(last.Parent(), last)
+ return link
+}
+
+func (s *linkParser) containsLink(n ast.Node) bool {
+ if n == nil {
+ return false
+ }
+ for c := n; c != nil; c = c.NextSibling() {
+ if _, ok := c.(*ast.Link); ok {
+ return true
+ }
+ if s.containsLink(c.FirstChild()) {
+ return true
+ }
+ }
+ return false
+}
+
+func processLinkLabelOpen(block text.Reader, pos int, isImage bool, pc Context) *linkLabelState {
+ start := pos
+ if isImage {
+ start--
+ }
+ state := newLinkLabelState(text.NewSegment(start, pos+1), isImage)
+ pushLinkLabelState(pc, state)
+ block.Advance(1)
+ return state
+}
+
+func (s *linkParser) processLinkLabel(parent ast.Node, link *ast.Link, last *linkLabelState, pc Context) {
+ var bottom ast.Node
+ if v := pc.Get(linkBottom); v != nil {
+ bottom = v.(ast.Node)
+ }
+ pc.Set(linkBottom, nil)
+ ProcessDelimiters(bottom, pc)
+ for c := last.NextSibling(); c != nil; {
+ next := c.NextSibling()
+ parent.RemoveChild(parent, c)
+ link.AppendChild(link, c)
+ c = next
+ }
+}
+
+var linkFindClosureOptions text.FindClosureOptions = text.FindClosureOptions{
+ Nesting: false,
+ Newline: true,
+ Advance: true,
+}
+
+func (s *linkParser) parseReferenceLink(parent ast.Node, last *linkLabelState, block text.Reader, pc Context) (*ast.Link, bool) {
+ _, orgpos := block.Position()
+ block.Advance(1) // skip '['
+ segments, found := block.FindClosure('[', ']', linkFindClosureOptions)
+ if !found {
+ return nil, false
+ }
+
+ var maybeReference []byte
+ if segments.Len() == 1 { // avoid allocate a new byte slice
+ maybeReference = block.Value(segments.At(0))
+ } else {
+ maybeReference = []byte{}
+ for i := 0; i < segments.Len(); i++ {
+ s := segments.At(i)
+ maybeReference = append(maybeReference, block.Value(s)...)
+ }
+ }
+ if util.IsBlank(maybeReference) { // collapsed reference link
+ s := text.NewSegment(last.Segment.Stop, orgpos.Start-1)
+ maybeReference = block.Value(s)
+ }
+ // CommonMark spec says:
+ // > A link label can have at most 999 characters inside the square brackets.
+ if len(maybeReference) > 999 {
+ return nil, true
+ }
+
+ ref, ok := pc.Reference(util.ToLinkReference(maybeReference))
+ if !ok {
+ return nil, true
+ }
+
+ link := ast.NewLink()
+ s.processLinkLabel(parent, link, last, pc)
+ link.Title = ref.Title()
+ link.Destination = ref.Destination()
+ return link, true
+}
+
+func (s *linkParser) parseLink(parent ast.Node, last *linkLabelState, block text.Reader, pc Context) *ast.Link {
+ block.Advance(1) // skip '('
+ block.SkipSpaces()
+ var title []byte
+ var destination []byte
+ var ok bool
+ if block.Peek() == ')' { // empty link like '[link]()'
+ block.Advance(1)
+ } else {
+ destination, ok = parseLinkDestination(block)
+ if !ok {
+ return nil
+ }
+ block.SkipSpaces()
+ if block.Peek() == ')' {
+ block.Advance(1)
+ } else {
+ title, ok = parseLinkTitle(block)
+ if !ok {
+ return nil
+ }
+ block.SkipSpaces()
+ if block.Peek() == ')' {
+ block.Advance(1)
+ } else {
+ return nil
+ }
+ }
+ }
+
+ link := ast.NewLink()
+ s.processLinkLabel(parent, link, last, pc)
+ link.Destination = destination
+ link.Title = title
+ return link
+}
+
+func parseLinkDestination(block text.Reader) ([]byte, bool) {
+ block.SkipSpaces()
+ line, _ := block.PeekLine()
+ if block.Peek() == '<' {
+ i := 1
+ for i < len(line) {
+ c := line[i]
+ if c == '\\' && i < len(line)-1 && util.IsPunct(line[i+1]) {
+ i += 2
+ continue
+ } else if c == '>' {
+ block.Advance(i + 1)
+ return line[1:i], true
+ }
+ i++
+ }
+ return nil, false
+ }
+ opened := 0
+ i := 0
+ for i < len(line) {
+ c := line[i]
+ if c == '\\' && i < len(line)-1 && util.IsPunct(line[i+1]) {
+ i += 2
+ continue
+ } else if c == '(' {
+ opened++
+ } else if c == ')' {
+ opened--
+ if opened < 0 {
+ break
+ }
+ } else if util.IsSpace(c) {
+ break
+ }
+ i++
+ }
+ block.Advance(i)
+ return line[:i], len(line[:i]) != 0
+}
+
+func parseLinkTitle(block text.Reader) ([]byte, bool) {
+ block.SkipSpaces()
+ opener := block.Peek()
+ if opener != '"' && opener != '\'' && opener != '(' {
+ return nil, false
+ }
+ closer := opener
+ if opener == '(' {
+ closer = ')'
+ }
+ block.Advance(1)
+ segments, found := block.FindClosure(opener, closer, linkFindClosureOptions)
+ if found {
+ if segments.Len() == 1 {
+ return block.Value(segments.At(0)), true
+ }
+ var title []byte
+ for i := 0; i < segments.Len(); i++ {
+ s := segments.At(i)
+ title = append(title, block.Value(s)...)
+ }
+ return title, true
+ }
+ return nil, false
+}
+
+func (s *linkParser) CloseBlock(parent ast.Node, block text.Reader, pc Context) {
+ pc.Set(linkBottom, nil)
+ tlist := pc.Get(linkLabelStateKey)
+ if tlist == nil {
+ return
+ }
+ for s := tlist.(*linkLabelState); s != nil; {
+ next := s.Next
+ removeLinkLabelState(pc, s)
+ s.Parent().ReplaceChild(s.Parent(), s, ast.NewTextSegment(s.Segment))
+ s = next
+ }
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/link_ref.go b/vendor/github.com/yuin/goldmark/parser/link_ref.go
new file mode 100644
index 0000000..ea3f654
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/link_ref.go
@@ -0,0 +1,152 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type linkReferenceParagraphTransformer struct {
+}
+
+// LinkReferenceParagraphTransformer is a ParagraphTransformer implementation
+// that parses and extracts link reference from paragraphs.
+var LinkReferenceParagraphTransformer = &linkReferenceParagraphTransformer{}
+
+func (p *linkReferenceParagraphTransformer) Transform(node *ast.Paragraph, reader text.Reader, pc Context) {
+ lines := node.Lines()
+ block := text.NewBlockReader(reader.Source(), lines)
+ removes := [][2]int{}
+ for {
+ start, end := parseLinkReferenceDefinition(block, pc)
+ if start > -1 {
+ if start == end {
+ end++
+ }
+ removes = append(removes, [2]int{start, end})
+ continue
+ }
+ break
+ }
+
+ offset := 0
+ for _, remove := range removes {
+ if lines.Len() == 0 {
+ break
+ }
+ s := lines.Sliced(remove[1]-offset, lines.Len())
+ lines.SetSliced(0, remove[0]-offset)
+ lines.AppendAll(s)
+ offset = remove[1]
+ }
+
+ if lines.Len() == 0 {
+ t := ast.NewTextBlock()
+ t.SetBlankPreviousLines(node.HasBlankPreviousLines())
+ node.Parent().ReplaceChild(node.Parent(), node, t)
+ return
+ }
+
+ node.SetLines(lines)
+}
+
+func parseLinkReferenceDefinition(block text.Reader, pc Context) (int, int) {
+ block.SkipSpaces()
+ line, _ := block.PeekLine()
+ if line == nil {
+ return -1, -1
+ }
+ startLine, _ := block.Position()
+ width, pos := util.IndentWidth(line, 0)
+ if width > 3 {
+ return -1, -1
+ }
+ if width != 0 {
+ pos++
+ }
+ if line[pos] != '[' {
+ return -1, -1
+ }
+ block.Advance(pos + 1)
+ segments, found := block.FindClosure('[', ']', linkFindClosureOptions)
+ if !found {
+ return -1, -1
+ }
+ var label []byte
+ if segments.Len() == 1 {
+ label = block.Value(segments.At(0))
+ } else {
+ for i := 0; i < segments.Len(); i++ {
+ s := segments.At(i)
+ label = append(label, block.Value(s)...)
+ }
+ }
+ if util.IsBlank(label) {
+ return -1, -1
+ }
+ if block.Peek() != ':' {
+ return -1, -1
+ }
+ block.Advance(1)
+ block.SkipSpaces()
+ destination, ok := parseLinkDestination(block)
+ if !ok {
+ return -1, -1
+ }
+ line, _ = block.PeekLine()
+ isNewLine := line == nil || util.IsBlank(line)
+
+ endLine, _ := block.Position()
+ _, spaces, _ := block.SkipSpaces()
+ opener := block.Peek()
+ if opener != '"' && opener != '\'' && opener != '(' {
+ if !isNewLine {
+ return -1, -1
+ }
+ ref := NewReference(label, destination, nil)
+ pc.AddReference(ref)
+ return startLine, endLine + 1
+ }
+ if spaces == 0 {
+ return -1, -1
+ }
+ block.Advance(1)
+ closer := opener
+ if opener == '(' {
+ closer = ')'
+ }
+ segments, found = block.FindClosure(opener, closer, linkFindClosureOptions)
+ if !found {
+ if !isNewLine {
+ return -1, -1
+ }
+ ref := NewReference(label, destination, nil)
+ pc.AddReference(ref)
+ block.AdvanceLine()
+ return startLine, endLine + 1
+ }
+ var title []byte
+ if segments.Len() == 1 {
+ title = block.Value(segments.At(0))
+ } else {
+ for i := 0; i < segments.Len(); i++ {
+ s := segments.At(i)
+ title = append(title, block.Value(s)...)
+ }
+ }
+
+ line, _ = block.PeekLine()
+ if line != nil && !util.IsBlank(line) {
+ if !isNewLine {
+ return -1, -1
+ }
+ ref := NewReference(label, destination, title)
+ pc.AddReference(ref)
+ return startLine, endLine
+ }
+
+ endLine, _ = block.Position()
+ ref := NewReference(label, destination, title)
+ pc.AddReference(ref)
+ return startLine, endLine + 1
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/list.go b/vendor/github.com/yuin/goldmark/parser/list.go
new file mode 100644
index 0000000..2a1c03a
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/list.go
@@ -0,0 +1,283 @@
+package parser
+
+import (
+ "strconv"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type listItemType int
+
+const (
+ notList listItemType = iota
+ bulletList
+ orderedList
+)
+
+var skipListParserKey = NewContextKey()
+var emptyListItemWithBlankLines = NewContextKey()
+var listItemFlagValue interface{} = true
+
+// Same as
+// `^(([ ]*)([\-\*\+]))(\s+.*)?\n?$`.FindSubmatchIndex or
+// `^(([ ]*)(\d{1,9}[\.\)]))(\s+.*)?\n?$`.FindSubmatchIndex
+func parseListItem(line []byte) ([6]int, listItemType) {
+ i := 0
+ l := len(line)
+ ret := [6]int{}
+ for ; i < l && line[i] == ' '; i++ {
+ c := line[i]
+ if c == '\t' {
+ return ret, notList
+ }
+ }
+ if i > 3 {
+ return ret, notList
+ }
+ ret[0] = 0
+ ret[1] = i
+ ret[2] = i
+ var typ listItemType
+ if i < l && (line[i] == '-' || line[i] == '*' || line[i] == '+') {
+ i++
+ ret[3] = i
+ typ = bulletList
+ } else if i < l {
+ for ; i < l && util.IsNumeric(line[i]); i++ {
+ }
+ ret[3] = i
+ if ret[3] == ret[2] || ret[3]-ret[2] > 9 {
+ return ret, notList
+ }
+ if i < l && (line[i] == '.' || line[i] == ')') {
+ i++
+ ret[3] = i
+ } else {
+ return ret, notList
+ }
+ typ = orderedList
+ } else {
+ return ret, notList
+ }
+ if i < l && line[i] != '\n' {
+ w, _ := util.IndentWidth(line[i:], 0)
+ if w == 0 {
+ return ret, notList
+ }
+ }
+ if i >= l {
+ ret[4] = -1
+ ret[5] = -1
+ return ret, typ
+ }
+ ret[4] = i
+ ret[5] = len(line)
+ if line[ret[5]-1] == '\n' && line[i] != '\n' {
+ ret[5]--
+ }
+ return ret, typ
+}
+
+func matchesListItem(source []byte, strict bool) ([6]int, listItemType) {
+ m, typ := parseListItem(source)
+ if typ != notList && (!strict || strict && m[1] < 4) {
+ return m, typ
+ }
+ return m, notList
+}
+
+func calcListOffset(source []byte, match [6]int) int {
+ offset := 0
+ if match[4] < 0 || util.IsBlank(source[match[4]:]) { // list item starts with a blank line
+ offset = 1
+ } else {
+ offset, _ = util.IndentWidth(source[match[4]:], match[4])
+ if offset > 4 { // offseted codeblock
+ offset = 1
+ }
+ }
+ return offset
+}
+
+func lastOffset(node ast.Node) int {
+ lastChild := node.LastChild()
+ if lastChild != nil {
+ return lastChild.(*ast.ListItem).Offset
+ }
+ return 0
+}
+
+type listParser struct {
+}
+
+var defaultListParser = &listParser{}
+
+// NewListParser returns a new BlockParser that
+// parses lists.
+// This parser must take precedence over the ListItemParser.
+func NewListParser() BlockParser {
+ return defaultListParser
+}
+
+func (b *listParser) Trigger() []byte {
+ return []byte{'-', '+', '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
+}
+
+func (b *listParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ last := pc.LastOpenedBlock().Node
+ if _, lok := last.(*ast.List); lok || pc.Get(skipListParserKey) != nil {
+ pc.Set(skipListParserKey, nil)
+ return nil, NoChildren
+ }
+ line, _ := reader.PeekLine()
+ match, typ := matchesListItem(line, true)
+ if typ == notList {
+ return nil, NoChildren
+ }
+ start := -1
+ if typ == orderedList {
+ number := line[match[2] : match[3]-1]
+ start, _ = strconv.Atoi(string(number))
+ }
+
+ if ast.IsParagraph(last) && last.Parent() == parent {
+ // we allow only lists starting with 1 to interrupt paragraphs.
+ if typ == orderedList && start != 1 {
+ return nil, NoChildren
+ }
+ //an empty list item cannot interrupt a paragraph:
+ if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
+ return nil, NoChildren
+ }
+ }
+
+ marker := line[match[3]-1]
+ node := ast.NewList(marker)
+ if start > -1 {
+ node.Start = start
+ }
+ pc.Set(emptyListItemWithBlankLines, nil)
+ return node, HasChildren
+}
+
+func (b *listParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ list := node.(*ast.List)
+ line, _ := reader.PeekLine()
+ if util.IsBlank(line) {
+ if node.LastChild().ChildCount() == 0 {
+ pc.Set(emptyListItemWithBlankLines, listItemFlagValue)
+ }
+ return Continue | HasChildren
+ }
+
+ // "offset" means a width that bar indicates.
+ // - aaaaaaaa
+ // |----|
+ //
+ // If the indent is less than the last offset like
+ // - a
+ // - b <--- current line
+ // it maybe a new child of the list.
+ //
+ // Empty list items can have multiple blanklines
+ //
+ // - <--- 1st item is an empty thus "offset" is unknown
+ //
+ //
+ // - <--- current line
+ //
+ // -> 1 list with 2 blank items
+ //
+ // So if the last item is an empty, it maybe a new child of the list.
+ //
+ offset := lastOffset(node)
+ lastIsEmpty := node.LastChild().ChildCount() == 0
+ indent, _ := util.IndentWidth(line, reader.LineOffset())
+
+ if indent < offset || lastIsEmpty {
+ if indent < 4 {
+ match, typ := matchesListItem(line, false) // may have a leading spaces more than 3
+ if typ != notList && match[1]-offset < 4 {
+ marker := line[match[3]-1]
+ if !list.CanContinue(marker, typ == orderedList) {
+ return Close
+ }
+ // Thematic Breaks take precedence over lists
+ if isThematicBreak(line[match[3]-1:], 0) {
+ isHeading := false
+ last := pc.LastOpenedBlock().Node
+ if ast.IsParagraph(last) {
+ c, ok := matchesSetextHeadingBar(line[match[3]-1:])
+ if ok && c == '-' {
+ isHeading = true
+ }
+ }
+ if !isHeading {
+ return Close
+ }
+ }
+ return Continue | HasChildren
+ }
+ }
+ if !lastIsEmpty {
+ return Close
+ }
+ }
+
+ // Non empty items can not exist next to an empty list item
+ // with blank lines. So we need to close the current list
+ //
+ // -
+ //
+ // foo
+ //
+ // -> 1 list with 1 blank items and 1 paragraph
+ if pc.Get(emptyListItemWithBlankLines) != nil {
+ return Close
+ }
+ return Continue | HasChildren
+}
+
+func (b *listParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ list := node.(*ast.List)
+
+ for c := node.FirstChild(); c != nil && list.IsTight; c = c.NextSibling() {
+ if c.FirstChild() != nil && c.FirstChild() != c.LastChild() {
+ for c1 := c.FirstChild().NextSibling(); c1 != nil; c1 = c1.NextSibling() {
+ if bl, ok := c1.(ast.Node); ok && bl.HasBlankPreviousLines() {
+ list.IsTight = false
+ break
+ }
+ }
+ }
+ if c != node.FirstChild() {
+ if bl, ok := c.(ast.Node); ok && bl.HasBlankPreviousLines() {
+ list.IsTight = false
+ }
+ }
+ }
+
+ if list.IsTight {
+ for child := node.FirstChild(); child != nil; child = child.NextSibling() {
+ for gc := child.FirstChild(); gc != nil; {
+ paragraph, ok := gc.(*ast.Paragraph)
+ gc = gc.NextSibling()
+ if ok {
+ textBlock := ast.NewTextBlock()
+ textBlock.SetLines(paragraph.Lines())
+ child.ReplaceChild(child, paragraph, textBlock)
+ }
+ }
+ }
+ }
+}
+
+func (b *listParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *listParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/list_item.go b/vendor/github.com/yuin/goldmark/parser/list_item.go
new file mode 100644
index 0000000..81357a9
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/list_item.go
@@ -0,0 +1,90 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type listItemParser struct {
+}
+
+var defaultListItemParser = &listItemParser{}
+
+// NewListItemParser returns a new BlockParser that
+// parses list items.
+func NewListItemParser() BlockParser {
+ return defaultListItemParser
+}
+
+func (b *listItemParser) Trigger() []byte {
+ return []byte{'-', '+', '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
+}
+
+func (b *listItemParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ list, lok := parent.(*ast.List)
+ if !lok { // list item must be a child of a list
+ return nil, NoChildren
+ }
+ offset := lastOffset(list)
+ line, _ := reader.PeekLine()
+ match, typ := matchesListItem(line, false)
+ if typ == notList {
+ return nil, NoChildren
+ }
+ if match[1]-offset > 3 {
+ return nil, NoChildren
+ }
+
+ pc.Set(emptyListItemWithBlankLines, nil)
+
+ itemOffset := calcListOffset(line, match)
+ node := ast.NewListItem(match[3] + itemOffset)
+ if match[4] < 0 || util.IsBlank(line[match[4]:match[5]]) {
+ return node, NoChildren
+ }
+
+ pos, padding := util.IndentPosition(line[match[4]:], match[4], itemOffset)
+ child := match[3] + pos
+ reader.AdvanceAndSetPadding(child, padding)
+ return node, HasChildren
+}
+
+func (b *listItemParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ line, _ := reader.PeekLine()
+ if util.IsBlank(line) {
+ reader.Advance(len(line) - 1)
+ return Continue | HasChildren
+ }
+
+ offset := lastOffset(node.Parent())
+ isEmpty := node.ChildCount() == 0
+ indent, _ := util.IndentWidth(line, reader.LineOffset())
+ if (isEmpty || indent < offset) && indent < 4 {
+ _, typ := matchesListItem(line, true)
+ // new list item found
+ if typ != notList {
+ pc.Set(skipListParserKey, listItemFlagValue)
+ return Close
+ }
+ if !isEmpty {
+ return Close
+ }
+ }
+ pos, padding := util.IndentPosition(line, reader.LineOffset(), offset)
+ reader.AdvanceAndSetPadding(pos, padding)
+
+ return Continue | HasChildren
+}
+
+func (b *listItemParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ // nothing to do
+}
+
+func (b *listItemParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *listItemParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/paragraph.go b/vendor/github.com/yuin/goldmark/parser/paragraph.go
new file mode 100644
index 0000000..2dd2b9a
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/paragraph.go
@@ -0,0 +1,71 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+)
+
+type paragraphParser struct {
+}
+
+var defaultParagraphParser = ¶graphParser{}
+
+// NewParagraphParser returns a new BlockParser that
+// parses paragraphs.
+func NewParagraphParser() BlockParser {
+ return defaultParagraphParser
+}
+
+func (b *paragraphParser) Trigger() []byte {
+ return nil
+}
+
+func (b *paragraphParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ _, segment := reader.PeekLine()
+ segment = segment.TrimLeftSpace(reader.Source())
+ if segment.IsEmpty() {
+ return nil, NoChildren
+ }
+ node := ast.NewParagraph()
+ node.Lines().Append(segment)
+ reader.Advance(segment.Len() - 1)
+ return node, NoChildren
+}
+
+func (b *paragraphParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ _, segment := reader.PeekLine()
+ segment = segment.TrimLeftSpace(reader.Source())
+ if segment.IsEmpty() {
+ return Close
+ }
+ node.Lines().Append(segment)
+ reader.Advance(segment.Len() - 1)
+ return Continue | NoChildren
+}
+
+func (b *paragraphParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ parent := node.Parent()
+ if parent == nil {
+ // paragraph has been transformed
+ return
+ }
+ lines := node.Lines()
+ if lines.Len() != 0 {
+ // trim trailing spaces
+ length := lines.Len()
+ lastLine := node.Lines().At(length - 1)
+ node.Lines().Set(length-1, lastLine.TrimRightSpace(reader.Source()))
+ }
+ if lines.Len() == 0 {
+ node.Parent().RemoveChild(node.Parent(), node)
+ return
+ }
+}
+
+func (b *paragraphParser) CanInterruptParagraph() bool {
+ return false
+}
+
+func (b *paragraphParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/parser.go b/vendor/github.com/yuin/goldmark/parser/parser.go
new file mode 100644
index 0000000..bac0704
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/parser.go
@@ -0,0 +1,1236 @@
+// Package parser contains stuff that are related to parsing a Markdown text.
+package parser
+
+import (
+ "fmt"
+ "strings"
+ "sync"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+// A Reference interface represents a link reference in Markdown text.
+type Reference interface {
+ // String implements Stringer.
+ String() string
+
+ // Label returns a label of the reference.
+ Label() []byte
+
+ // Destination returns a destination(URL) of the reference.
+ Destination() []byte
+
+ // Title returns a title of the reference.
+ Title() []byte
+}
+
+type reference struct {
+ label []byte
+ destination []byte
+ title []byte
+}
+
+// NewReference returns a new Reference.
+func NewReference(label, destination, title []byte) Reference {
+ return &reference{label, destination, title}
+}
+
+func (r *reference) Label() []byte {
+ return r.label
+}
+
+func (r *reference) Destination() []byte {
+ return r.destination
+}
+
+func (r *reference) Title() []byte {
+ return r.title
+}
+
+func (r *reference) String() string {
+ return fmt.Sprintf("Reference{Label:%s, Destination:%s, Title:%s}", r.label, r.destination, r.title)
+}
+
+// An IDs interface is a collection of the element ids.
+type IDs interface {
+ // Generate generates a new element id.
+ Generate(value []byte, kind ast.NodeKind) []byte
+
+ // Put puts a given element id to the used ids table.
+ Put(value []byte)
+}
+
+type ids struct {
+ values map[string]bool
+}
+
+func newIDs() IDs {
+ return &ids{
+ values: map[string]bool{},
+ }
+}
+
+func (s *ids) Generate(value []byte, kind ast.NodeKind) []byte {
+ value = util.TrimLeftSpace(value)
+ value = util.TrimRightSpace(value)
+ result := []byte{}
+ for i := 0; i < len(value); {
+ v := value[i]
+ l := util.UTF8Len(v)
+ i += int(l)
+ if l != 1 {
+ continue
+ }
+ if util.IsAlphaNumeric(v) {
+ if 'A' <= v && v <= 'Z' {
+ v += 'a' - 'A'
+ }
+ result = append(result, v)
+ } else if util.IsSpace(v) || v == '-' || v == '_' {
+ result = append(result, '-')
+ }
+ }
+ if len(result) == 0 {
+ if kind == ast.KindHeading {
+ result = []byte("heading")
+ } else {
+ result = []byte("id")
+ }
+ }
+ if _, ok := s.values[util.BytesToReadOnlyString(result)]; !ok {
+ s.values[util.BytesToReadOnlyString(result)] = true
+ return result
+ }
+ for i := 1; ; i++ {
+ newResult := fmt.Sprintf("%s-%d", result, i)
+ if _, ok := s.values[newResult]; !ok {
+ s.values[newResult] = true
+ return []byte(newResult)
+ }
+
+ }
+}
+
+func (s *ids) Put(value []byte) {
+ s.values[util.BytesToReadOnlyString(value)] = true
+}
+
+// ContextKey is a key that is used to set arbitrary values to the context.
+type ContextKey int
+
+// ContextKeyMax is a maximum value of the ContextKey.
+var ContextKeyMax ContextKey
+
+// NewContextKey return a new ContextKey value.
+func NewContextKey() ContextKey {
+ ContextKeyMax++
+ return ContextKeyMax
+}
+
+// A Context interface holds a information that are necessary to parse
+// Markdown text.
+type Context interface {
+ // String implements Stringer.
+ String() string
+
+ // Get returns a value associated with the given key.
+ Get(ContextKey) interface{}
+
+ // ComputeIfAbsent computes a value if a value associated with the given key is absent and returns the value.
+ ComputeIfAbsent(ContextKey, func() interface{}) interface{}
+
+ // Set sets the given value to the context.
+ Set(ContextKey, interface{})
+
+ // AddReference adds the given reference to this context.
+ AddReference(Reference)
+
+ // Reference returns (a reference, true) if a reference associated with
+ // the given label exists, otherwise (nil, false).
+ Reference(label string) (Reference, bool)
+
+ // References returns a list of references.
+ References() []Reference
+
+ // IDs returns a collection of the element ids.
+ IDs() IDs
+
+ // BlockOffset returns a first non-space character position on current line.
+ // This value is valid only for BlockParser.Open.
+ // BlockOffset returns -1 if current line is blank.
+ BlockOffset() int
+
+ // BlockOffset sets a first non-space character position on current line.
+ // This value is valid only for BlockParser.Open.
+ SetBlockOffset(int)
+
+ // BlockIndent returns an indent width on current line.
+ // This value is valid only for BlockParser.Open.
+ // BlockIndent returns -1 if current line is blank.
+ BlockIndent() int
+
+ // BlockIndent sets an indent width on current line.
+ // This value is valid only for BlockParser.Open.
+ SetBlockIndent(int)
+
+ // FirstDelimiter returns a first delimiter of the current delimiter list.
+ FirstDelimiter() *Delimiter
+
+ // LastDelimiter returns a last delimiter of the current delimiter list.
+ LastDelimiter() *Delimiter
+
+ // PushDelimiter appends the given delimiter to the tail of the current
+ // delimiter list.
+ PushDelimiter(delimiter *Delimiter)
+
+ // RemoveDelimiter removes the given delimiter from the current delimiter list.
+ RemoveDelimiter(d *Delimiter)
+
+ // ClearDelimiters clears the current delimiter list.
+ ClearDelimiters(bottom ast.Node)
+
+ // OpenedBlocks returns a list of nodes that are currently in parsing.
+ OpenedBlocks() []Block
+
+ // SetOpenedBlocks sets a list of nodes that are currently in parsing.
+ SetOpenedBlocks([]Block)
+
+ // LastOpenedBlock returns a last node that is currently in parsing.
+ LastOpenedBlock() Block
+
+ // IsInLinkLabel returns true if current position seems to be in link label.
+ IsInLinkLabel() bool
+}
+
+// A ContextConfig struct is a data structure that holds configuration of the Context.
+type ContextConfig struct {
+ IDs IDs
+}
+
+// An ContextOption is a functional option type for the Context.
+type ContextOption func(*ContextConfig)
+
+// WithIDs is a functional option for the Context.
+func WithIDs(ids IDs) ContextOption {
+ return func(c *ContextConfig) {
+ c.IDs = ids
+ }
+}
+
+type parseContext struct {
+ store []interface{}
+ ids IDs
+ refs map[string]Reference
+ blockOffset int
+ blockIndent int
+ delimiters *Delimiter
+ lastDelimiter *Delimiter
+ openedBlocks []Block
+}
+
+// NewContext returns a new Context.
+func NewContext(options ...ContextOption) Context {
+ cfg := &ContextConfig{
+ IDs: newIDs(),
+ }
+ for _, option := range options {
+ option(cfg)
+ }
+
+ return &parseContext{
+ store: make([]interface{}, ContextKeyMax+1),
+ refs: map[string]Reference{},
+ ids: cfg.IDs,
+ blockOffset: -1,
+ blockIndent: -1,
+ delimiters: nil,
+ lastDelimiter: nil,
+ openedBlocks: []Block{},
+ }
+}
+
+func (p *parseContext) Get(key ContextKey) interface{} {
+ return p.store[key]
+}
+
+func (p *parseContext) ComputeIfAbsent(key ContextKey, f func() interface{}) interface{} {
+ v := p.store[key]
+ if v == nil {
+ v = f()
+ p.store[key] = v
+ }
+ return v
+}
+
+func (p *parseContext) Set(key ContextKey, value interface{}) {
+ p.store[key] = value
+}
+
+func (p *parseContext) IDs() IDs {
+ return p.ids
+}
+
+func (p *parseContext) BlockOffset() int {
+ return p.blockOffset
+}
+
+func (p *parseContext) SetBlockOffset(v int) {
+ p.blockOffset = v
+}
+
+func (p *parseContext) BlockIndent() int {
+ return p.blockIndent
+}
+
+func (p *parseContext) SetBlockIndent(v int) {
+ p.blockIndent = v
+}
+
+func (p *parseContext) LastDelimiter() *Delimiter {
+ return p.lastDelimiter
+}
+
+func (p *parseContext) FirstDelimiter() *Delimiter {
+ return p.delimiters
+}
+
+func (p *parseContext) PushDelimiter(d *Delimiter) {
+ if p.delimiters == nil {
+ p.delimiters = d
+ p.lastDelimiter = d
+ } else {
+ l := p.lastDelimiter
+ p.lastDelimiter = d
+ l.NextDelimiter = d
+ d.PreviousDelimiter = l
+ }
+}
+
+func (p *parseContext) RemoveDelimiter(d *Delimiter) {
+ if d.PreviousDelimiter == nil {
+ p.delimiters = d.NextDelimiter
+ } else {
+ d.PreviousDelimiter.NextDelimiter = d.NextDelimiter
+ if d.NextDelimiter != nil {
+ d.NextDelimiter.PreviousDelimiter = d.PreviousDelimiter
+ }
+ }
+ if d.NextDelimiter == nil {
+ p.lastDelimiter = d.PreviousDelimiter
+ }
+ if p.delimiters != nil {
+ p.delimiters.PreviousDelimiter = nil
+ }
+ if p.lastDelimiter != nil {
+ p.lastDelimiter.NextDelimiter = nil
+ }
+ d.NextDelimiter = nil
+ d.PreviousDelimiter = nil
+ if d.Length != 0 {
+ ast.MergeOrReplaceTextSegment(d.Parent(), d, d.Segment)
+ } else {
+ d.Parent().RemoveChild(d.Parent(), d)
+ }
+}
+
+func (p *parseContext) ClearDelimiters(bottom ast.Node) {
+ if p.lastDelimiter == nil {
+ return
+ }
+ var c ast.Node
+ for c = p.lastDelimiter; c != nil && c != bottom; {
+ prev := c.PreviousSibling()
+ if d, ok := c.(*Delimiter); ok {
+ p.RemoveDelimiter(d)
+ }
+ c = prev
+ }
+}
+
+func (p *parseContext) AddReference(ref Reference) {
+ key := util.ToLinkReference(ref.Label())
+ if _, ok := p.refs[key]; !ok {
+ p.refs[key] = ref
+ }
+}
+
+func (p *parseContext) Reference(label string) (Reference, bool) {
+ v, ok := p.refs[label]
+ return v, ok
+}
+
+func (p *parseContext) References() []Reference {
+ ret := make([]Reference, 0, len(p.refs))
+ for _, v := range p.refs {
+ ret = append(ret, v)
+ }
+ return ret
+}
+
+func (p *parseContext) String() string {
+ refs := []string{}
+ for _, r := range p.refs {
+ refs = append(refs, r.String())
+ }
+
+ return fmt.Sprintf("Context{Store:%#v, Refs:%s}", p.store, strings.Join(refs, ","))
+}
+
+func (p *parseContext) OpenedBlocks() []Block {
+ return p.openedBlocks
+}
+
+func (p *parseContext) SetOpenedBlocks(v []Block) {
+ p.openedBlocks = v
+}
+
+func (p *parseContext) LastOpenedBlock() Block {
+ if l := len(p.openedBlocks); l != 0 {
+ return p.openedBlocks[l-1]
+ }
+ return Block{}
+}
+
+func (p *parseContext) IsInLinkLabel() bool {
+ tlist := p.Get(linkLabelStateKey)
+ return tlist != nil
+}
+
+// State represents parser's state.
+// State is designed to use as a bit flag.
+type State int
+
+const (
+ none State = 1 << iota
+
+ // Continue indicates parser can continue parsing.
+ Continue
+
+ // Close indicates parser cannot parse anymore.
+ Close
+
+ // HasChildren indicates parser may have child blocks.
+ HasChildren
+
+ // NoChildren indicates parser does not have child blocks.
+ NoChildren
+
+ // RequireParagraph indicates parser requires that the last node
+ // must be a paragraph and is not converted to other nodes by
+ // ParagraphTransformers.
+ RequireParagraph
+)
+
+// A Config struct is a data structure that holds configuration of the Parser.
+type Config struct {
+ Options map[OptionName]interface{}
+ BlockParsers util.PrioritizedSlice /**/
+ InlineParsers util.PrioritizedSlice /**/
+ ParagraphTransformers util.PrioritizedSlice /**/
+ ASTTransformers util.PrioritizedSlice /**/
+}
+
+// NewConfig returns a new Config.
+func NewConfig() *Config {
+ return &Config{
+ Options: map[OptionName]interface{}{},
+ BlockParsers: util.PrioritizedSlice{},
+ InlineParsers: util.PrioritizedSlice{},
+ ParagraphTransformers: util.PrioritizedSlice{},
+ ASTTransformers: util.PrioritizedSlice{},
+ }
+}
+
+// An Option interface is a functional option type for the Parser.
+type Option interface {
+ SetParserOption(*Config)
+}
+
+// OptionName is a name of parser options.
+type OptionName string
+
+// Attribute is an option name that spacify attributes of elements.
+const optAttribute OptionName = "Attribute"
+
+type withAttribute struct {
+}
+
+func (o *withAttribute) SetParserOption(c *Config) {
+ c.Options[optAttribute] = true
+}
+
+// WithAttribute is a functional option that enables custom attributes.
+func WithAttribute() Option {
+ return &withAttribute{}
+}
+
+// A Parser interface parses Markdown text into AST nodes.
+type Parser interface {
+ // Parse parses the given Markdown text into AST nodes.
+ Parse(reader text.Reader, opts ...ParseOption) ast.Node
+
+ // AddOption adds the given option to this parser.
+ AddOptions(...Option)
+}
+
+// A SetOptioner interface sets the given option to the object.
+type SetOptioner interface {
+ // SetOption sets the given option to the object.
+ // Unacceptable options may be passed.
+ // Thus implementations must ignore unacceptable options.
+ SetOption(name OptionName, value interface{})
+}
+
+// A BlockParser interface parses a block level element like Paragraph, List,
+// Blockquote etc.
+type BlockParser interface {
+ // Trigger returns a list of characters that triggers Parse method of
+ // this parser.
+ // If Trigger returns a nil, Open will be called with any lines.
+ Trigger() []byte
+
+ // Open parses the current line and returns a result of parsing.
+ //
+ // Open must not parse beyond the current line.
+ // If Open has been able to parse the current line, Open must advance a reader
+ // position by consumed byte length.
+ //
+ // If Open has not been able to parse the current line, Open should returns
+ // (nil, NoChildren). If Open has been able to parse the current line, Open
+ // should returns a new Block node and returns HasChildren or NoChildren.
+ Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State)
+
+ // Continue parses the current line and returns a result of parsing.
+ //
+ // Continue must not parse beyond the current line.
+ // If Continue has been able to parse the current line, Continue must advance
+ // a reader position by consumed byte length.
+ //
+ // If Continue has not been able to parse the current line, Continue should
+ // returns Close. If Continue has been able to parse the current line,
+ // Continue should returns (Continue | NoChildren) or
+ // (Continue | HasChildren)
+ Continue(node ast.Node, reader text.Reader, pc Context) State
+
+ // Close will be called when the parser returns Close.
+ Close(node ast.Node, reader text.Reader, pc Context)
+
+ // CanInterruptParagraph returns true if the parser can interrupt paragraphs,
+ // otherwise false.
+ CanInterruptParagraph() bool
+
+ // CanAcceptIndentedLine returns true if the parser can open new node when
+ // the given line is being indented more than 3 spaces.
+ CanAcceptIndentedLine() bool
+}
+
+// An InlineParser interface parses an inline level element like CodeSpan, Link etc.
+type InlineParser interface {
+ // Trigger returns a list of characters that triggers Parse method of
+ // this parser.
+ // Trigger characters must be a punctuation or a halfspace.
+ // Halfspaces triggers this parser when character is any spaces characters or
+ // a head of line
+ Trigger() []byte
+
+ // Parse parse the given block into an inline node.
+ //
+ // Parse can parse beyond the current line.
+ // If Parse has been able to parse the current line, it must advance a reader
+ // position by consumed byte length.
+ Parse(parent ast.Node, block text.Reader, pc Context) ast.Node
+}
+
+// A CloseBlocker interface is a callback function that will be
+// called when block is closed in the inline parsing.
+type CloseBlocker interface {
+ // CloseBlock will be called when a block is closed.
+ CloseBlock(parent ast.Node, block text.Reader, pc Context)
+}
+
+// A ParagraphTransformer transforms parsed Paragraph nodes.
+// For example, link references are searched in parsed Paragraphs.
+type ParagraphTransformer interface {
+ // Transform transforms the given paragraph.
+ Transform(node *ast.Paragraph, reader text.Reader, pc Context)
+}
+
+// ASTTransformer transforms entire Markdown document AST tree.
+type ASTTransformer interface {
+ // Transform transforms the given AST tree.
+ Transform(node *ast.Document, reader text.Reader, pc Context)
+}
+
+// DefaultBlockParsers returns a new list of default BlockParsers.
+// Priorities of default BlockParsers are:
+//
+// SetextHeadingParser, 100
+// ThematicBreakParser, 200
+// ListParser, 300
+// ListItemParser, 400
+// CodeBlockParser, 500
+// ATXHeadingParser, 600
+// FencedCodeBlockParser, 700
+// BlockquoteParser, 800
+// HTMLBlockParser, 900
+// ParagraphParser, 1000
+func DefaultBlockParsers() []util.PrioritizedValue {
+ return []util.PrioritizedValue{
+ util.Prioritized(NewSetextHeadingParser(), 100),
+ util.Prioritized(NewThematicBreakParser(), 200),
+ util.Prioritized(NewListParser(), 300),
+ util.Prioritized(NewListItemParser(), 400),
+ util.Prioritized(NewCodeBlockParser(), 500),
+ util.Prioritized(NewATXHeadingParser(), 600),
+ util.Prioritized(NewFencedCodeBlockParser(), 700),
+ util.Prioritized(NewBlockquoteParser(), 800),
+ util.Prioritized(NewHTMLBlockParser(), 900),
+ util.Prioritized(NewParagraphParser(), 1000),
+ }
+}
+
+// DefaultInlineParsers returns a new list of default InlineParsers.
+// Priorities of default InlineParsers are:
+//
+// CodeSpanParser, 100
+// LinkParser, 200
+// AutoLinkParser, 300
+// RawHTMLParser, 400
+// EmphasisParser, 500
+func DefaultInlineParsers() []util.PrioritizedValue {
+ return []util.PrioritizedValue{
+ util.Prioritized(NewCodeSpanParser(), 100),
+ util.Prioritized(NewLinkParser(), 200),
+ util.Prioritized(NewAutoLinkParser(), 300),
+ util.Prioritized(NewRawHTMLParser(), 400),
+ util.Prioritized(NewEmphasisParser(), 500),
+ }
+}
+
+// DefaultParagraphTransformers returns a new list of default ParagraphTransformers.
+// Priorities of default ParagraphTransformers are:
+//
+// LinkReferenceParagraphTransformer, 100
+func DefaultParagraphTransformers() []util.PrioritizedValue {
+ return []util.PrioritizedValue{
+ util.Prioritized(LinkReferenceParagraphTransformer, 100),
+ }
+}
+
+// A Block struct holds a node and correspond parser pair.
+type Block struct {
+ // Node is a BlockNode.
+ Node ast.Node
+ // Parser is a BlockParser.
+ Parser BlockParser
+}
+
+type parser struct {
+ options map[OptionName]interface{}
+ blockParsers [256][]BlockParser
+ freeBlockParsers []BlockParser
+ inlineParsers [256][]InlineParser
+ closeBlockers []CloseBlocker
+ paragraphTransformers []ParagraphTransformer
+ astTransformers []ASTTransformer
+ config *Config
+ initSync sync.Once
+}
+
+type withBlockParsers struct {
+ value []util.PrioritizedValue
+}
+
+func (o *withBlockParsers) SetParserOption(c *Config) {
+ c.BlockParsers = append(c.BlockParsers, o.value...)
+}
+
+// WithBlockParsers is a functional option that allow you to add
+// BlockParsers to the parser.
+func WithBlockParsers(bs ...util.PrioritizedValue) Option {
+ return &withBlockParsers{bs}
+}
+
+type withInlineParsers struct {
+ value []util.PrioritizedValue
+}
+
+func (o *withInlineParsers) SetParserOption(c *Config) {
+ c.InlineParsers = append(c.InlineParsers, o.value...)
+}
+
+// WithInlineParsers is a functional option that allow you to add
+// InlineParsers to the parser.
+func WithInlineParsers(bs ...util.PrioritizedValue) Option {
+ return &withInlineParsers{bs}
+}
+
+type withParagraphTransformers struct {
+ value []util.PrioritizedValue
+}
+
+func (o *withParagraphTransformers) SetParserOption(c *Config) {
+ c.ParagraphTransformers = append(c.ParagraphTransformers, o.value...)
+}
+
+// WithParagraphTransformers is a functional option that allow you to add
+// ParagraphTransformers to the parser.
+func WithParagraphTransformers(ps ...util.PrioritizedValue) Option {
+ return &withParagraphTransformers{ps}
+}
+
+type withASTTransformers struct {
+ value []util.PrioritizedValue
+}
+
+func (o *withASTTransformers) SetParserOption(c *Config) {
+ c.ASTTransformers = append(c.ASTTransformers, o.value...)
+}
+
+// WithASTTransformers is a functional option that allow you to add
+// ASTTransformers to the parser.
+func WithASTTransformers(ps ...util.PrioritizedValue) Option {
+ return &withASTTransformers{ps}
+}
+
+type withOption struct {
+ name OptionName
+ value interface{}
+}
+
+func (o *withOption) SetParserOption(c *Config) {
+ c.Options[o.name] = o.value
+}
+
+// WithOption is a functional option that allow you to set
+// an arbitrary option to the parser.
+func WithOption(name OptionName, value interface{}) Option {
+ return &withOption{name, value}
+}
+
+// NewParser returns a new Parser with given options.
+func NewParser(options ...Option) Parser {
+ config := NewConfig()
+ for _, opt := range options {
+ opt.SetParserOption(config)
+ }
+
+ p := &parser{
+ options: map[OptionName]interface{}{},
+ config: config,
+ }
+
+ return p
+}
+
+func (p *parser) AddOptions(opts ...Option) {
+ for _, opt := range opts {
+ opt.SetParserOption(p.config)
+ }
+}
+
+func (p *parser) addBlockParser(v util.PrioritizedValue, options map[OptionName]interface{}) {
+ bp, ok := v.Value.(BlockParser)
+ if !ok {
+ panic(fmt.Sprintf("%v is not a BlockParser", v.Value))
+ }
+ tcs := bp.Trigger()
+ so, ok := v.Value.(SetOptioner)
+ if ok {
+ for oname, ovalue := range options {
+ so.SetOption(oname, ovalue)
+ }
+ }
+ if tcs == nil {
+ p.freeBlockParsers = append(p.freeBlockParsers, bp)
+ } else {
+ for _, tc := range tcs {
+ if p.blockParsers[tc] == nil {
+ p.blockParsers[tc] = []BlockParser{}
+ }
+ p.blockParsers[tc] = append(p.blockParsers[tc], bp)
+ }
+ }
+}
+
+func (p *parser) addInlineParser(v util.PrioritizedValue, options map[OptionName]interface{}) {
+ ip, ok := v.Value.(InlineParser)
+ if !ok {
+ panic(fmt.Sprintf("%v is not a InlineParser", v.Value))
+ }
+ tcs := ip.Trigger()
+ so, ok := v.Value.(SetOptioner)
+ if ok {
+ for oname, ovalue := range options {
+ so.SetOption(oname, ovalue)
+ }
+ }
+ if cb, ok := ip.(CloseBlocker); ok {
+ p.closeBlockers = append(p.closeBlockers, cb)
+ }
+ for _, tc := range tcs {
+ if p.inlineParsers[tc] == nil {
+ p.inlineParsers[tc] = []InlineParser{}
+ }
+ p.inlineParsers[tc] = append(p.inlineParsers[tc], ip)
+ }
+}
+
+func (p *parser) addParagraphTransformer(v util.PrioritizedValue, options map[OptionName]interface{}) {
+ pt, ok := v.Value.(ParagraphTransformer)
+ if !ok {
+ panic(fmt.Sprintf("%v is not a ParagraphTransformer", v.Value))
+ }
+ so, ok := v.Value.(SetOptioner)
+ if ok {
+ for oname, ovalue := range options {
+ so.SetOption(oname, ovalue)
+ }
+ }
+ p.paragraphTransformers = append(p.paragraphTransformers, pt)
+}
+
+func (p *parser) addASTTransformer(v util.PrioritizedValue, options map[OptionName]interface{}) {
+ at, ok := v.Value.(ASTTransformer)
+ if !ok {
+ panic(fmt.Sprintf("%v is not a ASTTransformer", v.Value))
+ }
+ so, ok := v.Value.(SetOptioner)
+ if ok {
+ for oname, ovalue := range options {
+ so.SetOption(oname, ovalue)
+ }
+ }
+ p.astTransformers = append(p.astTransformers, at)
+}
+
+// A ParseConfig struct is a data structure that holds configuration of the Parser.Parse.
+type ParseConfig struct {
+ Context Context
+}
+
+// A ParseOption is a functional option type for the Parser.Parse.
+type ParseOption func(c *ParseConfig)
+
+// WithContext is a functional option that allow you to override
+// a default context.
+func WithContext(context Context) ParseOption {
+ return func(c *ParseConfig) {
+ c.Context = context
+ }
+}
+
+func (p *parser) Parse(reader text.Reader, opts ...ParseOption) ast.Node {
+ p.initSync.Do(func() {
+ p.config.BlockParsers.Sort()
+ for _, v := range p.config.BlockParsers {
+ p.addBlockParser(v, p.config.Options)
+ }
+ for i := range p.blockParsers {
+ if p.blockParsers[i] != nil {
+ p.blockParsers[i] = append(p.blockParsers[i], p.freeBlockParsers...)
+ }
+ }
+
+ p.config.InlineParsers.Sort()
+ for _, v := range p.config.InlineParsers {
+ p.addInlineParser(v, p.config.Options)
+ }
+ p.config.ParagraphTransformers.Sort()
+ for _, v := range p.config.ParagraphTransformers {
+ p.addParagraphTransformer(v, p.config.Options)
+ }
+ p.config.ASTTransformers.Sort()
+ for _, v := range p.config.ASTTransformers {
+ p.addASTTransformer(v, p.config.Options)
+ }
+ p.config = nil
+ })
+ c := &ParseConfig{}
+ for _, opt := range opts {
+ opt(c)
+ }
+ if c.Context == nil {
+ c.Context = NewContext()
+ }
+ pc := c.Context
+ root := ast.NewDocument()
+ p.parseBlocks(root, reader, pc)
+
+ blockReader := text.NewBlockReader(reader.Source(), nil)
+ p.walkBlock(root, func(node ast.Node) {
+ p.parseBlock(blockReader, node, pc)
+ })
+ for _, at := range p.astTransformers {
+ at.Transform(root, reader, pc)
+ }
+ // root.Dump(reader.Source(), 0)
+ return root
+}
+
+func (p *parser) transformParagraph(node *ast.Paragraph, reader text.Reader, pc Context) bool {
+ for _, pt := range p.paragraphTransformers {
+ pt.Transform(node, reader, pc)
+ if node.Parent() == nil {
+ return true
+ }
+ }
+ return false
+}
+
+func (p *parser) closeBlocks(from, to int, reader text.Reader, pc Context) {
+ blocks := pc.OpenedBlocks()
+ for i := from; i >= to; i-- {
+ node := blocks[i].Node
+ blocks[i].Parser.Close(blocks[i].Node, reader, pc)
+ paragraph, ok := node.(*ast.Paragraph)
+ if ok && node.Parent() != nil {
+ p.transformParagraph(paragraph, reader, pc)
+ }
+ }
+ if from == len(blocks)-1 {
+ blocks = blocks[0:to]
+ } else {
+ blocks = append(blocks[0:to], blocks[from+1:]...)
+ }
+ pc.SetOpenedBlocks(blocks)
+}
+
+type blockOpenResult int
+
+const (
+ paragraphContinuation blockOpenResult = iota + 1
+ newBlocksOpened
+ noBlocksOpened
+)
+
+func (p *parser) openBlocks(parent ast.Node, blankLine bool, reader text.Reader, pc Context) blockOpenResult {
+ result := blockOpenResult(noBlocksOpened)
+ continuable := false
+ lastBlock := pc.LastOpenedBlock()
+ if lastBlock.Node != nil {
+ continuable = ast.IsParagraph(lastBlock.Node)
+ }
+retry:
+ var bps []BlockParser
+ line, _ := reader.PeekLine()
+ w, pos := util.IndentWidth(line, reader.LineOffset())
+ if w >= len(line) {
+ pc.SetBlockOffset(-1)
+ pc.SetBlockIndent(-1)
+ } else {
+ pc.SetBlockOffset(pos)
+ pc.SetBlockIndent(w)
+ }
+ if line == nil || line[0] == '\n' {
+ goto continuable
+ }
+ bps = p.freeBlockParsers
+ if pos < len(line) {
+ bps = p.blockParsers[line[pos]]
+ if bps == nil {
+ bps = p.freeBlockParsers
+ }
+ }
+ if bps == nil {
+ goto continuable
+ }
+
+ for _, bp := range bps {
+ if continuable && result == noBlocksOpened && !bp.CanInterruptParagraph() {
+ continue
+ }
+ if w > 3 && !bp.CanAcceptIndentedLine() {
+ continue
+ }
+ lastBlock = pc.LastOpenedBlock()
+ last := lastBlock.Node
+ node, state := bp.Open(parent, reader, pc)
+ if node != nil {
+ // Parser requires last node to be a paragraph.
+ // With table extension:
+ //
+ // 0
+ // -:
+ // -
+ //
+ // '-' on 3rd line seems a Setext heading because 1st and 2nd lines
+ // are being paragraph when the Settext heading parser tries to parse the 3rd
+ // line.
+ // But 1st line and 2nd line are a table. Thus this paragraph will be transformed
+ // by a paragraph transformer. So this text should be converted to a table and
+ // an empty list.
+ if state&RequireParagraph != 0 {
+ if last == parent.LastChild() {
+ // Opened paragraph may be transformed by ParagraphTransformers in
+ // closeBlocks().
+ lastBlock.Parser.Close(last, reader, pc)
+ blocks := pc.OpenedBlocks()
+ pc.SetOpenedBlocks(blocks[0 : len(blocks)-1])
+ if p.transformParagraph(last.(*ast.Paragraph), reader, pc) {
+ // Paragraph has been transformed.
+ // So this parser is considered as failing.
+ continuable = false
+ goto retry
+ }
+ }
+ }
+ node.SetBlankPreviousLines(blankLine)
+ if last != nil && last.Parent() == nil {
+ lastPos := len(pc.OpenedBlocks()) - 1
+ p.closeBlocks(lastPos, lastPos, reader, pc)
+ }
+ parent.AppendChild(parent, node)
+ result = newBlocksOpened
+ be := Block{node, bp}
+ pc.SetOpenedBlocks(append(pc.OpenedBlocks(), be))
+ if state&HasChildren != 0 {
+ parent = node
+ goto retry // try child block
+ }
+ break // no children, can not open more blocks on this line
+ }
+ }
+
+continuable:
+ if result == noBlocksOpened && continuable {
+ state := lastBlock.Parser.Continue(lastBlock.Node, reader, pc)
+ if state&Continue != 0 {
+ result = paragraphContinuation
+ }
+ }
+ return result
+}
+
+type lineStat struct {
+ lineNum int
+ level int
+ isBlank bool
+}
+
+func isBlankLine(lineNum, level int, stats []lineStat) bool {
+ ret := true
+ for i := len(stats) - 1 - level; i >= 0; i-- {
+ ret = false
+ s := stats[i]
+ if s.lineNum == lineNum {
+ if s.level < level && s.isBlank {
+ return true
+ } else if s.level == level {
+ return s.isBlank
+ }
+ }
+ if s.lineNum < lineNum {
+ return ret
+ }
+ }
+ return ret
+}
+
+func (p *parser) parseBlocks(parent ast.Node, reader text.Reader, pc Context) {
+ pc.SetOpenedBlocks([]Block{})
+ blankLines := make([]lineStat, 0, 128)
+ isBlank := false
+ for { // process blocks separated by blank lines
+ _, lines, ok := reader.SkipBlankLines()
+ if !ok {
+ return
+ }
+ lineNum, _ := reader.Position()
+ if lines != 0 {
+ blankLines = blankLines[0:0]
+ l := len(pc.OpenedBlocks())
+ for i := 0; i < l; i++ {
+ blankLines = append(blankLines, lineStat{lineNum - 1, i, lines != 0})
+ }
+ }
+ isBlank = isBlankLine(lineNum-1, 0, blankLines)
+ // first, we try to open blocks
+ if p.openBlocks(parent, isBlank, reader, pc) != newBlocksOpened {
+ return
+ }
+ reader.AdvanceLine()
+ for { // process opened blocks line by line
+ openedBlocks := pc.OpenedBlocks()
+ l := len(openedBlocks)
+ if l == 0 {
+ break
+ }
+ lastIndex := l - 1
+ for i := 0; i < l; i++ {
+ be := openedBlocks[i]
+ line, _ := reader.PeekLine()
+ if line == nil {
+ p.closeBlocks(lastIndex, 0, reader, pc)
+ reader.AdvanceLine()
+ return
+ }
+ lineNum, _ := reader.Position()
+ blankLines = append(blankLines, lineStat{lineNum, i, util.IsBlank(line)})
+ // If node is a paragraph, p.openBlocks determines whether it is continuable.
+ // So we do not process paragraphs here.
+ if !ast.IsParagraph(be.Node) {
+ state := be.Parser.Continue(be.Node, reader, pc)
+ if state&Continue != 0 {
+ // When current node is a container block and has no children,
+ // we try to open new child nodes
+ if state&HasChildren != 0 && i == lastIndex {
+ isBlank = isBlankLine(lineNum-1, i, blankLines)
+ p.openBlocks(be.Node, isBlank, reader, pc)
+ break
+ }
+ continue
+ }
+ }
+ // current node may be closed or lazy continuation
+ isBlank = isBlankLine(lineNum-1, i, blankLines)
+ thisParent := parent
+ if i != 0 {
+ thisParent = openedBlocks[i-1].Node
+ }
+ lastNode := openedBlocks[lastIndex].Node
+ result := p.openBlocks(thisParent, isBlank, reader, pc)
+ if result != paragraphContinuation {
+ // lastNode is a paragraph and was transformed by the paragraph
+ // transformers.
+ if openedBlocks[lastIndex].Node != lastNode {
+ lastIndex--
+ }
+ p.closeBlocks(lastIndex, i, reader, pc)
+ }
+ break
+ }
+
+ reader.AdvanceLine()
+ }
+ }
+}
+
+func (p *parser) walkBlock(block ast.Node, cb func(node ast.Node)) {
+ for c := block.FirstChild(); c != nil; c = c.NextSibling() {
+ p.walkBlock(c, cb)
+ }
+ cb(block)
+}
+
+const (
+ lineBreakHard uint8 = 1 << iota
+ lineBreakSoft
+ lineBreakVisible
+)
+
+func (p *parser) parseBlock(block text.BlockReader, parent ast.Node, pc Context) {
+ if parent.IsRaw() {
+ return
+ }
+ escaped := false
+ source := block.Source()
+ block.Reset(parent.Lines())
+ for {
+ retry:
+ line, _ := block.PeekLine()
+ if line == nil {
+ break
+ }
+ lineLength := len(line)
+ var lineBreakFlags uint8 = 0
+ hasNewLine := line[lineLength-1] == '\n'
+ if ((lineLength >= 3 && line[lineLength-2] == '\\' && line[lineLength-3] != '\\') || (lineLength == 2 && line[lineLength-2] == '\\')) && hasNewLine { // ends with \\n
+ lineLength -= 2
+ lineBreakFlags |= lineBreakHard | lineBreakVisible
+ } else if ((lineLength >= 4 && line[lineLength-3] == '\\' && line[lineLength-2] == '\r' && line[lineLength-4] != '\\') || (lineLength == 3 && line[lineLength-3] == '\\' && line[lineLength-2] == '\r')) && hasNewLine { // ends with \\r\n
+ lineLength -= 3
+ lineBreakFlags |= lineBreakHard | lineBreakVisible
+ } else if lineLength >= 3 && line[lineLength-3] == ' ' && line[lineLength-2] == ' ' && hasNewLine { // ends with [space][space]\n
+ lineLength -= 3
+ lineBreakFlags |= lineBreakHard
+ } else if lineLength >= 4 && line[lineLength-4] == ' ' && line[lineLength-3] == ' ' && line[lineLength-2] == '\r' && hasNewLine { // ends with [space][space]\r\n
+ lineLength -= 4
+ lineBreakFlags |= lineBreakHard
+ } else if hasNewLine {
+ // If the line ends with a newline character, but it is not a hardlineBreak, then it is a softLinebreak
+ // If the line ends with a hardlineBreak, then it cannot end with a softLinebreak
+ // See https://spec.commonmark.org/0.30/#soft-line-breaks
+ lineBreakFlags |= lineBreakSoft
+ }
+
+ l, startPosition := block.Position()
+ n := 0
+ for i := 0; i < lineLength; i++ {
+ c := line[i]
+ if c == '\n' {
+ break
+ }
+ isSpace := util.IsSpace(c)
+ isPunct := util.IsPunct(c)
+ if (isPunct && !escaped) || isSpace || i == 0 {
+ parserChar := c
+ if isSpace || (i == 0 && !isPunct) {
+ parserChar = ' '
+ }
+ ips := p.inlineParsers[parserChar]
+ if ips != nil {
+ block.Advance(n)
+ n = 0
+ savedLine, savedPosition := block.Position()
+ if i != 0 {
+ _, currentPosition := block.Position()
+ ast.MergeOrAppendTextSegment(parent, startPosition.Between(currentPosition))
+ _, startPosition = block.Position()
+ }
+ var inlineNode ast.Node
+ for _, ip := range ips {
+ inlineNode = ip.Parse(parent, block, pc)
+ if inlineNode != nil {
+ break
+ }
+ block.SetPosition(savedLine, savedPosition)
+ }
+ if inlineNode != nil {
+ parent.AppendChild(parent, inlineNode)
+ goto retry
+ }
+ }
+ }
+ if escaped {
+ escaped = false
+ n++
+ continue
+ }
+
+ if c == '\\' {
+ escaped = true
+ n++
+ continue
+ }
+
+ escaped = false
+ n++
+ }
+ if n != 0 {
+ block.Advance(n)
+ }
+ currentL, currentPosition := block.Position()
+ if l != currentL {
+ continue
+ }
+ diff := startPosition.Between(currentPosition)
+ var text *ast.Text
+ if lineBreakFlags&(lineBreakHard|lineBreakVisible) == lineBreakHard|lineBreakVisible {
+ text = ast.NewTextSegment(diff)
+ } else {
+ text = ast.NewTextSegment(diff.TrimRightSpace(source))
+ }
+ text.SetSoftLineBreak(lineBreakFlags&lineBreakSoft != 0)
+ text.SetHardLineBreak(lineBreakFlags&lineBreakHard != 0)
+ parent.AppendChild(parent, text)
+ block.AdvanceLine()
+ }
+
+ ProcessDelimiters(nil, pc)
+ for _, ip := range p.closeBlockers {
+ ip.CloseBlock(parent, block, pc)
+ }
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/raw_html.go b/vendor/github.com/yuin/goldmark/parser/raw_html.go
new file mode 100644
index 0000000..55b9a99
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/raw_html.go
@@ -0,0 +1,163 @@
+package parser
+
+import (
+ "bytes"
+ "regexp"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type rawHTMLParser struct {
+}
+
+var defaultRawHTMLParser = &rawHTMLParser{}
+
+// NewRawHTMLParser return a new InlineParser that can parse
+// inline htmls
+func NewRawHTMLParser() InlineParser {
+ return defaultRawHTMLParser
+}
+
+func (s *rawHTMLParser) Trigger() []byte {
+ return []byte{'<'}
+}
+
+func (s *rawHTMLParser) Parse(parent ast.Node, block text.Reader, pc Context) ast.Node {
+ line, _ := block.PeekLine()
+ if len(line) > 1 && util.IsAlphaNumeric(line[1]) {
+ return s.parseMultiLineRegexp(openTagRegexp, block, pc)
+ }
+ if len(line) > 2 && line[1] == '/' && util.IsAlphaNumeric(line[2]) {
+ return s.parseMultiLineRegexp(closeTagRegexp, block, pc)
+ }
+ if bytes.HasPrefix(line, openComment) {
+ return s.parseComment(block, pc)
+ }
+ if bytes.HasPrefix(line, openProcessingInstruction) {
+ return s.parseUntil(block, closeProcessingInstruction, pc)
+ }
+ if len(line) > 2 && line[1] == '!' && line[2] >= 'A' && line[2] <= 'Z' {
+ return s.parseUntil(block, closeDecl, pc)
+ }
+ if bytes.HasPrefix(line, openCDATA) {
+ return s.parseUntil(block, closeCDATA, pc)
+ }
+ return nil
+}
+
+var tagnamePattern = `([A-Za-z][A-Za-z0-9-]*)`
+
+var attributePattern = `(?:[\r\n \t]+[a-zA-Z_:][a-zA-Z0-9:._-]*(?:[\r\n \t]*=[\r\n \t]*(?:[^\"'=<>` + "`" + `\x00-\x20]+|'[^']*'|"[^"]*"))?)`
+var openTagRegexp = regexp.MustCompile("^<" + tagnamePattern + attributePattern + `*[ \t]*/?>`)
+var closeTagRegexp = regexp.MustCompile("^" + tagnamePattern + `\s*>`)
+
+var openProcessingInstruction = []byte("")
+var closeProcessingInstruction = []byte("?>")
+var openCDATA = []byte("")
+var closeDecl = []byte(">")
+var emptyComment = []byte("")
+var invalidComment1 = []byte("")
+var invalidComment2 = []byte("")
+var openComment = []byte("")
+var doubleHyphen = []byte("--")
+
+func (s *rawHTMLParser) parseComment(block text.Reader, pc Context) ast.Node {
+ savedLine, savedSegment := block.Position()
+ node := ast.NewRawHTML()
+ line, segment := block.PeekLine()
+ if bytes.HasPrefix(line, emptyComment) {
+ node.Segments.Append(segment.WithStop(segment.Start + len(emptyComment)))
+ block.Advance(len(emptyComment))
+ return node
+ }
+ if bytes.HasPrefix(line, invalidComment1) || bytes.HasPrefix(line, invalidComment2) {
+ return nil
+ }
+ offset := len(openComment)
+ line = line[offset:]
+ for {
+ hindex := bytes.Index(line, doubleHyphen)
+ if hindex > -1 {
+ hindex += offset
+ }
+ index := bytes.Index(line, closeComment) + offset
+ if index > -1 && hindex == index {
+ if index == 0 || len(line) < 2 || line[index-offset-1] != '-' {
+ node.Segments.Append(segment.WithStop(segment.Start + index + len(closeComment)))
+ block.Advance(index + len(closeComment))
+ return node
+ }
+ }
+ if hindex > 0 {
+ break
+ }
+ node.Segments.Append(segment)
+ block.AdvanceLine()
+ line, segment = block.PeekLine()
+ offset = 0
+ if line == nil {
+ break
+ }
+ }
+ block.SetPosition(savedLine, savedSegment)
+ return nil
+}
+
+func (s *rawHTMLParser) parseUntil(block text.Reader, closer []byte, pc Context) ast.Node {
+ savedLine, savedSegment := block.Position()
+ node := ast.NewRawHTML()
+ for {
+ line, segment := block.PeekLine()
+ if line == nil {
+ break
+ }
+ index := bytes.Index(line, closer)
+ if index > -1 {
+ node.Segments.Append(segment.WithStop(segment.Start + index + len(closer)))
+ block.Advance(index + len(closer))
+ return node
+ }
+ node.Segments.Append(segment)
+ block.AdvanceLine()
+ }
+ block.SetPosition(savedLine, savedSegment)
+ return nil
+}
+
+func (s *rawHTMLParser) parseMultiLineRegexp(reg *regexp.Regexp, block text.Reader, pc Context) ast.Node {
+ sline, ssegment := block.Position()
+ if block.Match(reg) {
+ node := ast.NewRawHTML()
+ eline, esegment := block.Position()
+ block.SetPosition(sline, ssegment)
+ for {
+ line, segment := block.PeekLine()
+ if line == nil {
+ break
+ }
+ l, _ := block.Position()
+ start := segment.Start
+ if l == sline {
+ start = ssegment.Start
+ }
+ end := segment.Stop
+ if l == eline {
+ end = esegment.Start
+ }
+
+ node.Segments.Append(text.NewSegment(start, end))
+ if l == eline {
+ block.Advance(end - start)
+ break
+ } else {
+ block.AdvanceLine()
+ }
+ }
+ return node
+ }
+ return nil
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/setext_headings.go b/vendor/github.com/yuin/goldmark/parser/setext_headings.go
new file mode 100644
index 0000000..686efe1
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/setext_headings.go
@@ -0,0 +1,126 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+var temporaryParagraphKey = NewContextKey()
+
+type setextHeadingParser struct {
+ HeadingConfig
+}
+
+func matchesSetextHeadingBar(line []byte) (byte, bool) {
+ start := 0
+ end := len(line)
+ space := util.TrimLeftLength(line, []byte{' '})
+ if space > 3 {
+ return 0, false
+ }
+ start += space
+ level1 := util.TrimLeftLength(line[start:end], []byte{'='})
+ c := byte('=')
+ var level2 int
+ if level1 == 0 {
+ level2 = util.TrimLeftLength(line[start:end], []byte{'-'})
+ c = '-'
+ }
+ if util.IsSpace(line[end-1]) {
+ end -= util.TrimRightSpaceLength(line[start:end])
+ }
+ if !((level1 > 0 && start+level1 == end) || (level2 > 0 && start+level2 == end)) {
+ return 0, false
+ }
+ return c, true
+}
+
+// NewSetextHeadingParser return a new BlockParser that can parse Setext headings.
+func NewSetextHeadingParser(opts ...HeadingOption) BlockParser {
+ p := &setextHeadingParser{}
+ for _, o := range opts {
+ o.SetHeadingOption(&p.HeadingConfig)
+ }
+ return p
+}
+
+func (b *setextHeadingParser) Trigger() []byte {
+ return []byte{'-', '='}
+}
+
+func (b *setextHeadingParser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ last := pc.LastOpenedBlock().Node
+ if last == nil {
+ return nil, NoChildren
+ }
+ paragraph, ok := last.(*ast.Paragraph)
+ if !ok || paragraph.Parent() != parent {
+ return nil, NoChildren
+ }
+ line, segment := reader.PeekLine()
+ c, ok := matchesSetextHeadingBar(line)
+ if !ok {
+ return nil, NoChildren
+ }
+ level := 1
+ if c == '-' {
+ level = 2
+ }
+ node := ast.NewHeading(level)
+ node.Lines().Append(segment)
+ pc.Set(temporaryParagraphKey, last)
+ return node, NoChildren | RequireParagraph
+}
+
+func (b *setextHeadingParser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ return Close
+}
+
+func (b *setextHeadingParser) Close(node ast.Node, reader text.Reader, pc Context) {
+ heading := node.(*ast.Heading)
+ segment := node.Lines().At(0)
+ heading.Lines().Clear()
+ tmp := pc.Get(temporaryParagraphKey).(*ast.Paragraph)
+ pc.Set(temporaryParagraphKey, nil)
+ if tmp.Lines().Len() == 0 {
+ next := heading.NextSibling()
+ segment = segment.TrimLeftSpace(reader.Source())
+ if next == nil || !ast.IsParagraph(next) {
+ para := ast.NewParagraph()
+ para.Lines().Append(segment)
+ heading.Parent().InsertAfter(heading.Parent(), heading, para)
+ } else {
+ next.(ast.Node).Lines().Unshift(segment)
+ }
+ heading.Parent().RemoveChild(heading.Parent(), heading)
+ } else {
+ heading.SetLines(tmp.Lines())
+ heading.SetBlankPreviousLines(tmp.HasBlankPreviousLines())
+ tp := tmp.Parent()
+ if tp != nil {
+ tp.RemoveChild(tp, tmp)
+ }
+ }
+
+ if b.Attribute {
+ parseLastLineAttributes(node, reader, pc)
+ }
+
+ if b.AutoHeadingID {
+ id, ok := node.AttributeString("id")
+ if !ok {
+ generateAutoHeadingID(heading, reader, pc)
+ } else {
+ pc.IDs().Put(id.([]byte))
+ }
+ }
+}
+
+func (b *setextHeadingParser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *setextHeadingParser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/parser/thematic_break.go b/vendor/github.com/yuin/goldmark/parser/thematic_break.go
new file mode 100644
index 0000000..db20a1e
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/parser/thematic_break.go
@@ -0,0 +1,75 @@
+package parser
+
+import (
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/text"
+ "github.com/yuin/goldmark/util"
+)
+
+type thematicBreakPraser struct {
+}
+
+var defaultThematicBreakPraser = &thematicBreakPraser{}
+
+// NewThematicBreakParser returns a new BlockParser that
+// parses thematic breaks.
+func NewThematicBreakParser() BlockParser {
+ return defaultThematicBreakPraser
+}
+
+func isThematicBreak(line []byte, offset int) bool {
+ w, pos := util.IndentWidth(line, offset)
+ if w > 3 {
+ return false
+ }
+ mark := byte(0)
+ count := 0
+ for i := pos; i < len(line); i++ {
+ c := line[i]
+ if util.IsSpace(c) {
+ continue
+ }
+ if mark == 0 {
+ mark = c
+ count = 1
+ if mark == '*' || mark == '-' || mark == '_' {
+ continue
+ }
+ return false
+ }
+ if c != mark {
+ return false
+ }
+ count++
+ }
+ return count > 2
+}
+
+func (b *thematicBreakPraser) Trigger() []byte {
+ return []byte{'-', '*', '_'}
+}
+
+func (b *thematicBreakPraser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
+ line, segment := reader.PeekLine()
+ if isThematicBreak(line, reader.LineOffset()) {
+ reader.Advance(segment.Len() - 1)
+ return ast.NewThematicBreak(), NoChildren
+ }
+ return nil, NoChildren
+}
+
+func (b *thematicBreakPraser) Continue(node ast.Node, reader text.Reader, pc Context) State {
+ return Close
+}
+
+func (b *thematicBreakPraser) Close(node ast.Node, reader text.Reader, pc Context) {
+ // nothing to do
+}
+
+func (b *thematicBreakPraser) CanInterruptParagraph() bool {
+ return true
+}
+
+func (b *thematicBreakPraser) CanAcceptIndentedLine() bool {
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/renderer/html/html.go b/vendor/github.com/yuin/goldmark/renderer/html/html.go
new file mode 100644
index 0000000..12fa7ce
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/renderer/html/html.go
@@ -0,0 +1,842 @@
+package html
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/renderer"
+ "github.com/yuin/goldmark/util"
+)
+
+// A Config struct has configurations for the HTML based renderers.
+type Config struct {
+ Writer Writer
+ HardWraps bool
+ XHTML bool
+ Unsafe bool
+}
+
+// NewConfig returns a new Config with defaults.
+func NewConfig() Config {
+ return Config{
+ Writer: DefaultWriter,
+ HardWraps: false,
+ XHTML: false,
+ Unsafe: false,
+ }
+}
+
+// SetOption implements renderer.NodeRenderer.SetOption.
+func (c *Config) SetOption(name renderer.OptionName, value interface{}) {
+ switch name {
+ case optHardWraps:
+ c.HardWraps = value.(bool)
+ case optXHTML:
+ c.XHTML = value.(bool)
+ case optUnsafe:
+ c.Unsafe = value.(bool)
+ case optTextWriter:
+ c.Writer = value.(Writer)
+ }
+}
+
+// An Option interface sets options for HTML based renderers.
+type Option interface {
+ SetHTMLOption(*Config)
+}
+
+// TextWriter is an option name used in WithWriter.
+const optTextWriter renderer.OptionName = "Writer"
+
+type withWriter struct {
+ value Writer
+}
+
+func (o *withWriter) SetConfig(c *renderer.Config) {
+ c.Options[optTextWriter] = o.value
+}
+
+func (o *withWriter) SetHTMLOption(c *Config) {
+ c.Writer = o.value
+}
+
+// WithWriter is a functional option that allow you to set the given writer to
+// the renderer.
+func WithWriter(writer Writer) interface {
+ renderer.Option
+ Option
+} {
+ return &withWriter{writer}
+}
+
+// HardWraps is an option name used in WithHardWraps.
+const optHardWraps renderer.OptionName = "HardWraps"
+
+type withHardWraps struct {
+}
+
+func (o *withHardWraps) SetConfig(c *renderer.Config) {
+ c.Options[optHardWraps] = true
+}
+
+func (o *withHardWraps) SetHTMLOption(c *Config) {
+ c.HardWraps = true
+}
+
+// WithHardWraps is a functional option that indicates whether softline breaks
+// should be rendered as ' '.
+func WithHardWraps() interface {
+ renderer.Option
+ Option
+} {
+ return &withHardWraps{}
+}
+
+// XHTML is an option name used in WithXHTML.
+const optXHTML renderer.OptionName = "XHTML"
+
+type withXHTML struct {
+}
+
+func (o *withXHTML) SetConfig(c *renderer.Config) {
+ c.Options[optXHTML] = true
+}
+
+func (o *withXHTML) SetHTMLOption(c *Config) {
+ c.XHTML = true
+}
+
+// WithXHTML is a functional option indicates that nodes should be rendered in
+// xhtml instead of HTML5.
+func WithXHTML() interface {
+ Option
+ renderer.Option
+} {
+ return &withXHTML{}
+}
+
+// Unsafe is an option name used in WithUnsafe.
+const optUnsafe renderer.OptionName = "Unsafe"
+
+type withUnsafe struct {
+}
+
+func (o *withUnsafe) SetConfig(c *renderer.Config) {
+ c.Options[optUnsafe] = true
+}
+
+func (o *withUnsafe) SetHTMLOption(c *Config) {
+ c.Unsafe = true
+}
+
+// WithUnsafe is a functional option that renders dangerous contents
+// (raw htmls and potentially dangerous links) as it is.
+func WithUnsafe() interface {
+ renderer.Option
+ Option
+} {
+ return &withUnsafe{}
+}
+
+// A Renderer struct is an implementation of renderer.NodeRenderer that renders
+// nodes as (X)HTML.
+type Renderer struct {
+ Config
+}
+
+// NewRenderer returns a new Renderer with given options.
+func NewRenderer(opts ...Option) renderer.NodeRenderer {
+ r := &Renderer{
+ Config: NewConfig(),
+ }
+
+ for _, opt := range opts {
+ opt.SetHTMLOption(&r.Config)
+ }
+ return r
+}
+
+// RegisterFuncs implements NodeRenderer.RegisterFuncs .
+func (r *Renderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
+ // blocks
+
+ reg.Register(ast.KindDocument, r.renderDocument)
+ reg.Register(ast.KindHeading, r.renderHeading)
+ reg.Register(ast.KindBlockquote, r.renderBlockquote)
+ reg.Register(ast.KindCodeBlock, r.renderCodeBlock)
+ reg.Register(ast.KindFencedCodeBlock, r.renderFencedCodeBlock)
+ reg.Register(ast.KindHTMLBlock, r.renderHTMLBlock)
+ reg.Register(ast.KindList, r.renderList)
+ reg.Register(ast.KindListItem, r.renderListItem)
+ reg.Register(ast.KindParagraph, r.renderParagraph)
+ reg.Register(ast.KindTextBlock, r.renderTextBlock)
+ reg.Register(ast.KindThematicBreak, r.renderThematicBreak)
+
+ // inlines
+
+ reg.Register(ast.KindAutoLink, r.renderAutoLink)
+ reg.Register(ast.KindCodeSpan, r.renderCodeSpan)
+ reg.Register(ast.KindEmphasis, r.renderEmphasis)
+ reg.Register(ast.KindImage, r.renderImage)
+ reg.Register(ast.KindLink, r.renderLink)
+ reg.Register(ast.KindRawHTML, r.renderRawHTML)
+ reg.Register(ast.KindText, r.renderText)
+ reg.Register(ast.KindString, r.renderString)
+}
+
+func (r *Renderer) writeLines(w util.BufWriter, source []byte, n ast.Node) {
+ l := n.Lines().Len()
+ for i := 0; i < l; i++ {
+ line := n.Lines().At(i)
+ r.Writer.RawWrite(w, line.Value(source))
+ }
+}
+
+// GlobalAttributeFilter defines attribute names which any elements can have.
+var GlobalAttributeFilter = util.NewBytesFilter(
+ []byte("accesskey"),
+ []byte("autocapitalize"),
+ []byte("autofocus"),
+ []byte("class"),
+ []byte("contenteditable"),
+ []byte("dir"),
+ []byte("draggable"),
+ []byte("enterkeyhint"),
+ []byte("hidden"),
+ []byte("id"),
+ []byte("inert"),
+ []byte("inputmode"),
+ []byte("is"),
+ []byte("itemid"),
+ []byte("itemprop"),
+ []byte("itemref"),
+ []byte("itemscope"),
+ []byte("itemtype"),
+ []byte("lang"),
+ []byte("part"),
+ []byte("slot"),
+ []byte("spellcheck"),
+ []byte("style"),
+ []byte("tabindex"),
+ []byte("title"),
+ []byte("translate"),
+)
+
+func (r *Renderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ // nothing to do
+ return ast.WalkContinue, nil
+}
+
+// HeadingAttributeFilter defines attribute names which heading elements can have
+var HeadingAttributeFilter = GlobalAttributeFilter
+
+func (r *Renderer) renderHeading(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.Heading)
+ if entering {
+ _, _ = w.WriteString("')
+ } else {
+ _, _ = w.WriteString(" \n")
+ }
+ return ast.WalkContinue, nil
+}
+
+// BlockquoteAttributeFilter defines attribute names which blockquote elements can have
+var BlockquoteAttributeFilter = GlobalAttributeFilter.Extend(
+ []byte("cite"),
+)
+
+func (r *Renderer) renderBlockquote(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if entering {
+ if n.Attributes() != nil {
+ _, _ = w.WriteString("')
+ } else {
+ _, _ = w.WriteString("\n")
+ }
+ } else {
+ _, _ = w.WriteString(" \n")
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *Renderer) renderCodeBlock(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if entering {
+ _, _ = w.WriteString("")
+ r.writeLines(w, source, n)
+ } else {
+ _, _ = w.WriteString("
\n")
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *Renderer) renderFencedCodeBlock(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.FencedCodeBlock)
+ if entering {
+ _, _ = w.WriteString("')
+ r.writeLines(w, source, n)
+ } else {
+ _, _ = w.WriteString("
\n")
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *Renderer) renderHTMLBlock(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.HTMLBlock)
+ if entering {
+ if r.Unsafe {
+ l := n.Lines().Len()
+ for i := 0; i < l; i++ {
+ line := n.Lines().At(i)
+ r.Writer.SecureWrite(w, line.Value(source))
+ }
+ } else {
+ _, _ = w.WriteString("\n")
+ }
+ } else {
+ if n.HasClosure() {
+ if r.Unsafe {
+ closure := n.ClosureLine
+ r.Writer.SecureWrite(w, closure.Value(source))
+ } else {
+ _, _ = w.WriteString("\n")
+ }
+ }
+ }
+ return ast.WalkContinue, nil
+}
+
+// ListAttributeFilter defines attribute names which list elements can have.
+var ListAttributeFilter = GlobalAttributeFilter.Extend(
+ []byte("start"),
+ []byte("reversed"),
+ []byte("type"),
+)
+
+func (r *Renderer) renderList(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.List)
+ tag := "ul"
+ if n.IsOrdered() {
+ tag = "ol"
+ }
+ if entering {
+ _ = w.WriteByte('<')
+ _, _ = w.WriteString(tag)
+ if n.IsOrdered() && n.Start != 1 {
+ fmt.Fprintf(w, " start=\"%d\"", n.Start)
+ }
+ if n.Attributes() != nil {
+ RenderAttributes(w, n, ListAttributeFilter)
+ }
+ _, _ = w.WriteString(">\n")
+ } else {
+ _, _ = w.WriteString("")
+ _, _ = w.WriteString(tag)
+ _, _ = w.WriteString(">\n")
+ }
+ return ast.WalkContinue, nil
+}
+
+// ListItemAttributeFilter defines attribute names which list item elements can have.
+var ListItemAttributeFilter = GlobalAttributeFilter.Extend(
+ []byte("value"),
+)
+
+func (r *Renderer) renderListItem(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if entering {
+ if n.Attributes() != nil {
+ _, _ = w.WriteString("')
+ } else {
+ _, _ = w.WriteString(" ")
+ }
+ fc := n.FirstChild()
+ if fc != nil {
+ if _, ok := fc.(*ast.TextBlock); !ok {
+ _ = w.WriteByte('\n')
+ }
+ }
+ } else {
+ _, _ = w.WriteString(" \n")
+ }
+ return ast.WalkContinue, nil
+}
+
+// ParagraphAttributeFilter defines attribute names which paragraph elements can have.
+var ParagraphAttributeFilter = GlobalAttributeFilter
+
+func (r *Renderer) renderParagraph(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if entering {
+ if n.Attributes() != nil {
+ _, _ = w.WriteString("')
+ } else {
+ _, _ = w.WriteString("
")
+ }
+ } else {
+ _, _ = w.WriteString("
\n")
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *Renderer) renderTextBlock(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if !entering {
+ if _, ok := n.NextSibling().(ast.Node); ok && n.FirstChild() != nil {
+ _ = w.WriteByte('\n')
+ }
+ }
+ return ast.WalkContinue, nil
+}
+
+// ThematicAttributeFilter defines attribute names which hr elements can have.
+var ThematicAttributeFilter = GlobalAttributeFilter.Extend(
+ []byte("align"), // [Deprecated]
+ []byte("color"), // [Not Standardized]
+ []byte("noshade"), // [Deprecated]
+ []byte("size"), // [Deprecated]
+ []byte("width"), // [Deprecated]
+)
+
+func (r *Renderer) renderThematicBreak(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if !entering {
+ return ast.WalkContinue, nil
+ }
+ _, _ = w.WriteString(" \n")
+ } else {
+ _, _ = w.WriteString(">\n")
+ }
+ return ast.WalkContinue, nil
+}
+
+// LinkAttributeFilter defines attribute names which link elements can have.
+var LinkAttributeFilter = GlobalAttributeFilter.Extend(
+ []byte("download"),
+ // []byte("href"),
+ []byte("hreflang"),
+ []byte("media"),
+ []byte("ping"),
+ []byte("referrerpolicy"),
+ []byte("rel"),
+ []byte("shape"),
+ []byte("target"),
+)
+
+func (r *Renderer) renderAutoLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.AutoLink)
+ if !entering {
+ return ast.WalkContinue, nil
+ }
+ _, _ = w.WriteString(`')
+ } else {
+ _, _ = w.WriteString(`">`)
+ }
+ _, _ = w.Write(util.EscapeHTML(label))
+ _, _ = w.WriteString(` `)
+ return ast.WalkContinue, nil
+}
+
+// CodeAttributeFilter defines attribute names which code elements can have.
+var CodeAttributeFilter = GlobalAttributeFilter
+
+func (r *Renderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
+ if entering {
+ if n.Attributes() != nil {
+ _, _ = w.WriteString("')
+ } else {
+ _, _ = w.WriteString("")
+ }
+ for c := n.FirstChild(); c != nil; c = c.NextSibling() {
+ segment := c.(*ast.Text).Segment
+ value := segment.Value(source)
+ if bytes.HasSuffix(value, []byte("\n")) {
+ r.Writer.RawWrite(w, value[:len(value)-1])
+ r.Writer.RawWrite(w, []byte(" "))
+ } else {
+ r.Writer.RawWrite(w, value)
+ }
+ }
+ return ast.WalkSkipChildren, nil
+ }
+ _, _ = w.WriteString("
")
+ return ast.WalkContinue, nil
+}
+
+// EmphasisAttributeFilter defines attribute names which emphasis elements can have.
+var EmphasisAttributeFilter = GlobalAttributeFilter
+
+func (r *Renderer) renderEmphasis(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.Emphasis)
+ tag := "em"
+ if n.Level == 2 {
+ tag = "strong"
+ }
+ if entering {
+ _ = w.WriteByte('<')
+ _, _ = w.WriteString(tag)
+ if n.Attributes() != nil {
+ RenderAttributes(w, n, EmphasisAttributeFilter)
+ }
+ _ = w.WriteByte('>')
+ } else {
+ _, _ = w.WriteString("")
+ _, _ = w.WriteString(tag)
+ _ = w.WriteByte('>')
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *Renderer) renderLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ n := node.(*ast.Link)
+ if entering {
+ _, _ = w.WriteString("')
+ } else {
+ _, _ = w.WriteString(" ")
+ }
+ return ast.WalkContinue, nil
+}
+
+// ImageAttributeFilter defines attribute names which image elements can have.
+var ImageAttributeFilter = GlobalAttributeFilter.Extend(
+ []byte("align"),
+ []byte("border"),
+ []byte("crossorigin"),
+ []byte("decoding"),
+ []byte("height"),
+ []byte("importance"),
+ []byte("intrinsicsize"),
+ []byte("ismap"),
+ []byte("loading"),
+ []byte("referrerpolicy"),
+ []byte("sizes"),
+ []byte("srcset"),
+ []byte("usemap"),
+ []byte("width"),
+)
+
+func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ if !entering {
+ return ast.WalkContinue, nil
+ }
+ n := node.(*ast.Image)
+ _, _ = w.WriteString(" ")
+ } else {
+ _, _ = w.WriteString(">")
+ }
+ return ast.WalkSkipChildren, nil
+}
+
+func (r *Renderer) renderRawHTML(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ if !entering {
+ return ast.WalkSkipChildren, nil
+ }
+ if r.Unsafe {
+ n := node.(*ast.RawHTML)
+ l := n.Segments.Len()
+ for i := 0; i < l; i++ {
+ segment := n.Segments.At(i)
+ _, _ = w.Write(segment.Value(source))
+ }
+ return ast.WalkSkipChildren, nil
+ }
+ _, _ = w.WriteString("")
+ return ast.WalkSkipChildren, nil
+}
+
+func (r *Renderer) renderText(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ if !entering {
+ return ast.WalkContinue, nil
+ }
+ n := node.(*ast.Text)
+ segment := n.Segment
+ if n.IsRaw() {
+ r.Writer.RawWrite(w, segment.Value(source))
+ } else {
+ r.Writer.Write(w, segment.Value(source))
+ if n.HardLineBreak() || (n.SoftLineBreak() && r.HardWraps) {
+ if r.XHTML {
+ _, _ = w.WriteString(" \n")
+ } else {
+ _, _ = w.WriteString(" \n")
+ }
+ } else if n.SoftLineBreak() {
+ _ = w.WriteByte('\n')
+ }
+ }
+ return ast.WalkContinue, nil
+}
+
+func (r *Renderer) renderString(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
+ if !entering {
+ return ast.WalkContinue, nil
+ }
+ n := node.(*ast.String)
+ if n.IsCode() {
+ _, _ = w.Write(n.Value)
+ } else {
+ if n.IsRaw() {
+ r.Writer.RawWrite(w, n.Value)
+ } else {
+ r.Writer.Write(w, n.Value)
+ }
+ }
+ return ast.WalkContinue, nil
+}
+
+var dataPrefix = []byte("data-")
+
+// RenderAttributes renders given node's attributes.
+// You can specify attribute names to render by the filter.
+// If filter is nil, RenderAttributes renders all attributes.
+func RenderAttributes(w util.BufWriter, node ast.Node, filter util.BytesFilter) {
+ for _, attr := range node.Attributes() {
+ if filter != nil && !filter.Contains(attr.Name) {
+ if !bytes.HasPrefix(attr.Name, dataPrefix) {
+ continue
+ }
+ }
+ _, _ = w.WriteString(" ")
+ _, _ = w.Write(attr.Name)
+ _, _ = w.WriteString(`="`)
+ // TODO: convert numeric values to strings
+ _, _ = w.Write(util.EscapeHTML(attr.Value.([]byte)))
+ _ = w.WriteByte('"')
+ }
+}
+
+// A Writer interface writes textual contents to a writer.
+type Writer interface {
+ // Write writes the given source to writer with resolving references and unescaping
+ // backslash escaped characters.
+ Write(writer util.BufWriter, source []byte)
+
+ // RawWrite writes the given source to writer without resolving references and
+ // unescaping backslash escaped characters.
+ RawWrite(writer util.BufWriter, source []byte)
+
+ // SecureWrite writes the given source to writer with replacing insecure characters.
+ SecureWrite(writer util.BufWriter, source []byte)
+}
+
+var replacementCharacter = []byte("\ufffd")
+
+type defaultWriter struct {
+}
+
+func escapeRune(writer util.BufWriter, r rune) {
+ if r < 256 {
+ v := util.EscapeHTMLByte(byte(r))
+ if v != nil {
+ _, _ = writer.Write(v)
+ return
+ }
+ }
+ _, _ = writer.WriteRune(util.ToValidRune(r))
+}
+
+func (d *defaultWriter) SecureWrite(writer util.BufWriter, source []byte) {
+ n := 0
+ l := len(source)
+ for i := 0; i < l; i++ {
+ if source[i] == '\u0000' {
+ _, _ = writer.Write(source[i-n : i])
+ n = 0
+ _, _ = writer.Write(replacementCharacter)
+ continue
+ }
+ n++
+ }
+ if n != 0 {
+ _, _ = writer.Write(source[l-n:])
+ }
+}
+
+func (d *defaultWriter) RawWrite(writer util.BufWriter, source []byte) {
+ n := 0
+ l := len(source)
+ for i := 0; i < l; i++ {
+ v := util.EscapeHTMLByte(source[i])
+ if v != nil {
+ _, _ = writer.Write(source[i-n : i])
+ n = 0
+ _, _ = writer.Write(v)
+ continue
+ }
+ n++
+ }
+ if n != 0 {
+ _, _ = writer.Write(source[l-n:])
+ }
+}
+
+func (d *defaultWriter) Write(writer util.BufWriter, source []byte) {
+ escaped := false
+ var ok bool
+ limit := len(source)
+ n := 0
+ for i := 0; i < limit; i++ {
+ c := source[i]
+ if escaped {
+ if util.IsPunct(c) {
+ d.RawWrite(writer, source[n:i-1])
+ n = i
+ escaped = false
+ continue
+ }
+ }
+ if c == '\x00' {
+ d.RawWrite(writer, source[n:i])
+ d.RawWrite(writer, replacementCharacter)
+ n = i + 1
+ escaped = false
+ continue
+ }
+ if c == '&' {
+ pos := i
+ next := i + 1
+ if next < limit && source[next] == '#' {
+ nnext := next + 1
+ if nnext < limit {
+ nc := source[nnext]
+ // code point like #x22;
+ if nnext < limit && nc == 'x' || nc == 'X' {
+ start := nnext + 1
+ i, ok = util.ReadWhile(source, [2]int{start, limit}, util.IsHexDecimal)
+ if ok && i < limit && source[i] == ';' && i-start < 7 {
+ v, _ := strconv.ParseUint(util.BytesToReadOnlyString(source[start:i]), 16, 32)
+ d.RawWrite(writer, source[n:pos])
+ n = i + 1
+ escapeRune(writer, rune(v))
+ continue
+ }
+ // code point like #1234;
+ } else if nc >= '0' && nc <= '9' {
+ start := nnext
+ i, ok = util.ReadWhile(source, [2]int{start, limit}, util.IsNumeric)
+ if ok && i < limit && i-start < 8 && source[i] == ';' {
+ v, _ := strconv.ParseUint(util.BytesToReadOnlyString(source[start:i]), 10, 32)
+ d.RawWrite(writer, source[n:pos])
+ n = i + 1
+ escapeRune(writer, rune(v))
+ continue
+ }
+ }
+ }
+ } else {
+ start := next
+ i, ok = util.ReadWhile(source, [2]int{start, limit}, util.IsAlphaNumeric)
+ // entity reference
+ if ok && i < limit && source[i] == ';' {
+ name := util.BytesToReadOnlyString(source[start:i])
+ entity, ok := util.LookUpHTML5EntityByName(name)
+ if ok {
+ d.RawWrite(writer, source[n:pos])
+ n = i + 1
+ d.RawWrite(writer, entity.Characters)
+ continue
+ }
+ }
+ }
+ i = next - 1
+ }
+ if c == '\\' {
+ escaped = true
+ continue
+ }
+ escaped = false
+ }
+ d.RawWrite(writer, source[n:])
+}
+
+// DefaultWriter is a default implementation of the Writer.
+var DefaultWriter = &defaultWriter{}
+
+var bDataImage = []byte("data:image/")
+var bPng = []byte("png;")
+var bGif = []byte("gif;")
+var bJpeg = []byte("jpeg;")
+var bWebp = []byte("webp;")
+var bSvg = []byte("svg;")
+var bJs = []byte("javascript:")
+var bVb = []byte("vbscript:")
+var bFile = []byte("file:")
+var bData = []byte("data:")
+
+// IsDangerousURL returns true if the given url seems a potentially dangerous url,
+// otherwise false.
+func IsDangerousURL(url []byte) bool {
+ if bytes.HasPrefix(url, bDataImage) && len(url) >= 11 {
+ v := url[11:]
+ if bytes.HasPrefix(v, bPng) || bytes.HasPrefix(v, bGif) ||
+ bytes.HasPrefix(v, bJpeg) || bytes.HasPrefix(v, bWebp) ||
+ bytes.HasPrefix(v, bSvg) {
+ return false
+ }
+ return true
+ }
+ return bytes.HasPrefix(url, bJs) || bytes.HasPrefix(url, bVb) ||
+ bytes.HasPrefix(url, bFile) || bytes.HasPrefix(url, bData)
+}
diff --git a/vendor/github.com/yuin/goldmark/renderer/renderer.go b/vendor/github.com/yuin/goldmark/renderer/renderer.go
new file mode 100644
index 0000000..10f6d40
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/renderer/renderer.go
@@ -0,0 +1,174 @@
+// Package renderer renders the given AST to certain formats.
+package renderer
+
+import (
+ "bufio"
+ "io"
+ "sync"
+
+ "github.com/yuin/goldmark/ast"
+ "github.com/yuin/goldmark/util"
+)
+
+// A Config struct is a data structure that holds configuration of the Renderer.
+type Config struct {
+ Options map[OptionName]interface{}
+ NodeRenderers util.PrioritizedSlice
+}
+
+// NewConfig returns a new Config
+func NewConfig() *Config {
+ return &Config{
+ Options: map[OptionName]interface{}{},
+ NodeRenderers: util.PrioritizedSlice{},
+ }
+}
+
+// An OptionName is a name of the option.
+type OptionName string
+
+// An Option interface is a functional option type for the Renderer.
+type Option interface {
+ SetConfig(*Config)
+}
+
+type withNodeRenderers struct {
+ value []util.PrioritizedValue
+}
+
+func (o *withNodeRenderers) SetConfig(c *Config) {
+ c.NodeRenderers = append(c.NodeRenderers, o.value...)
+}
+
+// WithNodeRenderers is a functional option that allow you to add
+// NodeRenderers to the renderer.
+func WithNodeRenderers(ps ...util.PrioritizedValue) Option {
+ return &withNodeRenderers{ps}
+}
+
+type withOption struct {
+ name OptionName
+ value interface{}
+}
+
+func (o *withOption) SetConfig(c *Config) {
+ c.Options[o.name] = o.value
+}
+
+// WithOption is a functional option that allow you to set
+// an arbitrary option to the parser.
+func WithOption(name OptionName, value interface{}) Option {
+ return &withOption{name, value}
+}
+
+// A SetOptioner interface sets given option to the object.
+type SetOptioner interface {
+ // SetOption sets given option to the object.
+ // Unacceptable options may be passed.
+ // Thus implementations must ignore unacceptable options.
+ SetOption(name OptionName, value interface{})
+}
+
+// NodeRendererFunc is a function that renders a given node.
+type NodeRendererFunc func(writer util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error)
+
+// A NodeRenderer interface offers NodeRendererFuncs.
+type NodeRenderer interface {
+ // RendererFuncs registers NodeRendererFuncs to given NodeRendererFuncRegisterer.
+ RegisterFuncs(NodeRendererFuncRegisterer)
+}
+
+// A NodeRendererFuncRegisterer registers
+type NodeRendererFuncRegisterer interface {
+ // Register registers given NodeRendererFunc to this object.
+ Register(ast.NodeKind, NodeRendererFunc)
+}
+
+// A Renderer interface renders given AST node to given
+// writer with given Renderer.
+type Renderer interface {
+ Render(w io.Writer, source []byte, n ast.Node) error
+
+ // AddOptions adds given option to this renderer.
+ AddOptions(...Option)
+}
+
+type renderer struct {
+ config *Config
+ options map[OptionName]interface{}
+ nodeRendererFuncsTmp map[ast.NodeKind]NodeRendererFunc
+ maxKind int
+ nodeRendererFuncs []NodeRendererFunc
+ initSync sync.Once
+}
+
+// NewRenderer returns a new Renderer with given options.
+func NewRenderer(options ...Option) Renderer {
+ config := NewConfig()
+ for _, opt := range options {
+ opt.SetConfig(config)
+ }
+
+ r := &renderer{
+ options: map[OptionName]interface{}{},
+ config: config,
+ nodeRendererFuncsTmp: map[ast.NodeKind]NodeRendererFunc{},
+ }
+
+ return r
+}
+
+func (r *renderer) AddOptions(opts ...Option) {
+ for _, opt := range opts {
+ opt.SetConfig(r.config)
+ }
+}
+
+func (r *renderer) Register(kind ast.NodeKind, v NodeRendererFunc) {
+ r.nodeRendererFuncsTmp[kind] = v
+ if int(kind) > r.maxKind {
+ r.maxKind = int(kind)
+ }
+}
+
+// Render renders the given AST node to the given writer with the given Renderer.
+func (r *renderer) Render(w io.Writer, source []byte, n ast.Node) error {
+ r.initSync.Do(func() {
+ r.options = r.config.Options
+ r.config.NodeRenderers.Sort()
+ l := len(r.config.NodeRenderers)
+ for i := l - 1; i >= 0; i-- {
+ v := r.config.NodeRenderers[i]
+ nr, _ := v.Value.(NodeRenderer)
+ if se, ok := v.Value.(SetOptioner); ok {
+ for oname, ovalue := range r.options {
+ se.SetOption(oname, ovalue)
+ }
+ }
+ nr.RegisterFuncs(r)
+ }
+ r.nodeRendererFuncs = make([]NodeRendererFunc, r.maxKind+1)
+ for kind, nr := range r.nodeRendererFuncsTmp {
+ r.nodeRendererFuncs[kind] = nr
+ }
+ r.config = nil
+ r.nodeRendererFuncsTmp = nil
+ })
+ writer, ok := w.(util.BufWriter)
+ if !ok {
+ writer = bufio.NewWriter(w)
+ }
+ err := ast.Walk(n, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
+ s := ast.WalkStatus(ast.WalkContinue)
+ var err error
+ f := r.nodeRendererFuncs[n.Kind()]
+ if f != nil {
+ s, err = f(writer, source, n, entering)
+ }
+ return s, err
+ })
+ if err != nil {
+ return err
+ }
+ return writer.Flush()
+}
diff --git a/vendor/github.com/yuin/goldmark/text/reader.go b/vendor/github.com/yuin/goldmark/text/reader.go
new file mode 100644
index 0000000..319f1c8
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/text/reader.go
@@ -0,0 +1,653 @@
+package text
+
+import (
+ "io"
+ "regexp"
+ "unicode/utf8"
+
+ "github.com/yuin/goldmark/util"
+)
+
+const invalidValue = -1
+
+// EOF indicates the end of file.
+const EOF = byte(0xff)
+
+// A Reader interface provides abstracted method for reading text.
+type Reader interface {
+ io.RuneReader
+
+ // Source returns a source of the reader.
+ Source() []byte
+
+ // ResetPosition resets positions.
+ ResetPosition()
+
+ // Peek returns a byte at current position without advancing the internal pointer.
+ Peek() byte
+
+ // PeekLine returns the current line without advancing the internal pointer.
+ PeekLine() ([]byte, Segment)
+
+ // PrecendingCharacter returns a character just before current internal pointer.
+ PrecendingCharacter() rune
+
+ // Value returns a value of the given segment.
+ Value(Segment) []byte
+
+ // LineOffset returns a distance from the line head to current position.
+ LineOffset() int
+
+ // Position returns current line number and position.
+ Position() (int, Segment)
+
+ // SetPosition sets current line number and position.
+ SetPosition(int, Segment)
+
+ // SetPadding sets padding to the reader.
+ SetPadding(int)
+
+ // Advance advances the internal pointer.
+ Advance(int)
+
+ // AdvanceAndSetPadding advances the internal pointer and add padding to the
+ // reader.
+ AdvanceAndSetPadding(int, int)
+
+ // AdvanceLine advances the internal pointer to the next line head.
+ AdvanceLine()
+
+ // SkipSpaces skips space characters and returns a non-blank line.
+ // If it reaches EOF, returns false.
+ SkipSpaces() (Segment, int, bool)
+
+ // SkipSpaces skips blank lines and returns a non-blank line.
+ // If it reaches EOF, returns false.
+ SkipBlankLines() (Segment, int, bool)
+
+ // Match performs regular expression matching to current line.
+ Match(reg *regexp.Regexp) bool
+
+ // Match performs regular expression searching to current line.
+ FindSubMatch(reg *regexp.Regexp) [][]byte
+
+ // FindClosure finds corresponding closure.
+ FindClosure(opener, closer byte, options FindClosureOptions) (*Segments, bool)
+}
+
+// FindClosureOptions is options for Reader.FindClosure
+type FindClosureOptions struct {
+ // CodeSpan is a flag for the FindClosure. If this is set to true,
+ // FindClosure ignores closers in codespans.
+ CodeSpan bool
+
+ // Nesting is a flag for the FindClosure. If this is set to true,
+ // FindClosure allows nesting.
+ Nesting bool
+
+ // Newline is a flag for the FindClosure. If this is set to true,
+ // FindClosure searches for a closer over multiple lines.
+ Newline bool
+
+ // Advance is a flag for the FindClosure. If this is set to true,
+ // FindClosure advances pointers when closer is found.
+ Advance bool
+}
+
+type reader struct {
+ source []byte
+ sourceLength int
+ line int
+ peekedLine []byte
+ pos Segment
+ head int
+ lineOffset int
+}
+
+// NewReader return a new Reader that can read UTF-8 bytes .
+func NewReader(source []byte) Reader {
+ r := &reader{
+ source: source,
+ sourceLength: len(source),
+ }
+ r.ResetPosition()
+ return r
+}
+
+func (r *reader) FindClosure(opener, closer byte, options FindClosureOptions) (*Segments, bool) {
+ return findClosureReader(r, opener, closer, options)
+}
+
+func (r *reader) ResetPosition() {
+ r.line = -1
+ r.head = 0
+ r.lineOffset = -1
+ r.AdvanceLine()
+}
+
+func (r *reader) Source() []byte {
+ return r.source
+}
+
+func (r *reader) Value(seg Segment) []byte {
+ return seg.Value(r.source)
+}
+
+func (r *reader) Peek() byte {
+ if r.pos.Start >= 0 && r.pos.Start < r.sourceLength {
+ if r.pos.Padding != 0 {
+ return space[0]
+ }
+ return r.source[r.pos.Start]
+ }
+ return EOF
+}
+
+func (r *reader) PeekLine() ([]byte, Segment) {
+ if r.pos.Start >= 0 && r.pos.Start < r.sourceLength {
+ if r.peekedLine == nil {
+ r.peekedLine = r.pos.Value(r.Source())
+ }
+ return r.peekedLine, r.pos
+ }
+ return nil, r.pos
+}
+
+// io.RuneReader interface
+func (r *reader) ReadRune() (rune, int, error) {
+ return readRuneReader(r)
+}
+
+func (r *reader) LineOffset() int {
+ if r.lineOffset < 0 {
+ v := 0
+ for i := r.head; i < r.pos.Start; i++ {
+ if r.source[i] == '\t' {
+ v += util.TabWidth(v)
+ } else {
+ v++
+ }
+ }
+ r.lineOffset = v - r.pos.Padding
+ }
+ return r.lineOffset
+}
+
+func (r *reader) PrecendingCharacter() rune {
+ if r.pos.Start <= 0 {
+ if r.pos.Padding != 0 {
+ return rune(' ')
+ }
+ return rune('\n')
+ }
+ i := r.pos.Start - 1
+ for ; i >= 0; i-- {
+ if utf8.RuneStart(r.source[i]) {
+ break
+ }
+ }
+ rn, _ := utf8.DecodeRune(r.source[i:])
+ return rn
+}
+
+func (r *reader) Advance(n int) {
+ r.lineOffset = -1
+ if n < len(r.peekedLine) && r.pos.Padding == 0 {
+ r.pos.Start += n
+ r.peekedLine = nil
+ return
+ }
+ r.peekedLine = nil
+ l := r.sourceLength
+ for ; n > 0 && r.pos.Start < l; n-- {
+ if r.pos.Padding != 0 {
+ r.pos.Padding--
+ continue
+ }
+ if r.source[r.pos.Start] == '\n' {
+ r.AdvanceLine()
+ continue
+ }
+ r.pos.Start++
+ }
+}
+
+func (r *reader) AdvanceAndSetPadding(n, padding int) {
+ r.Advance(n)
+ if padding > r.pos.Padding {
+ r.SetPadding(padding)
+ }
+}
+
+func (r *reader) AdvanceLine() {
+ r.lineOffset = -1
+ r.peekedLine = nil
+ r.pos.Start = r.pos.Stop
+ r.head = r.pos.Start
+ if r.pos.Start < 0 {
+ return
+ }
+ r.pos.Stop = r.sourceLength
+ for i := r.pos.Start; i < r.sourceLength; i++ {
+ c := r.source[i]
+ if c == '\n' {
+ r.pos.Stop = i + 1
+ break
+ }
+ }
+ r.line++
+ r.pos.Padding = 0
+}
+
+func (r *reader) Position() (int, Segment) {
+ return r.line, r.pos
+}
+
+func (r *reader) SetPosition(line int, pos Segment) {
+ r.lineOffset = -1
+ r.line = line
+ r.pos = pos
+}
+
+func (r *reader) SetPadding(v int) {
+ r.pos.Padding = v
+}
+
+func (r *reader) SkipSpaces() (Segment, int, bool) {
+ return skipSpacesReader(r)
+}
+
+func (r *reader) SkipBlankLines() (Segment, int, bool) {
+ return skipBlankLinesReader(r)
+}
+
+func (r *reader) Match(reg *regexp.Regexp) bool {
+ return matchReader(r, reg)
+}
+
+func (r *reader) FindSubMatch(reg *regexp.Regexp) [][]byte {
+ return findSubMatchReader(r, reg)
+}
+
+// A BlockReader interface is a reader that is optimized for Blocks.
+type BlockReader interface {
+ Reader
+ // Reset resets current state and sets new segments to the reader.
+ Reset(segment *Segments)
+}
+
+type blockReader struct {
+ source []byte
+ segments *Segments
+ segmentsLength int
+ line int
+ pos Segment
+ head int
+ last int
+ lineOffset int
+}
+
+// NewBlockReader returns a new BlockReader.
+func NewBlockReader(source []byte, segments *Segments) BlockReader {
+ r := &blockReader{
+ source: source,
+ }
+ if segments != nil {
+ r.Reset(segments)
+ }
+ return r
+}
+
+func (r *blockReader) FindClosure(opener, closer byte, options FindClosureOptions) (*Segments, bool) {
+ return findClosureReader(r, opener, closer, options)
+}
+
+func (r *blockReader) ResetPosition() {
+ r.line = -1
+ r.head = 0
+ r.last = 0
+ r.lineOffset = -1
+ r.pos.Start = -1
+ r.pos.Stop = -1
+ r.pos.Padding = 0
+ if r.segmentsLength > 0 {
+ last := r.segments.At(r.segmentsLength - 1)
+ r.last = last.Stop
+ }
+ r.AdvanceLine()
+}
+
+func (r *blockReader) Reset(segments *Segments) {
+ r.segments = segments
+ r.segmentsLength = segments.Len()
+ r.ResetPosition()
+}
+
+func (r *blockReader) Source() []byte {
+ return r.source
+}
+
+func (r *blockReader) Value(seg Segment) []byte {
+ line := r.segmentsLength - 1
+ ret := make([]byte, 0, seg.Stop-seg.Start+1)
+ for ; line >= 0; line-- {
+ if seg.Start >= r.segments.At(line).Start {
+ break
+ }
+ }
+ i := seg.Start
+ for ; line < r.segmentsLength; line++ {
+ s := r.segments.At(line)
+ if i < 0 {
+ i = s.Start
+ }
+ ret = s.ConcatPadding(ret)
+ for ; i < seg.Stop && i < s.Stop; i++ {
+ ret = append(ret, r.source[i])
+ }
+ i = -1
+ if s.Stop > seg.Stop {
+ break
+ }
+ }
+ return ret
+}
+
+// io.RuneReader interface
+func (r *blockReader) ReadRune() (rune, int, error) {
+ return readRuneReader(r)
+}
+
+func (r *blockReader) PrecendingCharacter() rune {
+ if r.pos.Padding != 0 {
+ return rune(' ')
+ }
+ if r.segments.Len() < 1 {
+ return rune('\n')
+ }
+ firstSegment := r.segments.At(0)
+ if r.line == 0 && r.pos.Start <= firstSegment.Start {
+ return rune('\n')
+ }
+ l := len(r.source)
+ i := r.pos.Start - 1
+ for ; i < l && i >= 0; i-- {
+ if utf8.RuneStart(r.source[i]) {
+ break
+ }
+ }
+ if i < 0 || i >= l {
+ return rune('\n')
+ }
+ rn, _ := utf8.DecodeRune(r.source[i:])
+ return rn
+}
+
+func (r *blockReader) LineOffset() int {
+ if r.lineOffset < 0 {
+ v := 0
+ for i := r.head; i < r.pos.Start; i++ {
+ if r.source[i] == '\t' {
+ v += util.TabWidth(v)
+ } else {
+ v++
+ }
+ }
+ r.lineOffset = v - r.pos.Padding
+ }
+ return r.lineOffset
+}
+
+func (r *blockReader) Peek() byte {
+ if r.line < r.segmentsLength && r.pos.Start >= 0 && r.pos.Start < r.last {
+ if r.pos.Padding != 0 {
+ return space[0]
+ }
+ return r.source[r.pos.Start]
+ }
+ return EOF
+}
+
+func (r *blockReader) PeekLine() ([]byte, Segment) {
+ if r.line < r.segmentsLength && r.pos.Start >= 0 && r.pos.Start < r.last {
+ return r.pos.Value(r.source), r.pos
+ }
+ return nil, r.pos
+}
+
+func (r *blockReader) Advance(n int) {
+ r.lineOffset = -1
+
+ if n < r.pos.Stop-r.pos.Start && r.pos.Padding == 0 {
+ r.pos.Start += n
+ return
+ }
+
+ for ; n > 0; n-- {
+ if r.pos.Padding != 0 {
+ r.pos.Padding--
+ continue
+ }
+ if r.pos.Start >= r.pos.Stop-1 && r.pos.Stop < r.last {
+ r.AdvanceLine()
+ continue
+ }
+ r.pos.Start++
+ }
+}
+
+func (r *blockReader) AdvanceAndSetPadding(n, padding int) {
+ r.Advance(n)
+ if padding > r.pos.Padding {
+ r.SetPadding(padding)
+ }
+}
+
+func (r *blockReader) AdvanceLine() {
+ r.SetPosition(r.line+1, NewSegment(invalidValue, invalidValue))
+ r.head = r.pos.Start
+}
+
+func (r *blockReader) Position() (int, Segment) {
+ return r.line, r.pos
+}
+
+func (r *blockReader) SetPosition(line int, pos Segment) {
+ r.lineOffset = -1
+ r.line = line
+ if pos.Start == invalidValue {
+ if r.line < r.segmentsLength {
+ s := r.segments.At(line)
+ r.head = s.Start
+ r.pos = s
+ }
+ } else {
+ r.pos = pos
+ if r.line < r.segmentsLength {
+ s := r.segments.At(line)
+ r.head = s.Start
+ }
+ }
+}
+
+func (r *blockReader) SetPadding(v int) {
+ r.lineOffset = -1
+ r.pos.Padding = v
+}
+
+func (r *blockReader) SkipSpaces() (Segment, int, bool) {
+ return skipSpacesReader(r)
+}
+
+func (r *blockReader) SkipBlankLines() (Segment, int, bool) {
+ return skipBlankLinesReader(r)
+}
+
+func (r *blockReader) Match(reg *regexp.Regexp) bool {
+ return matchReader(r, reg)
+}
+
+func (r *blockReader) FindSubMatch(reg *regexp.Regexp) [][]byte {
+ return findSubMatchReader(r, reg)
+}
+
+func skipBlankLinesReader(r Reader) (Segment, int, bool) {
+ lines := 0
+ for {
+ line, seg := r.PeekLine()
+ if line == nil {
+ return seg, lines, false
+ }
+ if util.IsBlank(line) {
+ lines++
+ r.AdvanceLine()
+ } else {
+ return seg, lines, true
+ }
+ }
+}
+
+func skipSpacesReader(r Reader) (Segment, int, bool) {
+ chars := 0
+ for {
+ line, segment := r.PeekLine()
+ if line == nil {
+ return segment, chars, false
+ }
+ for i, c := range line {
+ if util.IsSpace(c) {
+ chars++
+ r.Advance(1)
+ continue
+ }
+ return segment.WithStart(segment.Start + i + 1), chars, true
+ }
+ }
+}
+
+func matchReader(r Reader, reg *regexp.Regexp) bool {
+ oldline, oldseg := r.Position()
+ match := reg.FindReaderSubmatchIndex(r)
+ r.SetPosition(oldline, oldseg)
+ if match == nil {
+ return false
+ }
+ r.Advance(match[1] - match[0])
+ return true
+}
+
+func findSubMatchReader(r Reader, reg *regexp.Regexp) [][]byte {
+ oldline, oldseg := r.Position()
+ match := reg.FindReaderSubmatchIndex(r)
+ r.SetPosition(oldline, oldseg)
+ if match == nil {
+ return nil
+ }
+ runes := make([]rune, 0, match[1]-match[0])
+ for i := 0; i < match[1]; {
+ r, size, _ := readRuneReader(r)
+ i += size
+ runes = append(runes, r)
+ }
+ result := [][]byte{}
+ for i := 0; i < len(match); i += 2 {
+ result = append(result, []byte(string(runes[match[i]:match[i+1]])))
+ }
+
+ r.SetPosition(oldline, oldseg)
+ r.Advance(match[1] - match[0])
+ return result
+}
+
+func readRuneReader(r Reader) (rune, int, error) {
+ line, _ := r.PeekLine()
+ if line == nil {
+ return 0, 0, io.EOF
+ }
+ rn, size := utf8.DecodeRune(line)
+ if rn == utf8.RuneError {
+ return 0, 0, io.EOF
+ }
+ r.Advance(size)
+ return rn, size, nil
+}
+
+func findClosureReader(r Reader, opener, closer byte, opts FindClosureOptions) (*Segments, bool) {
+ opened := 1
+ codeSpanOpener := 0
+ closed := false
+ orgline, orgpos := r.Position()
+ var ret *Segments
+
+ for {
+ bs, seg := r.PeekLine()
+ if bs == nil {
+ goto end
+ }
+ i := 0
+ for i < len(bs) {
+ c := bs[i]
+ if opts.CodeSpan && codeSpanOpener != 0 && c == '`' {
+ codeSpanCloser := 0
+ for ; i < len(bs); i++ {
+ if bs[i] == '`' {
+ codeSpanCloser++
+ } else {
+ i--
+ break
+ }
+ }
+ if codeSpanCloser == codeSpanOpener {
+ codeSpanOpener = 0
+ }
+ } else if codeSpanOpener == 0 && c == '\\' && i < len(bs)-1 && util.IsPunct(bs[i+1]) {
+ i += 2
+ continue
+ } else if opts.CodeSpan && codeSpanOpener == 0 && c == '`' {
+ for ; i < len(bs); i++ {
+ if bs[i] == '`' {
+ codeSpanOpener++
+ } else {
+ i--
+ break
+ }
+ }
+ } else if (opts.CodeSpan && codeSpanOpener == 0) || !opts.CodeSpan {
+ if c == closer {
+ opened--
+ if opened == 0 {
+ if ret == nil {
+ ret = NewSegments()
+ }
+ ret.Append(seg.WithStop(seg.Start + i))
+ r.Advance(i + 1)
+ closed = true
+ goto end
+ }
+ } else if c == opener {
+ if !opts.Nesting {
+ goto end
+ }
+ opened++
+ }
+ }
+ i++
+ }
+ if !opts.Newline {
+ goto end
+ }
+ r.AdvanceLine()
+ if ret == nil {
+ ret = NewSegments()
+ }
+ ret.Append(seg)
+ }
+end:
+ if !opts.Advance {
+ r.SetPosition(orgline, orgpos)
+ }
+ if closed {
+ return ret, true
+ }
+ return nil, false
+}
diff --git a/vendor/github.com/yuin/goldmark/text/segment.go b/vendor/github.com/yuin/goldmark/text/segment.go
new file mode 100644
index 0000000..badd4bc
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/text/segment.go
@@ -0,0 +1,209 @@
+package text
+
+import (
+ "bytes"
+ "github.com/yuin/goldmark/util"
+)
+
+var space = []byte(" ")
+
+// A Segment struct holds information about source positions.
+type Segment struct {
+ // Start is a start position of the segment.
+ Start int
+
+ // Stop is a stop position of the segment.
+ // This value should be excluded.
+ Stop int
+
+ // Padding is a padding length of the segment.
+ Padding int
+}
+
+// NewSegment return a new Segment.
+func NewSegment(start, stop int) Segment {
+ return Segment{
+ Start: start,
+ Stop: stop,
+ Padding: 0,
+ }
+}
+
+// NewSegmentPadding returns a new Segment with the given padding.
+func NewSegmentPadding(start, stop, n int) Segment {
+ return Segment{
+ Start: start,
+ Stop: stop,
+ Padding: n,
+ }
+}
+
+// Value returns a value of the segment.
+func (t *Segment) Value(buffer []byte) []byte {
+ if t.Padding == 0 {
+ return buffer[t.Start:t.Stop]
+ }
+ result := make([]byte, 0, t.Padding+t.Stop-t.Start+1)
+ result = append(result, bytes.Repeat(space, t.Padding)...)
+ return append(result, buffer[t.Start:t.Stop]...)
+}
+
+// Len returns a length of the segment.
+func (t *Segment) Len() int {
+ return t.Stop - t.Start + t.Padding
+}
+
+// Between returns a segment between this segment and the given segment.
+func (t *Segment) Between(other Segment) Segment {
+ if t.Stop != other.Stop {
+ panic("invalid state")
+ }
+ return NewSegmentPadding(
+ t.Start,
+ other.Start,
+ t.Padding-other.Padding,
+ )
+}
+
+// IsEmpty returns true if this segment is empty, otherwise false.
+func (t *Segment) IsEmpty() bool {
+ return t.Start >= t.Stop && t.Padding == 0
+}
+
+// TrimRightSpace returns a new segment by slicing off all trailing
+// space characters.
+func (t *Segment) TrimRightSpace(buffer []byte) Segment {
+ v := buffer[t.Start:t.Stop]
+ l := util.TrimRightSpaceLength(v)
+ if l == len(v) {
+ return NewSegment(t.Start, t.Start)
+ }
+ return NewSegmentPadding(t.Start, t.Stop-l, t.Padding)
+}
+
+// TrimLeftSpace returns a new segment by slicing off all leading
+// space characters including padding.
+func (t *Segment) TrimLeftSpace(buffer []byte) Segment {
+ v := buffer[t.Start:t.Stop]
+ l := util.TrimLeftSpaceLength(v)
+ return NewSegment(t.Start+l, t.Stop)
+}
+
+// TrimLeftSpaceWidth returns a new segment by slicing off leading space
+// characters until the given width.
+func (t *Segment) TrimLeftSpaceWidth(width int, buffer []byte) Segment {
+ padding := t.Padding
+ for ; width > 0; width-- {
+ if padding == 0 {
+ break
+ }
+ padding--
+ }
+ if width == 0 {
+ return NewSegmentPadding(t.Start, t.Stop, padding)
+ }
+ text := buffer[t.Start:t.Stop]
+ start := t.Start
+ for _, c := range text {
+ if start >= t.Stop-1 || width <= 0 {
+ break
+ }
+ if c == ' ' {
+ width--
+ } else if c == '\t' {
+ width -= 4
+ } else {
+ break
+ }
+ start++
+ }
+ if width < 0 {
+ padding = width * -1
+ }
+ return NewSegmentPadding(start, t.Stop, padding)
+}
+
+// WithStart returns a new Segment with same value except Start.
+func (t *Segment) WithStart(v int) Segment {
+ return NewSegmentPadding(v, t.Stop, t.Padding)
+}
+
+// WithStop returns a new Segment with same value except Stop.
+func (t *Segment) WithStop(v int) Segment {
+ return NewSegmentPadding(t.Start, v, t.Padding)
+}
+
+// ConcatPadding concats the padding to the given slice.
+func (t *Segment) ConcatPadding(v []byte) []byte {
+ if t.Padding > 0 {
+ return append(v, bytes.Repeat(space, t.Padding)...)
+ }
+ return v
+}
+
+// Segments is a collection of the Segment.
+type Segments struct {
+ values []Segment
+}
+
+// NewSegments return a new Segments.
+func NewSegments() *Segments {
+ return &Segments{
+ values: nil,
+ }
+}
+
+// Append appends the given segment after the tail of the collection.
+func (s *Segments) Append(t Segment) {
+ if s.values == nil {
+ s.values = make([]Segment, 0, 20)
+ }
+ s.values = append(s.values, t)
+}
+
+// AppendAll appends all elements of given segments after the tail of the collection.
+func (s *Segments) AppendAll(t []Segment) {
+ if s.values == nil {
+ s.values = make([]Segment, 0, 20)
+ }
+ s.values = append(s.values, t...)
+}
+
+// Len returns the length of the collection.
+func (s *Segments) Len() int {
+ if s.values == nil {
+ return 0
+ }
+ return len(s.values)
+}
+
+// At returns a segment at the given index.
+func (s *Segments) At(i int) Segment {
+ return s.values[i]
+}
+
+// Set sets the given Segment.
+func (s *Segments) Set(i int, v Segment) {
+ s.values[i] = v
+}
+
+// SetSliced replace the collection with a subsliced value.
+func (s *Segments) SetSliced(lo, hi int) {
+ s.values = s.values[lo:hi]
+}
+
+// Sliced returns a subslice of the collection.
+func (s *Segments) Sliced(lo, hi int) []Segment {
+ return s.values[lo:hi]
+}
+
+// Clear delete all element of the collection.
+func (s *Segments) Clear() {
+ s.values = nil
+}
+
+// Unshift insert the given Segment to head of the collection.
+func (s *Segments) Unshift(v Segment) {
+ s.values = append(s.values[0:1], s.values[0:]...)
+ s.values[0] = v
+}
diff --git a/vendor/github.com/yuin/goldmark/util/html5entities.go b/vendor/github.com/yuin/goldmark/util/html5entities.go
new file mode 100644
index 0000000..b8e00a9
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/html5entities.go
@@ -0,0 +1,2142 @@
+package util
+
+// An HTML5Entity struct represents HTML5 entitites.
+type HTML5Entity struct {
+ Name string
+ CodePoints []int
+ Characters []byte
+}
+
+// LookUpHTML5EntityByName returns (an HTML5Entity, true) if an entity named
+// given name is found, otherwise (nil, false)
+func LookUpHTML5EntityByName(name string) (*HTML5Entity, bool) {
+ v, ok := html5entities[name]
+ return v, ok
+}
+
+var html5entities = map[string]*HTML5Entity{
+ "AElig": {Name: "AElig", CodePoints: []int{198}, Characters: []byte{0xc3, 0x86}},
+ "AMP": {Name: "AMP", CodePoints: []int{38}, Characters: []byte{0x26}},
+ "Aacute": {Name: "Aacute", CodePoints: []int{193}, Characters: []byte{0xc3, 0x81}},
+ "Acirc": {Name: "Acirc", CodePoints: []int{194}, Characters: []byte{0xc3, 0x82}},
+ "Acy": {Name: "Acy", CodePoints: []int{1040}, Characters: []byte{0xd0, 0x90}},
+ "Afr": {Name: "Afr", CodePoints: []int{120068}, Characters: []byte{0xf0, 0x9d, 0x94, 0x84}},
+ "Agrave": {Name: "Agrave", CodePoints: []int{192}, Characters: []byte{0xc3, 0x80}},
+ "Alpha": {Name: "Alpha", CodePoints: []int{913}, Characters: []byte{0xce, 0x91}},
+ "Amacr": {Name: "Amacr", CodePoints: []int{256}, Characters: []byte{0xc4, 0x80}},
+ "And": {Name: "And", CodePoints: []int{10835}, Characters: []byte{0xe2, 0xa9, 0x93}},
+ "Aogon": {Name: "Aogon", CodePoints: []int{260}, Characters: []byte{0xc4, 0x84}},
+ "Aopf": {Name: "Aopf", CodePoints: []int{120120}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb8}},
+ "ApplyFunction": {Name: "ApplyFunction", CodePoints: []int{8289}, Characters: []byte{0xe2, 0x81, 0xa1}},
+ "Aring": {Name: "Aring", CodePoints: []int{197}, Characters: []byte{0xc3, 0x85}},
+ "Ascr": {Name: "Ascr", CodePoints: []int{119964}, Characters: []byte{0xf0, 0x9d, 0x92, 0x9c}},
+ "Assign": {Name: "Assign", CodePoints: []int{8788}, Characters: []byte{0xe2, 0x89, 0x94}},
+ "Atilde": {Name: "Atilde", CodePoints: []int{195}, Characters: []byte{0xc3, 0x83}},
+ "Auml": {Name: "Auml", CodePoints: []int{196}, Characters: []byte{0xc3, 0x84}},
+ "Backslash": {Name: "Backslash", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
+ "Barv": {Name: "Barv", CodePoints: []int{10983}, Characters: []byte{0xe2, 0xab, 0xa7}},
+ "Barwed": {Name: "Barwed", CodePoints: []int{8966}, Characters: []byte{0xe2, 0x8c, 0x86}},
+ "Bcy": {Name: "Bcy", CodePoints: []int{1041}, Characters: []byte{0xd0, 0x91}},
+ "Because": {Name: "Because", CodePoints: []int{8757}, Characters: []byte{0xe2, 0x88, 0xb5}},
+ "Bernoullis": {Name: "Bernoullis", CodePoints: []int{8492}, Characters: []byte{0xe2, 0x84, 0xac}},
+ "Beta": {Name: "Beta", CodePoints: []int{914}, Characters: []byte{0xce, 0x92}},
+ "Bfr": {Name: "Bfr", CodePoints: []int{120069}, Characters: []byte{0xf0, 0x9d, 0x94, 0x85}},
+ "Bopf": {Name: "Bopf", CodePoints: []int{120121}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb9}},
+ "Breve": {Name: "Breve", CodePoints: []int{728}, Characters: []byte{0xcb, 0x98}},
+ "Bscr": {Name: "Bscr", CodePoints: []int{8492}, Characters: []byte{0xe2, 0x84, 0xac}},
+ "Bumpeq": {Name: "Bumpeq", CodePoints: []int{8782}, Characters: []byte{0xe2, 0x89, 0x8e}},
+ "CHcy": {Name: "CHcy", CodePoints: []int{1063}, Characters: []byte{0xd0, 0xa7}},
+ "COPY": {Name: "COPY", CodePoints: []int{169}, Characters: []byte{0xc2, 0xa9}},
+ "Cacute": {Name: "Cacute", CodePoints: []int{262}, Characters: []byte{0xc4, 0x86}},
+ "Cap": {Name: "Cap", CodePoints: []int{8914}, Characters: []byte{0xe2, 0x8b, 0x92}},
+ "CapitalDifferentialD": {Name: "CapitalDifferentialD", CodePoints: []int{8517}, Characters: []byte{0xe2, 0x85, 0x85}},
+ "Cayleys": {Name: "Cayleys", CodePoints: []int{8493}, Characters: []byte{0xe2, 0x84, 0xad}},
+ "Ccaron": {Name: "Ccaron", CodePoints: []int{268}, Characters: []byte{0xc4, 0x8c}},
+ "Ccedil": {Name: "Ccedil", CodePoints: []int{199}, Characters: []byte{0xc3, 0x87}},
+ "Ccirc": {Name: "Ccirc", CodePoints: []int{264}, Characters: []byte{0xc4, 0x88}},
+ "Cconint": {Name: "Cconint", CodePoints: []int{8752}, Characters: []byte{0xe2, 0x88, 0xb0}},
+ "Cdot": {Name: "Cdot", CodePoints: []int{266}, Characters: []byte{0xc4, 0x8a}},
+ "Cedilla": {Name: "Cedilla", CodePoints: []int{184}, Characters: []byte{0xc2, 0xb8}},
+ "CenterDot": {Name: "CenterDot", CodePoints: []int{183}, Characters: []byte{0xc2, 0xb7}},
+ "Cfr": {Name: "Cfr", CodePoints: []int{8493}, Characters: []byte{0xe2, 0x84, 0xad}},
+ "Chi": {Name: "Chi", CodePoints: []int{935}, Characters: []byte{0xce, 0xa7}},
+ "CircleDot": {Name: "CircleDot", CodePoints: []int{8857}, Characters: []byte{0xe2, 0x8a, 0x99}},
+ "CircleMinus": {Name: "CircleMinus", CodePoints: []int{8854}, Characters: []byte{0xe2, 0x8a, 0x96}},
+ "CirclePlus": {Name: "CirclePlus", CodePoints: []int{8853}, Characters: []byte{0xe2, 0x8a, 0x95}},
+ "CircleTimes": {Name: "CircleTimes", CodePoints: []int{8855}, Characters: []byte{0xe2, 0x8a, 0x97}},
+ "ClockwiseContourIntegral": {Name: "ClockwiseContourIntegral", CodePoints: []int{8754}, Characters: []byte{0xe2, 0x88, 0xb2}},
+ "CloseCurlyDoubleQuote": {Name: "CloseCurlyDoubleQuote", CodePoints: []int{8221}, Characters: []byte{0xe2, 0x80, 0x9d}},
+ "CloseCurlyQuote": {Name: "CloseCurlyQuote", CodePoints: []int{8217}, Characters: []byte{0xe2, 0x80, 0x99}},
+ "Colon": {Name: "Colon", CodePoints: []int{8759}, Characters: []byte{0xe2, 0x88, 0xb7}},
+ "Colone": {Name: "Colone", CodePoints: []int{10868}, Characters: []byte{0xe2, 0xa9, 0xb4}},
+ "Congruent": {Name: "Congruent", CodePoints: []int{8801}, Characters: []byte{0xe2, 0x89, 0xa1}},
+ "Conint": {Name: "Conint", CodePoints: []int{8751}, Characters: []byte{0xe2, 0x88, 0xaf}},
+ "ContourIntegral": {Name: "ContourIntegral", CodePoints: []int{8750}, Characters: []byte{0xe2, 0x88, 0xae}},
+ "Copf": {Name: "Copf", CodePoints: []int{8450}, Characters: []byte{0xe2, 0x84, 0x82}},
+ "Coproduct": {Name: "Coproduct", CodePoints: []int{8720}, Characters: []byte{0xe2, 0x88, 0x90}},
+ "CounterClockwiseContourIntegral": {Name: "CounterClockwiseContourIntegral", CodePoints: []int{8755}, Characters: []byte{0xe2, 0x88, 0xb3}},
+ "Cross": {Name: "Cross", CodePoints: []int{10799}, Characters: []byte{0xe2, 0xa8, 0xaf}},
+ "Cscr": {Name: "Cscr", CodePoints: []int{119966}, Characters: []byte{0xf0, 0x9d, 0x92, 0x9e}},
+ "Cup": {Name: "Cup", CodePoints: []int{8915}, Characters: []byte{0xe2, 0x8b, 0x93}},
+ "CupCap": {Name: "CupCap", CodePoints: []int{8781}, Characters: []byte{0xe2, 0x89, 0x8d}},
+ "DD": {Name: "DD", CodePoints: []int{8517}, Characters: []byte{0xe2, 0x85, 0x85}},
+ "DDotrahd": {Name: "DDotrahd", CodePoints: []int{10513}, Characters: []byte{0xe2, 0xa4, 0x91}},
+ "DJcy": {Name: "DJcy", CodePoints: []int{1026}, Characters: []byte{0xd0, 0x82}},
+ "DScy": {Name: "DScy", CodePoints: []int{1029}, Characters: []byte{0xd0, 0x85}},
+ "DZcy": {Name: "DZcy", CodePoints: []int{1039}, Characters: []byte{0xd0, 0x8f}},
+ "Dagger": {Name: "Dagger", CodePoints: []int{8225}, Characters: []byte{0xe2, 0x80, 0xa1}},
+ "Darr": {Name: "Darr", CodePoints: []int{8609}, Characters: []byte{0xe2, 0x86, 0xa1}},
+ "Dashv": {Name: "Dashv", CodePoints: []int{10980}, Characters: []byte{0xe2, 0xab, 0xa4}},
+ "Dcaron": {Name: "Dcaron", CodePoints: []int{270}, Characters: []byte{0xc4, 0x8e}},
+ "Dcy": {Name: "Dcy", CodePoints: []int{1044}, Characters: []byte{0xd0, 0x94}},
+ "Del": {Name: "Del", CodePoints: []int{8711}, Characters: []byte{0xe2, 0x88, 0x87}},
+ "Delta": {Name: "Delta", CodePoints: []int{916}, Characters: []byte{0xce, 0x94}},
+ "Dfr": {Name: "Dfr", CodePoints: []int{120071}, Characters: []byte{0xf0, 0x9d, 0x94, 0x87}},
+ "DiacriticalAcute": {Name: "DiacriticalAcute", CodePoints: []int{180}, Characters: []byte{0xc2, 0xb4}},
+ "DiacriticalDot": {Name: "DiacriticalDot", CodePoints: []int{729}, Characters: []byte{0xcb, 0x99}},
+ "DiacriticalDoubleAcute": {Name: "DiacriticalDoubleAcute", CodePoints: []int{733}, Characters: []byte{0xcb, 0x9d}},
+ "DiacriticalGrave": {Name: "DiacriticalGrave", CodePoints: []int{96}, Characters: []byte{0x60}},
+ "DiacriticalTilde": {Name: "DiacriticalTilde", CodePoints: []int{732}, Characters: []byte{0xcb, 0x9c}},
+ "Diamond": {Name: "Diamond", CodePoints: []int{8900}, Characters: []byte{0xe2, 0x8b, 0x84}},
+ "DifferentialD": {Name: "DifferentialD", CodePoints: []int{8518}, Characters: []byte{0xe2, 0x85, 0x86}},
+ "Dopf": {Name: "Dopf", CodePoints: []int{120123}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbb}},
+ "Dot": {Name: "Dot", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
+ "DotDot": {Name: "DotDot", CodePoints: []int{8412}, Characters: []byte{0xe2, 0x83, 0x9c}},
+ "DotEqual": {Name: "DotEqual", CodePoints: []int{8784}, Characters: []byte{0xe2, 0x89, 0x90}},
+ "DoubleContourIntegral": {Name: "DoubleContourIntegral", CodePoints: []int{8751}, Characters: []byte{0xe2, 0x88, 0xaf}},
+ "DoubleDot": {Name: "DoubleDot", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
+ "DoubleDownArrow": {Name: "DoubleDownArrow", CodePoints: []int{8659}, Characters: []byte{0xe2, 0x87, 0x93}},
+ "DoubleLeftArrow": {Name: "DoubleLeftArrow", CodePoints: []int{8656}, Characters: []byte{0xe2, 0x87, 0x90}},
+ "DoubleLeftRightArrow": {Name: "DoubleLeftRightArrow", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
+ "DoubleLeftTee": {Name: "DoubleLeftTee", CodePoints: []int{10980}, Characters: []byte{0xe2, 0xab, 0xa4}},
+ "DoubleLongLeftArrow": {Name: "DoubleLongLeftArrow", CodePoints: []int{10232}, Characters: []byte{0xe2, 0x9f, 0xb8}},
+ "DoubleLongLeftRightArrow": {Name: "DoubleLongLeftRightArrow", CodePoints: []int{10234}, Characters: []byte{0xe2, 0x9f, 0xba}},
+ "DoubleLongRightArrow": {Name: "DoubleLongRightArrow", CodePoints: []int{10233}, Characters: []byte{0xe2, 0x9f, 0xb9}},
+ "DoubleRightArrow": {Name: "DoubleRightArrow", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
+ "DoubleRightTee": {Name: "DoubleRightTee", CodePoints: []int{8872}, Characters: []byte{0xe2, 0x8a, 0xa8}},
+ "DoubleUpArrow": {Name: "DoubleUpArrow", CodePoints: []int{8657}, Characters: []byte{0xe2, 0x87, 0x91}},
+ "DoubleUpDownArrow": {Name: "DoubleUpDownArrow", CodePoints: []int{8661}, Characters: []byte{0xe2, 0x87, 0x95}},
+ "DoubleVerticalBar": {Name: "DoubleVerticalBar", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
+ "DownArrow": {Name: "DownArrow", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
+ "DownArrowBar": {Name: "DownArrowBar", CodePoints: []int{10515}, Characters: []byte{0xe2, 0xa4, 0x93}},
+ "DownArrowUpArrow": {Name: "DownArrowUpArrow", CodePoints: []int{8693}, Characters: []byte{0xe2, 0x87, 0xb5}},
+ "DownBreve": {Name: "DownBreve", CodePoints: []int{785}, Characters: []byte{0xcc, 0x91}},
+ "DownLeftRightVector": {Name: "DownLeftRightVector", CodePoints: []int{10576}, Characters: []byte{0xe2, 0xa5, 0x90}},
+ "DownLeftTeeVector": {Name: "DownLeftTeeVector", CodePoints: []int{10590}, Characters: []byte{0xe2, 0xa5, 0x9e}},
+ "DownLeftVector": {Name: "DownLeftVector", CodePoints: []int{8637}, Characters: []byte{0xe2, 0x86, 0xbd}},
+ "DownLeftVectorBar": {Name: "DownLeftVectorBar", CodePoints: []int{10582}, Characters: []byte{0xe2, 0xa5, 0x96}},
+ "DownRightTeeVector": {Name: "DownRightTeeVector", CodePoints: []int{10591}, Characters: []byte{0xe2, 0xa5, 0x9f}},
+ "DownRightVector": {Name: "DownRightVector", CodePoints: []int{8641}, Characters: []byte{0xe2, 0x87, 0x81}},
+ "DownRightVectorBar": {Name: "DownRightVectorBar", CodePoints: []int{10583}, Characters: []byte{0xe2, 0xa5, 0x97}},
+ "DownTee": {Name: "DownTee", CodePoints: []int{8868}, Characters: []byte{0xe2, 0x8a, 0xa4}},
+ "DownTeeArrow": {Name: "DownTeeArrow", CodePoints: []int{8615}, Characters: []byte{0xe2, 0x86, 0xa7}},
+ "Downarrow": {Name: "Downarrow", CodePoints: []int{8659}, Characters: []byte{0xe2, 0x87, 0x93}},
+ "Dscr": {Name: "Dscr", CodePoints: []int{119967}, Characters: []byte{0xf0, 0x9d, 0x92, 0x9f}},
+ "Dstrok": {Name: "Dstrok", CodePoints: []int{272}, Characters: []byte{0xc4, 0x90}},
+ "ENG": {Name: "ENG", CodePoints: []int{330}, Characters: []byte{0xc5, 0x8a}},
+ "ETH": {Name: "ETH", CodePoints: []int{208}, Characters: []byte{0xc3, 0x90}},
+ "Eacute": {Name: "Eacute", CodePoints: []int{201}, Characters: []byte{0xc3, 0x89}},
+ "Ecaron": {Name: "Ecaron", CodePoints: []int{282}, Characters: []byte{0xc4, 0x9a}},
+ "Ecirc": {Name: "Ecirc", CodePoints: []int{202}, Characters: []byte{0xc3, 0x8a}},
+ "Ecy": {Name: "Ecy", CodePoints: []int{1069}, Characters: []byte{0xd0, 0xad}},
+ "Edot": {Name: "Edot", CodePoints: []int{278}, Characters: []byte{0xc4, 0x96}},
+ "Efr": {Name: "Efr", CodePoints: []int{120072}, Characters: []byte{0xf0, 0x9d, 0x94, 0x88}},
+ "Egrave": {Name: "Egrave", CodePoints: []int{200}, Characters: []byte{0xc3, 0x88}},
+ "Element": {Name: "Element", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
+ "Emacr": {Name: "Emacr", CodePoints: []int{274}, Characters: []byte{0xc4, 0x92}},
+ "EmptySmallSquare": {Name: "EmptySmallSquare", CodePoints: []int{9723}, Characters: []byte{0xe2, 0x97, 0xbb}},
+ "EmptyVerySmallSquare": {Name: "EmptyVerySmallSquare", CodePoints: []int{9643}, Characters: []byte{0xe2, 0x96, 0xab}},
+ "Eogon": {Name: "Eogon", CodePoints: []int{280}, Characters: []byte{0xc4, 0x98}},
+ "Eopf": {Name: "Eopf", CodePoints: []int{120124}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbc}},
+ "Epsilon": {Name: "Epsilon", CodePoints: []int{917}, Characters: []byte{0xce, 0x95}},
+ "Equal": {Name: "Equal", CodePoints: []int{10869}, Characters: []byte{0xe2, 0xa9, 0xb5}},
+ "EqualTilde": {Name: "EqualTilde", CodePoints: []int{8770}, Characters: []byte{0xe2, 0x89, 0x82}},
+ "Equilibrium": {Name: "Equilibrium", CodePoints: []int{8652}, Characters: []byte{0xe2, 0x87, 0x8c}},
+ "Escr": {Name: "Escr", CodePoints: []int{8496}, Characters: []byte{0xe2, 0x84, 0xb0}},
+ "Esim": {Name: "Esim", CodePoints: []int{10867}, Characters: []byte{0xe2, 0xa9, 0xb3}},
+ "Eta": {Name: "Eta", CodePoints: []int{919}, Characters: []byte{0xce, 0x97}},
+ "Euml": {Name: "Euml", CodePoints: []int{203}, Characters: []byte{0xc3, 0x8b}},
+ "Exists": {Name: "Exists", CodePoints: []int{8707}, Characters: []byte{0xe2, 0x88, 0x83}},
+ "ExponentialE": {Name: "ExponentialE", CodePoints: []int{8519}, Characters: []byte{0xe2, 0x85, 0x87}},
+ "Fcy": {Name: "Fcy", CodePoints: []int{1060}, Characters: []byte{0xd0, 0xa4}},
+ "Ffr": {Name: "Ffr", CodePoints: []int{120073}, Characters: []byte{0xf0, 0x9d, 0x94, 0x89}},
+ "FilledSmallSquare": {Name: "FilledSmallSquare", CodePoints: []int{9724}, Characters: []byte{0xe2, 0x97, 0xbc}},
+ "FilledVerySmallSquare": {Name: "FilledVerySmallSquare", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
+ "Fopf": {Name: "Fopf", CodePoints: []int{120125}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbd}},
+ "ForAll": {Name: "ForAll", CodePoints: []int{8704}, Characters: []byte{0xe2, 0x88, 0x80}},
+ "Fouriertrf": {Name: "Fouriertrf", CodePoints: []int{8497}, Characters: []byte{0xe2, 0x84, 0xb1}},
+ "Fscr": {Name: "Fscr", CodePoints: []int{8497}, Characters: []byte{0xe2, 0x84, 0xb1}},
+ "GJcy": {Name: "GJcy", CodePoints: []int{1027}, Characters: []byte{0xd0, 0x83}},
+ "GT": {Name: "GT", CodePoints: []int{62}, Characters: []byte{0x3e}},
+ "Gamma": {Name: "Gamma", CodePoints: []int{915}, Characters: []byte{0xce, 0x93}},
+ "Gammad": {Name: "Gammad", CodePoints: []int{988}, Characters: []byte{0xcf, 0x9c}},
+ "Gbreve": {Name: "Gbreve", CodePoints: []int{286}, Characters: []byte{0xc4, 0x9e}},
+ "Gcedil": {Name: "Gcedil", CodePoints: []int{290}, Characters: []byte{0xc4, 0xa2}},
+ "Gcirc": {Name: "Gcirc", CodePoints: []int{284}, Characters: []byte{0xc4, 0x9c}},
+ "Gcy": {Name: "Gcy", CodePoints: []int{1043}, Characters: []byte{0xd0, 0x93}},
+ "Gdot": {Name: "Gdot", CodePoints: []int{288}, Characters: []byte{0xc4, 0xa0}},
+ "Gfr": {Name: "Gfr", CodePoints: []int{120074}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8a}},
+ "Gg": {Name: "Gg", CodePoints: []int{8921}, Characters: []byte{0xe2, 0x8b, 0x99}},
+ "Gopf": {Name: "Gopf", CodePoints: []int{120126}, Characters: []byte{0xf0, 0x9d, 0x94, 0xbe}},
+ "GreaterEqual": {Name: "GreaterEqual", CodePoints: []int{8805}, Characters: []byte{0xe2, 0x89, 0xa5}},
+ "GreaterEqualLess": {Name: "GreaterEqualLess", CodePoints: []int{8923}, Characters: []byte{0xe2, 0x8b, 0x9b}},
+ "GreaterFullEqual": {Name: "GreaterFullEqual", CodePoints: []int{8807}, Characters: []byte{0xe2, 0x89, 0xa7}},
+ "GreaterGreater": {Name: "GreaterGreater", CodePoints: []int{10914}, Characters: []byte{0xe2, 0xaa, 0xa2}},
+ "GreaterLess": {Name: "GreaterLess", CodePoints: []int{8823}, Characters: []byte{0xe2, 0x89, 0xb7}},
+ "GreaterSlantEqual": {Name: "GreaterSlantEqual", CodePoints: []int{10878}, Characters: []byte{0xe2, 0xa9, 0xbe}},
+ "GreaterTilde": {Name: "GreaterTilde", CodePoints: []int{8819}, Characters: []byte{0xe2, 0x89, 0xb3}},
+ "Gscr": {Name: "Gscr", CodePoints: []int{119970}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa2}},
+ "Gt": {Name: "Gt", CodePoints: []int{8811}, Characters: []byte{0xe2, 0x89, 0xab}},
+ "HARDcy": {Name: "HARDcy", CodePoints: []int{1066}, Characters: []byte{0xd0, 0xaa}},
+ "Hacek": {Name: "Hacek", CodePoints: []int{711}, Characters: []byte{0xcb, 0x87}},
+ "Hat": {Name: "Hat", CodePoints: []int{94}, Characters: []byte{0x5e}},
+ "Hcirc": {Name: "Hcirc", CodePoints: []int{292}, Characters: []byte{0xc4, 0xa4}},
+ "Hfr": {Name: "Hfr", CodePoints: []int{8460}, Characters: []byte{0xe2, 0x84, 0x8c}},
+ "HilbertSpace": {Name: "HilbertSpace", CodePoints: []int{8459}, Characters: []byte{0xe2, 0x84, 0x8b}},
+ "Hopf": {Name: "Hopf", CodePoints: []int{8461}, Characters: []byte{0xe2, 0x84, 0x8d}},
+ "HorizontalLine": {Name: "HorizontalLine", CodePoints: []int{9472}, Characters: []byte{0xe2, 0x94, 0x80}},
+ "Hscr": {Name: "Hscr", CodePoints: []int{8459}, Characters: []byte{0xe2, 0x84, 0x8b}},
+ "Hstrok": {Name: "Hstrok", CodePoints: []int{294}, Characters: []byte{0xc4, 0xa6}},
+ "HumpDownHump": {Name: "HumpDownHump", CodePoints: []int{8782}, Characters: []byte{0xe2, 0x89, 0x8e}},
+ "HumpEqual": {Name: "HumpEqual", CodePoints: []int{8783}, Characters: []byte{0xe2, 0x89, 0x8f}},
+ "IEcy": {Name: "IEcy", CodePoints: []int{1045}, Characters: []byte{0xd0, 0x95}},
+ "IJlig": {Name: "IJlig", CodePoints: []int{306}, Characters: []byte{0xc4, 0xb2}},
+ "IOcy": {Name: "IOcy", CodePoints: []int{1025}, Characters: []byte{0xd0, 0x81}},
+ "Iacute": {Name: "Iacute", CodePoints: []int{205}, Characters: []byte{0xc3, 0x8d}},
+ "Icirc": {Name: "Icirc", CodePoints: []int{206}, Characters: []byte{0xc3, 0x8e}},
+ "Icy": {Name: "Icy", CodePoints: []int{1048}, Characters: []byte{0xd0, 0x98}},
+ "Idot": {Name: "Idot", CodePoints: []int{304}, Characters: []byte{0xc4, 0xb0}},
+ "Ifr": {Name: "Ifr", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
+ "Igrave": {Name: "Igrave", CodePoints: []int{204}, Characters: []byte{0xc3, 0x8c}},
+ "Im": {Name: "Im", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
+ "Imacr": {Name: "Imacr", CodePoints: []int{298}, Characters: []byte{0xc4, 0xaa}},
+ "ImaginaryI": {Name: "ImaginaryI", CodePoints: []int{8520}, Characters: []byte{0xe2, 0x85, 0x88}},
+ "Implies": {Name: "Implies", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
+ "Int": {Name: "Int", CodePoints: []int{8748}, Characters: []byte{0xe2, 0x88, 0xac}},
+ "Integral": {Name: "Integral", CodePoints: []int{8747}, Characters: []byte{0xe2, 0x88, 0xab}},
+ "Intersection": {Name: "Intersection", CodePoints: []int{8898}, Characters: []byte{0xe2, 0x8b, 0x82}},
+ "InvisibleComma": {Name: "InvisibleComma", CodePoints: []int{8291}, Characters: []byte{0xe2, 0x81, 0xa3}},
+ "InvisibleTimes": {Name: "InvisibleTimes", CodePoints: []int{8290}, Characters: []byte{0xe2, 0x81, 0xa2}},
+ "Iogon": {Name: "Iogon", CodePoints: []int{302}, Characters: []byte{0xc4, 0xae}},
+ "Iopf": {Name: "Iopf", CodePoints: []int{120128}, Characters: []byte{0xf0, 0x9d, 0x95, 0x80}},
+ "Iota": {Name: "Iota", CodePoints: []int{921}, Characters: []byte{0xce, 0x99}},
+ "Iscr": {Name: "Iscr", CodePoints: []int{8464}, Characters: []byte{0xe2, 0x84, 0x90}},
+ "Itilde": {Name: "Itilde", CodePoints: []int{296}, Characters: []byte{0xc4, 0xa8}},
+ "Iukcy": {Name: "Iukcy", CodePoints: []int{1030}, Characters: []byte{0xd0, 0x86}},
+ "Iuml": {Name: "Iuml", CodePoints: []int{207}, Characters: []byte{0xc3, 0x8f}},
+ "Jcirc": {Name: "Jcirc", CodePoints: []int{308}, Characters: []byte{0xc4, 0xb4}},
+ "Jcy": {Name: "Jcy", CodePoints: []int{1049}, Characters: []byte{0xd0, 0x99}},
+ "Jfr": {Name: "Jfr", CodePoints: []int{120077}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8d}},
+ "Jopf": {Name: "Jopf", CodePoints: []int{120129}, Characters: []byte{0xf0, 0x9d, 0x95, 0x81}},
+ "Jscr": {Name: "Jscr", CodePoints: []int{119973}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa5}},
+ "Jsercy": {Name: "Jsercy", CodePoints: []int{1032}, Characters: []byte{0xd0, 0x88}},
+ "Jukcy": {Name: "Jukcy", CodePoints: []int{1028}, Characters: []byte{0xd0, 0x84}},
+ "KHcy": {Name: "KHcy", CodePoints: []int{1061}, Characters: []byte{0xd0, 0xa5}},
+ "KJcy": {Name: "KJcy", CodePoints: []int{1036}, Characters: []byte{0xd0, 0x8c}},
+ "Kappa": {Name: "Kappa", CodePoints: []int{922}, Characters: []byte{0xce, 0x9a}},
+ "Kcedil": {Name: "Kcedil", CodePoints: []int{310}, Characters: []byte{0xc4, 0xb6}},
+ "Kcy": {Name: "Kcy", CodePoints: []int{1050}, Characters: []byte{0xd0, 0x9a}},
+ "Kfr": {Name: "Kfr", CodePoints: []int{120078}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8e}},
+ "Kopf": {Name: "Kopf", CodePoints: []int{120130}, Characters: []byte{0xf0, 0x9d, 0x95, 0x82}},
+ "Kscr": {Name: "Kscr", CodePoints: []int{119974}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa6}},
+ "LJcy": {Name: "LJcy", CodePoints: []int{1033}, Characters: []byte{0xd0, 0x89}},
+ "LT": {Name: "LT", CodePoints: []int{60}, Characters: []byte{0x3c}},
+ "Lacute": {Name: "Lacute", CodePoints: []int{313}, Characters: []byte{0xc4, 0xb9}},
+ "Lambda": {Name: "Lambda", CodePoints: []int{923}, Characters: []byte{0xce, 0x9b}},
+ "Lang": {Name: "Lang", CodePoints: []int{10218}, Characters: []byte{0xe2, 0x9f, 0xaa}},
+ "Laplacetrf": {Name: "Laplacetrf", CodePoints: []int{8466}, Characters: []byte{0xe2, 0x84, 0x92}},
+ "Larr": {Name: "Larr", CodePoints: []int{8606}, Characters: []byte{0xe2, 0x86, 0x9e}},
+ "Lcaron": {Name: "Lcaron", CodePoints: []int{317}, Characters: []byte{0xc4, 0xbd}},
+ "Lcedil": {Name: "Lcedil", CodePoints: []int{315}, Characters: []byte{0xc4, 0xbb}},
+ "Lcy": {Name: "Lcy", CodePoints: []int{1051}, Characters: []byte{0xd0, 0x9b}},
+ "LeftAngleBracket": {Name: "LeftAngleBracket", CodePoints: []int{10216}, Characters: []byte{0xe2, 0x9f, 0xa8}},
+ "LeftArrow": {Name: "LeftArrow", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
+ "LeftArrowBar": {Name: "LeftArrowBar", CodePoints: []int{8676}, Characters: []byte{0xe2, 0x87, 0xa4}},
+ "LeftArrowRightArrow": {Name: "LeftArrowRightArrow", CodePoints: []int{8646}, Characters: []byte{0xe2, 0x87, 0x86}},
+ "LeftCeiling": {Name: "LeftCeiling", CodePoints: []int{8968}, Characters: []byte{0xe2, 0x8c, 0x88}},
+ "LeftDoubleBracket": {Name: "LeftDoubleBracket", CodePoints: []int{10214}, Characters: []byte{0xe2, 0x9f, 0xa6}},
+ "LeftDownTeeVector": {Name: "LeftDownTeeVector", CodePoints: []int{10593}, Characters: []byte{0xe2, 0xa5, 0xa1}},
+ "LeftDownVector": {Name: "LeftDownVector", CodePoints: []int{8643}, Characters: []byte{0xe2, 0x87, 0x83}},
+ "LeftDownVectorBar": {Name: "LeftDownVectorBar", CodePoints: []int{10585}, Characters: []byte{0xe2, 0xa5, 0x99}},
+ "LeftFloor": {Name: "LeftFloor", CodePoints: []int{8970}, Characters: []byte{0xe2, 0x8c, 0x8a}},
+ "LeftRightArrow": {Name: "LeftRightArrow", CodePoints: []int{8596}, Characters: []byte{0xe2, 0x86, 0x94}},
+ "LeftRightVector": {Name: "LeftRightVector", CodePoints: []int{10574}, Characters: []byte{0xe2, 0xa5, 0x8e}},
+ "LeftTee": {Name: "LeftTee", CodePoints: []int{8867}, Characters: []byte{0xe2, 0x8a, 0xa3}},
+ "LeftTeeArrow": {Name: "LeftTeeArrow", CodePoints: []int{8612}, Characters: []byte{0xe2, 0x86, 0xa4}},
+ "LeftTeeVector": {Name: "LeftTeeVector", CodePoints: []int{10586}, Characters: []byte{0xe2, 0xa5, 0x9a}},
+ "LeftTriangle": {Name: "LeftTriangle", CodePoints: []int{8882}, Characters: []byte{0xe2, 0x8a, 0xb2}},
+ "LeftTriangleBar": {Name: "LeftTriangleBar", CodePoints: []int{10703}, Characters: []byte{0xe2, 0xa7, 0x8f}},
+ "LeftTriangleEqual": {Name: "LeftTriangleEqual", CodePoints: []int{8884}, Characters: []byte{0xe2, 0x8a, 0xb4}},
+ "LeftUpDownVector": {Name: "LeftUpDownVector", CodePoints: []int{10577}, Characters: []byte{0xe2, 0xa5, 0x91}},
+ "LeftUpTeeVector": {Name: "LeftUpTeeVector", CodePoints: []int{10592}, Characters: []byte{0xe2, 0xa5, 0xa0}},
+ "LeftUpVector": {Name: "LeftUpVector", CodePoints: []int{8639}, Characters: []byte{0xe2, 0x86, 0xbf}},
+ "LeftUpVectorBar": {Name: "LeftUpVectorBar", CodePoints: []int{10584}, Characters: []byte{0xe2, 0xa5, 0x98}},
+ "LeftVector": {Name: "LeftVector", CodePoints: []int{8636}, Characters: []byte{0xe2, 0x86, 0xbc}},
+ "LeftVectorBar": {Name: "LeftVectorBar", CodePoints: []int{10578}, Characters: []byte{0xe2, 0xa5, 0x92}},
+ "Leftarrow": {Name: "Leftarrow", CodePoints: []int{8656}, Characters: []byte{0xe2, 0x87, 0x90}},
+ "Leftrightarrow": {Name: "Leftrightarrow", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
+ "LessEqualGreater": {Name: "LessEqualGreater", CodePoints: []int{8922}, Characters: []byte{0xe2, 0x8b, 0x9a}},
+ "LessFullEqual": {Name: "LessFullEqual", CodePoints: []int{8806}, Characters: []byte{0xe2, 0x89, 0xa6}},
+ "LessGreater": {Name: "LessGreater", CodePoints: []int{8822}, Characters: []byte{0xe2, 0x89, 0xb6}},
+ "LessLess": {Name: "LessLess", CodePoints: []int{10913}, Characters: []byte{0xe2, 0xaa, 0xa1}},
+ "LessSlantEqual": {Name: "LessSlantEqual", CodePoints: []int{10877}, Characters: []byte{0xe2, 0xa9, 0xbd}},
+ "LessTilde": {Name: "LessTilde", CodePoints: []int{8818}, Characters: []byte{0xe2, 0x89, 0xb2}},
+ "Lfr": {Name: "Lfr", CodePoints: []int{120079}, Characters: []byte{0xf0, 0x9d, 0x94, 0x8f}},
+ "Ll": {Name: "Ll", CodePoints: []int{8920}, Characters: []byte{0xe2, 0x8b, 0x98}},
+ "Lleftarrow": {Name: "Lleftarrow", CodePoints: []int{8666}, Characters: []byte{0xe2, 0x87, 0x9a}},
+ "Lmidot": {Name: "Lmidot", CodePoints: []int{319}, Characters: []byte{0xc4, 0xbf}},
+ "LongLeftArrow": {Name: "LongLeftArrow", CodePoints: []int{10229}, Characters: []byte{0xe2, 0x9f, 0xb5}},
+ "LongLeftRightArrow": {Name: "LongLeftRightArrow", CodePoints: []int{10231}, Characters: []byte{0xe2, 0x9f, 0xb7}},
+ "LongRightArrow": {Name: "LongRightArrow", CodePoints: []int{10230}, Characters: []byte{0xe2, 0x9f, 0xb6}},
+ "Longleftarrow": {Name: "Longleftarrow", CodePoints: []int{10232}, Characters: []byte{0xe2, 0x9f, 0xb8}},
+ "Longleftrightarrow": {Name: "Longleftrightarrow", CodePoints: []int{10234}, Characters: []byte{0xe2, 0x9f, 0xba}},
+ "Longrightarrow": {Name: "Longrightarrow", CodePoints: []int{10233}, Characters: []byte{0xe2, 0x9f, 0xb9}},
+ "Lopf": {Name: "Lopf", CodePoints: []int{120131}, Characters: []byte{0xf0, 0x9d, 0x95, 0x83}},
+ "LowerLeftArrow": {Name: "LowerLeftArrow", CodePoints: []int{8601}, Characters: []byte{0xe2, 0x86, 0x99}},
+ "LowerRightArrow": {Name: "LowerRightArrow", CodePoints: []int{8600}, Characters: []byte{0xe2, 0x86, 0x98}},
+ "Lscr": {Name: "Lscr", CodePoints: []int{8466}, Characters: []byte{0xe2, 0x84, 0x92}},
+ "Lsh": {Name: "Lsh", CodePoints: []int{8624}, Characters: []byte{0xe2, 0x86, 0xb0}},
+ "Lstrok": {Name: "Lstrok", CodePoints: []int{321}, Characters: []byte{0xc5, 0x81}},
+ "Lt": {Name: "Lt", CodePoints: []int{8810}, Characters: []byte{0xe2, 0x89, 0xaa}},
+ "Map": {Name: "Map", CodePoints: []int{10501}, Characters: []byte{0xe2, 0xa4, 0x85}},
+ "Mcy": {Name: "Mcy", CodePoints: []int{1052}, Characters: []byte{0xd0, 0x9c}},
+ "MediumSpace": {Name: "MediumSpace", CodePoints: []int{8287}, Characters: []byte{0xe2, 0x81, 0x9f}},
+ "Mellintrf": {Name: "Mellintrf", CodePoints: []int{8499}, Characters: []byte{0xe2, 0x84, 0xb3}},
+ "Mfr": {Name: "Mfr", CodePoints: []int{120080}, Characters: []byte{0xf0, 0x9d, 0x94, 0x90}},
+ "MinusPlus": {Name: "MinusPlus", CodePoints: []int{8723}, Characters: []byte{0xe2, 0x88, 0x93}},
+ "Mopf": {Name: "Mopf", CodePoints: []int{120132}, Characters: []byte{0xf0, 0x9d, 0x95, 0x84}},
+ "Mscr": {Name: "Mscr", CodePoints: []int{8499}, Characters: []byte{0xe2, 0x84, 0xb3}},
+ "Mu": {Name: "Mu", CodePoints: []int{924}, Characters: []byte{0xce, 0x9c}},
+ "NJcy": {Name: "NJcy", CodePoints: []int{1034}, Characters: []byte{0xd0, 0x8a}},
+ "Nacute": {Name: "Nacute", CodePoints: []int{323}, Characters: []byte{0xc5, 0x83}},
+ "Ncaron": {Name: "Ncaron", CodePoints: []int{327}, Characters: []byte{0xc5, 0x87}},
+ "Ncedil": {Name: "Ncedil", CodePoints: []int{325}, Characters: []byte{0xc5, 0x85}},
+ "Ncy": {Name: "Ncy", CodePoints: []int{1053}, Characters: []byte{0xd0, 0x9d}},
+ "NegativeMediumSpace": {Name: "NegativeMediumSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
+ "NegativeThickSpace": {Name: "NegativeThickSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
+ "NegativeThinSpace": {Name: "NegativeThinSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
+ "NegativeVeryThinSpace": {Name: "NegativeVeryThinSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
+ "NestedGreaterGreater": {Name: "NestedGreaterGreater", CodePoints: []int{8811}, Characters: []byte{0xe2, 0x89, 0xab}},
+ "NestedLessLess": {Name: "NestedLessLess", CodePoints: []int{8810}, Characters: []byte{0xe2, 0x89, 0xaa}},
+ "NewLine": {Name: "NewLine", CodePoints: []int{10}, Characters: []byte{0xa}},
+ "Nfr": {Name: "Nfr", CodePoints: []int{120081}, Characters: []byte{0xf0, 0x9d, 0x94, 0x91}},
+ "NoBreak": {Name: "NoBreak", CodePoints: []int{8288}, Characters: []byte{0xe2, 0x81, 0xa0}},
+ "NonBreakingSpace": {Name: "NonBreakingSpace", CodePoints: []int{160}, Characters: []byte{0xc2, 0xa0}},
+ "Nopf": {Name: "Nopf", CodePoints: []int{8469}, Characters: []byte{0xe2, 0x84, 0x95}},
+ "Not": {Name: "Not", CodePoints: []int{10988}, Characters: []byte{0xe2, 0xab, 0xac}},
+ "NotCongruent": {Name: "NotCongruent", CodePoints: []int{8802}, Characters: []byte{0xe2, 0x89, 0xa2}},
+ "NotCupCap": {Name: "NotCupCap", CodePoints: []int{8813}, Characters: []byte{0xe2, 0x89, 0xad}},
+ "NotDoubleVerticalBar": {Name: "NotDoubleVerticalBar", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
+ "NotElement": {Name: "NotElement", CodePoints: []int{8713}, Characters: []byte{0xe2, 0x88, 0x89}},
+ "NotEqual": {Name: "NotEqual", CodePoints: []int{8800}, Characters: []byte{0xe2, 0x89, 0xa0}},
+ "NotEqualTilde": {Name: "NotEqualTilde", CodePoints: []int{8770, 824}, Characters: []byte{0xe2, 0x89, 0x82, 0xcc, 0xb8}},
+ "NotExists": {Name: "NotExists", CodePoints: []int{8708}, Characters: []byte{0xe2, 0x88, 0x84}},
+ "NotGreater": {Name: "NotGreater", CodePoints: []int{8815}, Characters: []byte{0xe2, 0x89, 0xaf}},
+ "NotGreaterEqual": {Name: "NotGreaterEqual", CodePoints: []int{8817}, Characters: []byte{0xe2, 0x89, 0xb1}},
+ "NotGreaterFullEqual": {Name: "NotGreaterFullEqual", CodePoints: []int{8807, 824}, Characters: []byte{0xe2, 0x89, 0xa7, 0xcc, 0xb8}},
+ "NotGreaterGreater": {Name: "NotGreaterGreater", CodePoints: []int{8811, 824}, Characters: []byte{0xe2, 0x89, 0xab, 0xcc, 0xb8}},
+ "NotGreaterLess": {Name: "NotGreaterLess", CodePoints: []int{8825}, Characters: []byte{0xe2, 0x89, 0xb9}},
+ "NotGreaterSlantEqual": {Name: "NotGreaterSlantEqual", CodePoints: []int{10878, 824}, Characters: []byte{0xe2, 0xa9, 0xbe, 0xcc, 0xb8}},
+ "NotGreaterTilde": {Name: "NotGreaterTilde", CodePoints: []int{8821}, Characters: []byte{0xe2, 0x89, 0xb5}},
+ "NotHumpDownHump": {Name: "NotHumpDownHump", CodePoints: []int{8782, 824}, Characters: []byte{0xe2, 0x89, 0x8e, 0xcc, 0xb8}},
+ "NotHumpEqual": {Name: "NotHumpEqual", CodePoints: []int{8783, 824}, Characters: []byte{0xe2, 0x89, 0x8f, 0xcc, 0xb8}},
+ "NotLeftTriangle": {Name: "NotLeftTriangle", CodePoints: []int{8938}, Characters: []byte{0xe2, 0x8b, 0xaa}},
+ "NotLeftTriangleBar": {Name: "NotLeftTriangleBar", CodePoints: []int{10703, 824}, Characters: []byte{0xe2, 0xa7, 0x8f, 0xcc, 0xb8}},
+ "NotLeftTriangleEqual": {Name: "NotLeftTriangleEqual", CodePoints: []int{8940}, Characters: []byte{0xe2, 0x8b, 0xac}},
+ "NotLess": {Name: "NotLess", CodePoints: []int{8814}, Characters: []byte{0xe2, 0x89, 0xae}},
+ "NotLessEqual": {Name: "NotLessEqual", CodePoints: []int{8816}, Characters: []byte{0xe2, 0x89, 0xb0}},
+ "NotLessGreater": {Name: "NotLessGreater", CodePoints: []int{8824}, Characters: []byte{0xe2, 0x89, 0xb8}},
+ "NotLessLess": {Name: "NotLessLess", CodePoints: []int{8810, 824}, Characters: []byte{0xe2, 0x89, 0xaa, 0xcc, 0xb8}},
+ "NotLessSlantEqual": {Name: "NotLessSlantEqual", CodePoints: []int{10877, 824}, Characters: []byte{0xe2, 0xa9, 0xbd, 0xcc, 0xb8}},
+ "NotLessTilde": {Name: "NotLessTilde", CodePoints: []int{8820}, Characters: []byte{0xe2, 0x89, 0xb4}},
+ "NotNestedGreaterGreater": {Name: "NotNestedGreaterGreater", CodePoints: []int{10914, 824}, Characters: []byte{0xe2, 0xaa, 0xa2, 0xcc, 0xb8}},
+ "NotNestedLessLess": {Name: "NotNestedLessLess", CodePoints: []int{10913, 824}, Characters: []byte{0xe2, 0xaa, 0xa1, 0xcc, 0xb8}},
+ "NotPrecedes": {Name: "NotPrecedes", CodePoints: []int{8832}, Characters: []byte{0xe2, 0x8a, 0x80}},
+ "NotPrecedesEqual": {Name: "NotPrecedesEqual", CodePoints: []int{10927, 824}, Characters: []byte{0xe2, 0xaa, 0xaf, 0xcc, 0xb8}},
+ "NotPrecedesSlantEqual": {Name: "NotPrecedesSlantEqual", CodePoints: []int{8928}, Characters: []byte{0xe2, 0x8b, 0xa0}},
+ "NotReverseElement": {Name: "NotReverseElement", CodePoints: []int{8716}, Characters: []byte{0xe2, 0x88, 0x8c}},
+ "NotRightTriangle": {Name: "NotRightTriangle", CodePoints: []int{8939}, Characters: []byte{0xe2, 0x8b, 0xab}},
+ "NotRightTriangleBar": {Name: "NotRightTriangleBar", CodePoints: []int{10704, 824}, Characters: []byte{0xe2, 0xa7, 0x90, 0xcc, 0xb8}},
+ "NotRightTriangleEqual": {Name: "NotRightTriangleEqual", CodePoints: []int{8941}, Characters: []byte{0xe2, 0x8b, 0xad}},
+ "NotSquareSubset": {Name: "NotSquareSubset", CodePoints: []int{8847, 824}, Characters: []byte{0xe2, 0x8a, 0x8f, 0xcc, 0xb8}},
+ "NotSquareSubsetEqual": {Name: "NotSquareSubsetEqual", CodePoints: []int{8930}, Characters: []byte{0xe2, 0x8b, 0xa2}},
+ "NotSquareSuperset": {Name: "NotSquareSuperset", CodePoints: []int{8848, 824}, Characters: []byte{0xe2, 0x8a, 0x90, 0xcc, 0xb8}},
+ "NotSquareSupersetEqual": {Name: "NotSquareSupersetEqual", CodePoints: []int{8931}, Characters: []byte{0xe2, 0x8b, 0xa3}},
+ "NotSubset": {Name: "NotSubset", CodePoints: []int{8834, 8402}, Characters: []byte{0xe2, 0x8a, 0x82, 0xe2, 0x83, 0x92}},
+ "NotSubsetEqual": {Name: "NotSubsetEqual", CodePoints: []int{8840}, Characters: []byte{0xe2, 0x8a, 0x88}},
+ "NotSucceeds": {Name: "NotSucceeds", CodePoints: []int{8833}, Characters: []byte{0xe2, 0x8a, 0x81}},
+ "NotSucceedsEqual": {Name: "NotSucceedsEqual", CodePoints: []int{10928, 824}, Characters: []byte{0xe2, 0xaa, 0xb0, 0xcc, 0xb8}},
+ "NotSucceedsSlantEqual": {Name: "NotSucceedsSlantEqual", CodePoints: []int{8929}, Characters: []byte{0xe2, 0x8b, 0xa1}},
+ "NotSucceedsTilde": {Name: "NotSucceedsTilde", CodePoints: []int{8831, 824}, Characters: []byte{0xe2, 0x89, 0xbf, 0xcc, 0xb8}},
+ "NotSuperset": {Name: "NotSuperset", CodePoints: []int{8835, 8402}, Characters: []byte{0xe2, 0x8a, 0x83, 0xe2, 0x83, 0x92}},
+ "NotSupersetEqual": {Name: "NotSupersetEqual", CodePoints: []int{8841}, Characters: []byte{0xe2, 0x8a, 0x89}},
+ "NotTilde": {Name: "NotTilde", CodePoints: []int{8769}, Characters: []byte{0xe2, 0x89, 0x81}},
+ "NotTildeEqual": {Name: "NotTildeEqual", CodePoints: []int{8772}, Characters: []byte{0xe2, 0x89, 0x84}},
+ "NotTildeFullEqual": {Name: "NotTildeFullEqual", CodePoints: []int{8775}, Characters: []byte{0xe2, 0x89, 0x87}},
+ "NotTildeTilde": {Name: "NotTildeTilde", CodePoints: []int{8777}, Characters: []byte{0xe2, 0x89, 0x89}},
+ "NotVerticalBar": {Name: "NotVerticalBar", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
+ "Nscr": {Name: "Nscr", CodePoints: []int{119977}, Characters: []byte{0xf0, 0x9d, 0x92, 0xa9}},
+ "Ntilde": {Name: "Ntilde", CodePoints: []int{209}, Characters: []byte{0xc3, 0x91}},
+ "Nu": {Name: "Nu", CodePoints: []int{925}, Characters: []byte{0xce, 0x9d}},
+ "OElig": {Name: "OElig", CodePoints: []int{338}, Characters: []byte{0xc5, 0x92}},
+ "Oacute": {Name: "Oacute", CodePoints: []int{211}, Characters: []byte{0xc3, 0x93}},
+ "Ocirc": {Name: "Ocirc", CodePoints: []int{212}, Characters: []byte{0xc3, 0x94}},
+ "Ocy": {Name: "Ocy", CodePoints: []int{1054}, Characters: []byte{0xd0, 0x9e}},
+ "Odblac": {Name: "Odblac", CodePoints: []int{336}, Characters: []byte{0xc5, 0x90}},
+ "Ofr": {Name: "Ofr", CodePoints: []int{120082}, Characters: []byte{0xf0, 0x9d, 0x94, 0x92}},
+ "Ograve": {Name: "Ograve", CodePoints: []int{210}, Characters: []byte{0xc3, 0x92}},
+ "Omacr": {Name: "Omacr", CodePoints: []int{332}, Characters: []byte{0xc5, 0x8c}},
+ "Omega": {Name: "Omega", CodePoints: []int{937}, Characters: []byte{0xce, 0xa9}},
+ "Omicron": {Name: "Omicron", CodePoints: []int{927}, Characters: []byte{0xce, 0x9f}},
+ "Oopf": {Name: "Oopf", CodePoints: []int{120134}, Characters: []byte{0xf0, 0x9d, 0x95, 0x86}},
+ "OpenCurlyDoubleQuote": {Name: "OpenCurlyDoubleQuote", CodePoints: []int{8220}, Characters: []byte{0xe2, 0x80, 0x9c}},
+ "OpenCurlyQuote": {Name: "OpenCurlyQuote", CodePoints: []int{8216}, Characters: []byte{0xe2, 0x80, 0x98}},
+ "Or": {Name: "Or", CodePoints: []int{10836}, Characters: []byte{0xe2, 0xa9, 0x94}},
+ "Oscr": {Name: "Oscr", CodePoints: []int{119978}, Characters: []byte{0xf0, 0x9d, 0x92, 0xaa}},
+ "Oslash": {Name: "Oslash", CodePoints: []int{216}, Characters: []byte{0xc3, 0x98}},
+ "Otilde": {Name: "Otilde", CodePoints: []int{213}, Characters: []byte{0xc3, 0x95}},
+ "Otimes": {Name: "Otimes", CodePoints: []int{10807}, Characters: []byte{0xe2, 0xa8, 0xb7}},
+ "Ouml": {Name: "Ouml", CodePoints: []int{214}, Characters: []byte{0xc3, 0x96}},
+ "OverBar": {Name: "OverBar", CodePoints: []int{8254}, Characters: []byte{0xe2, 0x80, 0xbe}},
+ "OverBrace": {Name: "OverBrace", CodePoints: []int{9182}, Characters: []byte{0xe2, 0x8f, 0x9e}},
+ "OverBracket": {Name: "OverBracket", CodePoints: []int{9140}, Characters: []byte{0xe2, 0x8e, 0xb4}},
+ "OverParenthesis": {Name: "OverParenthesis", CodePoints: []int{9180}, Characters: []byte{0xe2, 0x8f, 0x9c}},
+ "PartialD": {Name: "PartialD", CodePoints: []int{8706}, Characters: []byte{0xe2, 0x88, 0x82}},
+ "Pcy": {Name: "Pcy", CodePoints: []int{1055}, Characters: []byte{0xd0, 0x9f}},
+ "Pfr": {Name: "Pfr", CodePoints: []int{120083}, Characters: []byte{0xf0, 0x9d, 0x94, 0x93}},
+ "Phi": {Name: "Phi", CodePoints: []int{934}, Characters: []byte{0xce, 0xa6}},
+ "Pi": {Name: "Pi", CodePoints: []int{928}, Characters: []byte{0xce, 0xa0}},
+ "PlusMinus": {Name: "PlusMinus", CodePoints: []int{177}, Characters: []byte{0xc2, 0xb1}},
+ "Poincareplane": {Name: "Poincareplane", CodePoints: []int{8460}, Characters: []byte{0xe2, 0x84, 0x8c}},
+ "Popf": {Name: "Popf", CodePoints: []int{8473}, Characters: []byte{0xe2, 0x84, 0x99}},
+ "Pr": {Name: "Pr", CodePoints: []int{10939}, Characters: []byte{0xe2, 0xaa, 0xbb}},
+ "Precedes": {Name: "Precedes", CodePoints: []int{8826}, Characters: []byte{0xe2, 0x89, 0xba}},
+ "PrecedesEqual": {Name: "PrecedesEqual", CodePoints: []int{10927}, Characters: []byte{0xe2, 0xaa, 0xaf}},
+ "PrecedesSlantEqual": {Name: "PrecedesSlantEqual", CodePoints: []int{8828}, Characters: []byte{0xe2, 0x89, 0xbc}},
+ "PrecedesTilde": {Name: "PrecedesTilde", CodePoints: []int{8830}, Characters: []byte{0xe2, 0x89, 0xbe}},
+ "Prime": {Name: "Prime", CodePoints: []int{8243}, Characters: []byte{0xe2, 0x80, 0xb3}},
+ "Product": {Name: "Product", CodePoints: []int{8719}, Characters: []byte{0xe2, 0x88, 0x8f}},
+ "Proportion": {Name: "Proportion", CodePoints: []int{8759}, Characters: []byte{0xe2, 0x88, 0xb7}},
+ "Proportional": {Name: "Proportional", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
+ "Pscr": {Name: "Pscr", CodePoints: []int{119979}, Characters: []byte{0xf0, 0x9d, 0x92, 0xab}},
+ "Psi": {Name: "Psi", CodePoints: []int{936}, Characters: []byte{0xce, 0xa8}},
+ "QUOT": {Name: "QUOT", CodePoints: []int{34}, Characters: []byte{0x22}},
+ "Qfr": {Name: "Qfr", CodePoints: []int{120084}, Characters: []byte{0xf0, 0x9d, 0x94, 0x94}},
+ "Qopf": {Name: "Qopf", CodePoints: []int{8474}, Characters: []byte{0xe2, 0x84, 0x9a}},
+ "Qscr": {Name: "Qscr", CodePoints: []int{119980}, Characters: []byte{0xf0, 0x9d, 0x92, 0xac}},
+ "RBarr": {Name: "RBarr", CodePoints: []int{10512}, Characters: []byte{0xe2, 0xa4, 0x90}},
+ "REG": {Name: "REG", CodePoints: []int{174}, Characters: []byte{0xc2, 0xae}},
+ "Racute": {Name: "Racute", CodePoints: []int{340}, Characters: []byte{0xc5, 0x94}},
+ "Rang": {Name: "Rang", CodePoints: []int{10219}, Characters: []byte{0xe2, 0x9f, 0xab}},
+ "Rarr": {Name: "Rarr", CodePoints: []int{8608}, Characters: []byte{0xe2, 0x86, 0xa0}},
+ "Rarrtl": {Name: "Rarrtl", CodePoints: []int{10518}, Characters: []byte{0xe2, 0xa4, 0x96}},
+ "Rcaron": {Name: "Rcaron", CodePoints: []int{344}, Characters: []byte{0xc5, 0x98}},
+ "Rcedil": {Name: "Rcedil", CodePoints: []int{342}, Characters: []byte{0xc5, 0x96}},
+ "Rcy": {Name: "Rcy", CodePoints: []int{1056}, Characters: []byte{0xd0, 0xa0}},
+ "Re": {Name: "Re", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
+ "ReverseElement": {Name: "ReverseElement", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
+ "ReverseEquilibrium": {Name: "ReverseEquilibrium", CodePoints: []int{8651}, Characters: []byte{0xe2, 0x87, 0x8b}},
+ "ReverseUpEquilibrium": {Name: "ReverseUpEquilibrium", CodePoints: []int{10607}, Characters: []byte{0xe2, 0xa5, 0xaf}},
+ "Rfr": {Name: "Rfr", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
+ "Rho": {Name: "Rho", CodePoints: []int{929}, Characters: []byte{0xce, 0xa1}},
+ "RightAngleBracket": {Name: "RightAngleBracket", CodePoints: []int{10217}, Characters: []byte{0xe2, 0x9f, 0xa9}},
+ "RightArrow": {Name: "RightArrow", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
+ "RightArrowBar": {Name: "RightArrowBar", CodePoints: []int{8677}, Characters: []byte{0xe2, 0x87, 0xa5}},
+ "RightArrowLeftArrow": {Name: "RightArrowLeftArrow", CodePoints: []int{8644}, Characters: []byte{0xe2, 0x87, 0x84}},
+ "RightCeiling": {Name: "RightCeiling", CodePoints: []int{8969}, Characters: []byte{0xe2, 0x8c, 0x89}},
+ "RightDoubleBracket": {Name: "RightDoubleBracket", CodePoints: []int{10215}, Characters: []byte{0xe2, 0x9f, 0xa7}},
+ "RightDownTeeVector": {Name: "RightDownTeeVector", CodePoints: []int{10589}, Characters: []byte{0xe2, 0xa5, 0x9d}},
+ "RightDownVector": {Name: "RightDownVector", CodePoints: []int{8642}, Characters: []byte{0xe2, 0x87, 0x82}},
+ "RightDownVectorBar": {Name: "RightDownVectorBar", CodePoints: []int{10581}, Characters: []byte{0xe2, 0xa5, 0x95}},
+ "RightFloor": {Name: "RightFloor", CodePoints: []int{8971}, Characters: []byte{0xe2, 0x8c, 0x8b}},
+ "RightTee": {Name: "RightTee", CodePoints: []int{8866}, Characters: []byte{0xe2, 0x8a, 0xa2}},
+ "RightTeeArrow": {Name: "RightTeeArrow", CodePoints: []int{8614}, Characters: []byte{0xe2, 0x86, 0xa6}},
+ "RightTeeVector": {Name: "RightTeeVector", CodePoints: []int{10587}, Characters: []byte{0xe2, 0xa5, 0x9b}},
+ "RightTriangle": {Name: "RightTriangle", CodePoints: []int{8883}, Characters: []byte{0xe2, 0x8a, 0xb3}},
+ "RightTriangleBar": {Name: "RightTriangleBar", CodePoints: []int{10704}, Characters: []byte{0xe2, 0xa7, 0x90}},
+ "RightTriangleEqual": {Name: "RightTriangleEqual", CodePoints: []int{8885}, Characters: []byte{0xe2, 0x8a, 0xb5}},
+ "RightUpDownVector": {Name: "RightUpDownVector", CodePoints: []int{10575}, Characters: []byte{0xe2, 0xa5, 0x8f}},
+ "RightUpTeeVector": {Name: "RightUpTeeVector", CodePoints: []int{10588}, Characters: []byte{0xe2, 0xa5, 0x9c}},
+ "RightUpVector": {Name: "RightUpVector", CodePoints: []int{8638}, Characters: []byte{0xe2, 0x86, 0xbe}},
+ "RightUpVectorBar": {Name: "RightUpVectorBar", CodePoints: []int{10580}, Characters: []byte{0xe2, 0xa5, 0x94}},
+ "RightVector": {Name: "RightVector", CodePoints: []int{8640}, Characters: []byte{0xe2, 0x87, 0x80}},
+ "RightVectorBar": {Name: "RightVectorBar", CodePoints: []int{10579}, Characters: []byte{0xe2, 0xa5, 0x93}},
+ "Rightarrow": {Name: "Rightarrow", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
+ "Ropf": {Name: "Ropf", CodePoints: []int{8477}, Characters: []byte{0xe2, 0x84, 0x9d}},
+ "RoundImplies": {Name: "RoundImplies", CodePoints: []int{10608}, Characters: []byte{0xe2, 0xa5, 0xb0}},
+ "Rrightarrow": {Name: "Rrightarrow", CodePoints: []int{8667}, Characters: []byte{0xe2, 0x87, 0x9b}},
+ "Rscr": {Name: "Rscr", CodePoints: []int{8475}, Characters: []byte{0xe2, 0x84, 0x9b}},
+ "Rsh": {Name: "Rsh", CodePoints: []int{8625}, Characters: []byte{0xe2, 0x86, 0xb1}},
+ "RuleDelayed": {Name: "RuleDelayed", CodePoints: []int{10740}, Characters: []byte{0xe2, 0xa7, 0xb4}},
+ "SHCHcy": {Name: "SHCHcy", CodePoints: []int{1065}, Characters: []byte{0xd0, 0xa9}},
+ "SHcy": {Name: "SHcy", CodePoints: []int{1064}, Characters: []byte{0xd0, 0xa8}},
+ "SOFTcy": {Name: "SOFTcy", CodePoints: []int{1068}, Characters: []byte{0xd0, 0xac}},
+ "Sacute": {Name: "Sacute", CodePoints: []int{346}, Characters: []byte{0xc5, 0x9a}},
+ "Sc": {Name: "Sc", CodePoints: []int{10940}, Characters: []byte{0xe2, 0xaa, 0xbc}},
+ "Scaron": {Name: "Scaron", CodePoints: []int{352}, Characters: []byte{0xc5, 0xa0}},
+ "Scedil": {Name: "Scedil", CodePoints: []int{350}, Characters: []byte{0xc5, 0x9e}},
+ "Scirc": {Name: "Scirc", CodePoints: []int{348}, Characters: []byte{0xc5, 0x9c}},
+ "Scy": {Name: "Scy", CodePoints: []int{1057}, Characters: []byte{0xd0, 0xa1}},
+ "Sfr": {Name: "Sfr", CodePoints: []int{120086}, Characters: []byte{0xf0, 0x9d, 0x94, 0x96}},
+ "ShortDownArrow": {Name: "ShortDownArrow", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
+ "ShortLeftArrow": {Name: "ShortLeftArrow", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
+ "ShortRightArrow": {Name: "ShortRightArrow", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
+ "ShortUpArrow": {Name: "ShortUpArrow", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
+ "Sigma": {Name: "Sigma", CodePoints: []int{931}, Characters: []byte{0xce, 0xa3}},
+ "SmallCircle": {Name: "SmallCircle", CodePoints: []int{8728}, Characters: []byte{0xe2, 0x88, 0x98}},
+ "Sopf": {Name: "Sopf", CodePoints: []int{120138}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8a}},
+ "Sqrt": {Name: "Sqrt", CodePoints: []int{8730}, Characters: []byte{0xe2, 0x88, 0x9a}},
+ "Square": {Name: "Square", CodePoints: []int{9633}, Characters: []byte{0xe2, 0x96, 0xa1}},
+ "SquareIntersection": {Name: "SquareIntersection", CodePoints: []int{8851}, Characters: []byte{0xe2, 0x8a, 0x93}},
+ "SquareSubset": {Name: "SquareSubset", CodePoints: []int{8847}, Characters: []byte{0xe2, 0x8a, 0x8f}},
+ "SquareSubsetEqual": {Name: "SquareSubsetEqual", CodePoints: []int{8849}, Characters: []byte{0xe2, 0x8a, 0x91}},
+ "SquareSuperset": {Name: "SquareSuperset", CodePoints: []int{8848}, Characters: []byte{0xe2, 0x8a, 0x90}},
+ "SquareSupersetEqual": {Name: "SquareSupersetEqual", CodePoints: []int{8850}, Characters: []byte{0xe2, 0x8a, 0x92}},
+ "SquareUnion": {Name: "SquareUnion", CodePoints: []int{8852}, Characters: []byte{0xe2, 0x8a, 0x94}},
+ "Sscr": {Name: "Sscr", CodePoints: []int{119982}, Characters: []byte{0xf0, 0x9d, 0x92, 0xae}},
+ "Star": {Name: "Star", CodePoints: []int{8902}, Characters: []byte{0xe2, 0x8b, 0x86}},
+ "Sub": {Name: "Sub", CodePoints: []int{8912}, Characters: []byte{0xe2, 0x8b, 0x90}},
+ "Subset": {Name: "Subset", CodePoints: []int{8912}, Characters: []byte{0xe2, 0x8b, 0x90}},
+ "SubsetEqual": {Name: "SubsetEqual", CodePoints: []int{8838}, Characters: []byte{0xe2, 0x8a, 0x86}},
+ "Succeeds": {Name: "Succeeds", CodePoints: []int{8827}, Characters: []byte{0xe2, 0x89, 0xbb}},
+ "SucceedsEqual": {Name: "SucceedsEqual", CodePoints: []int{10928}, Characters: []byte{0xe2, 0xaa, 0xb0}},
+ "SucceedsSlantEqual": {Name: "SucceedsSlantEqual", CodePoints: []int{8829}, Characters: []byte{0xe2, 0x89, 0xbd}},
+ "SucceedsTilde": {Name: "SucceedsTilde", CodePoints: []int{8831}, Characters: []byte{0xe2, 0x89, 0xbf}},
+ "SuchThat": {Name: "SuchThat", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
+ "Sum": {Name: "Sum", CodePoints: []int{8721}, Characters: []byte{0xe2, 0x88, 0x91}},
+ "Sup": {Name: "Sup", CodePoints: []int{8913}, Characters: []byte{0xe2, 0x8b, 0x91}},
+ "Superset": {Name: "Superset", CodePoints: []int{8835}, Characters: []byte{0xe2, 0x8a, 0x83}},
+ "SupersetEqual": {Name: "SupersetEqual", CodePoints: []int{8839}, Characters: []byte{0xe2, 0x8a, 0x87}},
+ "Supset": {Name: "Supset", CodePoints: []int{8913}, Characters: []byte{0xe2, 0x8b, 0x91}},
+ "THORN": {Name: "THORN", CodePoints: []int{222}, Characters: []byte{0xc3, 0x9e}},
+ "TRADE": {Name: "TRADE", CodePoints: []int{8482}, Characters: []byte{0xe2, 0x84, 0xa2}},
+ "TSHcy": {Name: "TSHcy", CodePoints: []int{1035}, Characters: []byte{0xd0, 0x8b}},
+ "TScy": {Name: "TScy", CodePoints: []int{1062}, Characters: []byte{0xd0, 0xa6}},
+ "Tab": {Name: "Tab", CodePoints: []int{9}, Characters: []byte{0x9}},
+ "Tau": {Name: "Tau", CodePoints: []int{932}, Characters: []byte{0xce, 0xa4}},
+ "Tcaron": {Name: "Tcaron", CodePoints: []int{356}, Characters: []byte{0xc5, 0xa4}},
+ "Tcedil": {Name: "Tcedil", CodePoints: []int{354}, Characters: []byte{0xc5, 0xa2}},
+ "Tcy": {Name: "Tcy", CodePoints: []int{1058}, Characters: []byte{0xd0, 0xa2}},
+ "Tfr": {Name: "Tfr", CodePoints: []int{120087}, Characters: []byte{0xf0, 0x9d, 0x94, 0x97}},
+ "Therefore": {Name: "Therefore", CodePoints: []int{8756}, Characters: []byte{0xe2, 0x88, 0xb4}},
+ "Theta": {Name: "Theta", CodePoints: []int{920}, Characters: []byte{0xce, 0x98}},
+ "ThickSpace": {Name: "ThickSpace", CodePoints: []int{8287, 8202}, Characters: []byte{0xe2, 0x81, 0x9f, 0xe2, 0x80, 0x8a}},
+ "ThinSpace": {Name: "ThinSpace", CodePoints: []int{8201}, Characters: []byte{0xe2, 0x80, 0x89}},
+ "Tilde": {Name: "Tilde", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
+ "TildeEqual": {Name: "TildeEqual", CodePoints: []int{8771}, Characters: []byte{0xe2, 0x89, 0x83}},
+ "TildeFullEqual": {Name: "TildeFullEqual", CodePoints: []int{8773}, Characters: []byte{0xe2, 0x89, 0x85}},
+ "TildeTilde": {Name: "TildeTilde", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
+ "Topf": {Name: "Topf", CodePoints: []int{120139}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8b}},
+ "TripleDot": {Name: "TripleDot", CodePoints: []int{8411}, Characters: []byte{0xe2, 0x83, 0x9b}},
+ "Tscr": {Name: "Tscr", CodePoints: []int{119983}, Characters: []byte{0xf0, 0x9d, 0x92, 0xaf}},
+ "Tstrok": {Name: "Tstrok", CodePoints: []int{358}, Characters: []byte{0xc5, 0xa6}},
+ "Uacute": {Name: "Uacute", CodePoints: []int{218}, Characters: []byte{0xc3, 0x9a}},
+ "Uarr": {Name: "Uarr", CodePoints: []int{8607}, Characters: []byte{0xe2, 0x86, 0x9f}},
+ "Uarrocir": {Name: "Uarrocir", CodePoints: []int{10569}, Characters: []byte{0xe2, 0xa5, 0x89}},
+ "Ubrcy": {Name: "Ubrcy", CodePoints: []int{1038}, Characters: []byte{0xd0, 0x8e}},
+ "Ubreve": {Name: "Ubreve", CodePoints: []int{364}, Characters: []byte{0xc5, 0xac}},
+ "Ucirc": {Name: "Ucirc", CodePoints: []int{219}, Characters: []byte{0xc3, 0x9b}},
+ "Ucy": {Name: "Ucy", CodePoints: []int{1059}, Characters: []byte{0xd0, 0xa3}},
+ "Udblac": {Name: "Udblac", CodePoints: []int{368}, Characters: []byte{0xc5, 0xb0}},
+ "Ufr": {Name: "Ufr", CodePoints: []int{120088}, Characters: []byte{0xf0, 0x9d, 0x94, 0x98}},
+ "Ugrave": {Name: "Ugrave", CodePoints: []int{217}, Characters: []byte{0xc3, 0x99}},
+ "Umacr": {Name: "Umacr", CodePoints: []int{362}, Characters: []byte{0xc5, 0xaa}},
+ "UnderBar": {Name: "UnderBar", CodePoints: []int{95}, Characters: []byte{0x5f}},
+ "UnderBrace": {Name: "UnderBrace", CodePoints: []int{9183}, Characters: []byte{0xe2, 0x8f, 0x9f}},
+ "UnderBracket": {Name: "UnderBracket", CodePoints: []int{9141}, Characters: []byte{0xe2, 0x8e, 0xb5}},
+ "UnderParenthesis": {Name: "UnderParenthesis", CodePoints: []int{9181}, Characters: []byte{0xe2, 0x8f, 0x9d}},
+ "Union": {Name: "Union", CodePoints: []int{8899}, Characters: []byte{0xe2, 0x8b, 0x83}},
+ "UnionPlus": {Name: "UnionPlus", CodePoints: []int{8846}, Characters: []byte{0xe2, 0x8a, 0x8e}},
+ "Uogon": {Name: "Uogon", CodePoints: []int{370}, Characters: []byte{0xc5, 0xb2}},
+ "Uopf": {Name: "Uopf", CodePoints: []int{120140}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8c}},
+ "UpArrow": {Name: "UpArrow", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
+ "UpArrowBar": {Name: "UpArrowBar", CodePoints: []int{10514}, Characters: []byte{0xe2, 0xa4, 0x92}},
+ "UpArrowDownArrow": {Name: "UpArrowDownArrow", CodePoints: []int{8645}, Characters: []byte{0xe2, 0x87, 0x85}},
+ "UpDownArrow": {Name: "UpDownArrow", CodePoints: []int{8597}, Characters: []byte{0xe2, 0x86, 0x95}},
+ "UpEquilibrium": {Name: "UpEquilibrium", CodePoints: []int{10606}, Characters: []byte{0xe2, 0xa5, 0xae}},
+ "UpTee": {Name: "UpTee", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
+ "UpTeeArrow": {Name: "UpTeeArrow", CodePoints: []int{8613}, Characters: []byte{0xe2, 0x86, 0xa5}},
+ "Uparrow": {Name: "Uparrow", CodePoints: []int{8657}, Characters: []byte{0xe2, 0x87, 0x91}},
+ "Updownarrow": {Name: "Updownarrow", CodePoints: []int{8661}, Characters: []byte{0xe2, 0x87, 0x95}},
+ "UpperLeftArrow": {Name: "UpperLeftArrow", CodePoints: []int{8598}, Characters: []byte{0xe2, 0x86, 0x96}},
+ "UpperRightArrow": {Name: "UpperRightArrow", CodePoints: []int{8599}, Characters: []byte{0xe2, 0x86, 0x97}},
+ "Upsi": {Name: "Upsi", CodePoints: []int{978}, Characters: []byte{0xcf, 0x92}},
+ "Upsilon": {Name: "Upsilon", CodePoints: []int{933}, Characters: []byte{0xce, 0xa5}},
+ "Uring": {Name: "Uring", CodePoints: []int{366}, Characters: []byte{0xc5, 0xae}},
+ "Uscr": {Name: "Uscr", CodePoints: []int{119984}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb0}},
+ "Utilde": {Name: "Utilde", CodePoints: []int{360}, Characters: []byte{0xc5, 0xa8}},
+ "Uuml": {Name: "Uuml", CodePoints: []int{220}, Characters: []byte{0xc3, 0x9c}},
+ "VDash": {Name: "VDash", CodePoints: []int{8875}, Characters: []byte{0xe2, 0x8a, 0xab}},
+ "Vbar": {Name: "Vbar", CodePoints: []int{10987}, Characters: []byte{0xe2, 0xab, 0xab}},
+ "Vcy": {Name: "Vcy", CodePoints: []int{1042}, Characters: []byte{0xd0, 0x92}},
+ "Vdash": {Name: "Vdash", CodePoints: []int{8873}, Characters: []byte{0xe2, 0x8a, 0xa9}},
+ "Vdashl": {Name: "Vdashl", CodePoints: []int{10982}, Characters: []byte{0xe2, 0xab, 0xa6}},
+ "Vee": {Name: "Vee", CodePoints: []int{8897}, Characters: []byte{0xe2, 0x8b, 0x81}},
+ "Verbar": {Name: "Verbar", CodePoints: []int{8214}, Characters: []byte{0xe2, 0x80, 0x96}},
+ "Vert": {Name: "Vert", CodePoints: []int{8214}, Characters: []byte{0xe2, 0x80, 0x96}},
+ "VerticalBar": {Name: "VerticalBar", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
+ "VerticalLine": {Name: "VerticalLine", CodePoints: []int{124}, Characters: []byte{0x7c}},
+ "VerticalSeparator": {Name: "VerticalSeparator", CodePoints: []int{10072}, Characters: []byte{0xe2, 0x9d, 0x98}},
+ "VerticalTilde": {Name: "VerticalTilde", CodePoints: []int{8768}, Characters: []byte{0xe2, 0x89, 0x80}},
+ "VeryThinSpace": {Name: "VeryThinSpace", CodePoints: []int{8202}, Characters: []byte{0xe2, 0x80, 0x8a}},
+ "Vfr": {Name: "Vfr", CodePoints: []int{120089}, Characters: []byte{0xf0, 0x9d, 0x94, 0x99}},
+ "Vopf": {Name: "Vopf", CodePoints: []int{120141}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8d}},
+ "Vscr": {Name: "Vscr", CodePoints: []int{119985}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb1}},
+ "Vvdash": {Name: "Vvdash", CodePoints: []int{8874}, Characters: []byte{0xe2, 0x8a, 0xaa}},
+ "Wcirc": {Name: "Wcirc", CodePoints: []int{372}, Characters: []byte{0xc5, 0xb4}},
+ "Wedge": {Name: "Wedge", CodePoints: []int{8896}, Characters: []byte{0xe2, 0x8b, 0x80}},
+ "Wfr": {Name: "Wfr", CodePoints: []int{120090}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9a}},
+ "Wopf": {Name: "Wopf", CodePoints: []int{120142}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8e}},
+ "Wscr": {Name: "Wscr", CodePoints: []int{119986}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb2}},
+ "Xfr": {Name: "Xfr", CodePoints: []int{120091}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9b}},
+ "Xi": {Name: "Xi", CodePoints: []int{926}, Characters: []byte{0xce, 0x9e}},
+ "Xopf": {Name: "Xopf", CodePoints: []int{120143}, Characters: []byte{0xf0, 0x9d, 0x95, 0x8f}},
+ "Xscr": {Name: "Xscr", CodePoints: []int{119987}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb3}},
+ "YAcy": {Name: "YAcy", CodePoints: []int{1071}, Characters: []byte{0xd0, 0xaf}},
+ "YIcy": {Name: "YIcy", CodePoints: []int{1031}, Characters: []byte{0xd0, 0x87}},
+ "YUcy": {Name: "YUcy", CodePoints: []int{1070}, Characters: []byte{0xd0, 0xae}},
+ "Yacute": {Name: "Yacute", CodePoints: []int{221}, Characters: []byte{0xc3, 0x9d}},
+ "Ycirc": {Name: "Ycirc", CodePoints: []int{374}, Characters: []byte{0xc5, 0xb6}},
+ "Ycy": {Name: "Ycy", CodePoints: []int{1067}, Characters: []byte{0xd0, 0xab}},
+ "Yfr": {Name: "Yfr", CodePoints: []int{120092}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9c}},
+ "Yopf": {Name: "Yopf", CodePoints: []int{120144}, Characters: []byte{0xf0, 0x9d, 0x95, 0x90}},
+ "Yscr": {Name: "Yscr", CodePoints: []int{119988}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb4}},
+ "Yuml": {Name: "Yuml", CodePoints: []int{376}, Characters: []byte{0xc5, 0xb8}},
+ "ZHcy": {Name: "ZHcy", CodePoints: []int{1046}, Characters: []byte{0xd0, 0x96}},
+ "Zacute": {Name: "Zacute", CodePoints: []int{377}, Characters: []byte{0xc5, 0xb9}},
+ "Zcaron": {Name: "Zcaron", CodePoints: []int{381}, Characters: []byte{0xc5, 0xbd}},
+ "Zcy": {Name: "Zcy", CodePoints: []int{1047}, Characters: []byte{0xd0, 0x97}},
+ "Zdot": {Name: "Zdot", CodePoints: []int{379}, Characters: []byte{0xc5, 0xbb}},
+ "ZeroWidthSpace": {Name: "ZeroWidthSpace", CodePoints: []int{8203}, Characters: []byte{0xe2, 0x80, 0x8b}},
+ "Zeta": {Name: "Zeta", CodePoints: []int{918}, Characters: []byte{0xce, 0x96}},
+ "Zfr": {Name: "Zfr", CodePoints: []int{8488}, Characters: []byte{0xe2, 0x84, 0xa8}},
+ "Zopf": {Name: "Zopf", CodePoints: []int{8484}, Characters: []byte{0xe2, 0x84, 0xa4}},
+ "Zscr": {Name: "Zscr", CodePoints: []int{119989}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb5}},
+ "aacute": {Name: "aacute", CodePoints: []int{225}, Characters: []byte{0xc3, 0xa1}},
+ "abreve": {Name: "abreve", CodePoints: []int{259}, Characters: []byte{0xc4, 0x83}},
+ "ac": {Name: "ac", CodePoints: []int{8766}, Characters: []byte{0xe2, 0x88, 0xbe}},
+ "acE": {Name: "acE", CodePoints: []int{8766, 819}, Characters: []byte{0xe2, 0x88, 0xbe, 0xcc, 0xb3}},
+ "acd": {Name: "acd", CodePoints: []int{8767}, Characters: []byte{0xe2, 0x88, 0xbf}},
+ "acirc": {Name: "acirc", CodePoints: []int{226}, Characters: []byte{0xc3, 0xa2}},
+ "acute": {Name: "acute", CodePoints: []int{180}, Characters: []byte{0xc2, 0xb4}},
+ "acy": {Name: "acy", CodePoints: []int{1072}, Characters: []byte{0xd0, 0xb0}},
+ "aelig": {Name: "aelig", CodePoints: []int{230}, Characters: []byte{0xc3, 0xa6}},
+ "af": {Name: "af", CodePoints: []int{8289}, Characters: []byte{0xe2, 0x81, 0xa1}},
+ "afr": {Name: "afr", CodePoints: []int{120094}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9e}},
+ "agrave": {Name: "agrave", CodePoints: []int{224}, Characters: []byte{0xc3, 0xa0}},
+ "alefsym": {Name: "alefsym", CodePoints: []int{8501}, Characters: []byte{0xe2, 0x84, 0xb5}},
+ "aleph": {Name: "aleph", CodePoints: []int{8501}, Characters: []byte{0xe2, 0x84, 0xb5}},
+ "alpha": {Name: "alpha", CodePoints: []int{945}, Characters: []byte{0xce, 0xb1}},
+ "amacr": {Name: "amacr", CodePoints: []int{257}, Characters: []byte{0xc4, 0x81}},
+ "amalg": {Name: "amalg", CodePoints: []int{10815}, Characters: []byte{0xe2, 0xa8, 0xbf}},
+ "amp": {Name: "amp", CodePoints: []int{38}, Characters: []byte{0x26}},
+ "and": {Name: "and", CodePoints: []int{8743}, Characters: []byte{0xe2, 0x88, 0xa7}},
+ "andand": {Name: "andand", CodePoints: []int{10837}, Characters: []byte{0xe2, 0xa9, 0x95}},
+ "andd": {Name: "andd", CodePoints: []int{10844}, Characters: []byte{0xe2, 0xa9, 0x9c}},
+ "andslope": {Name: "andslope", CodePoints: []int{10840}, Characters: []byte{0xe2, 0xa9, 0x98}},
+ "andv": {Name: "andv", CodePoints: []int{10842}, Characters: []byte{0xe2, 0xa9, 0x9a}},
+ "ang": {Name: "ang", CodePoints: []int{8736}, Characters: []byte{0xe2, 0x88, 0xa0}},
+ "ange": {Name: "ange", CodePoints: []int{10660}, Characters: []byte{0xe2, 0xa6, 0xa4}},
+ "angle": {Name: "angle", CodePoints: []int{8736}, Characters: []byte{0xe2, 0x88, 0xa0}},
+ "angmsd": {Name: "angmsd", CodePoints: []int{8737}, Characters: []byte{0xe2, 0x88, 0xa1}},
+ "angmsdaa": {Name: "angmsdaa", CodePoints: []int{10664}, Characters: []byte{0xe2, 0xa6, 0xa8}},
+ "angmsdab": {Name: "angmsdab", CodePoints: []int{10665}, Characters: []byte{0xe2, 0xa6, 0xa9}},
+ "angmsdac": {Name: "angmsdac", CodePoints: []int{10666}, Characters: []byte{0xe2, 0xa6, 0xaa}},
+ "angmsdad": {Name: "angmsdad", CodePoints: []int{10667}, Characters: []byte{0xe2, 0xa6, 0xab}},
+ "angmsdae": {Name: "angmsdae", CodePoints: []int{10668}, Characters: []byte{0xe2, 0xa6, 0xac}},
+ "angmsdaf": {Name: "angmsdaf", CodePoints: []int{10669}, Characters: []byte{0xe2, 0xa6, 0xad}},
+ "angmsdag": {Name: "angmsdag", CodePoints: []int{10670}, Characters: []byte{0xe2, 0xa6, 0xae}},
+ "angmsdah": {Name: "angmsdah", CodePoints: []int{10671}, Characters: []byte{0xe2, 0xa6, 0xaf}},
+ "angrt": {Name: "angrt", CodePoints: []int{8735}, Characters: []byte{0xe2, 0x88, 0x9f}},
+ "angrtvb": {Name: "angrtvb", CodePoints: []int{8894}, Characters: []byte{0xe2, 0x8a, 0xbe}},
+ "angrtvbd": {Name: "angrtvbd", CodePoints: []int{10653}, Characters: []byte{0xe2, 0xa6, 0x9d}},
+ "angsph": {Name: "angsph", CodePoints: []int{8738}, Characters: []byte{0xe2, 0x88, 0xa2}},
+ "angst": {Name: "angst", CodePoints: []int{197}, Characters: []byte{0xc3, 0x85}},
+ "angzarr": {Name: "angzarr", CodePoints: []int{9084}, Characters: []byte{0xe2, 0x8d, 0xbc}},
+ "aogon": {Name: "aogon", CodePoints: []int{261}, Characters: []byte{0xc4, 0x85}},
+ "aopf": {Name: "aopf", CodePoints: []int{120146}, Characters: []byte{0xf0, 0x9d, 0x95, 0x92}},
+ "ap": {Name: "ap", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
+ "apE": {Name: "apE", CodePoints: []int{10864}, Characters: []byte{0xe2, 0xa9, 0xb0}},
+ "apacir": {Name: "apacir", CodePoints: []int{10863}, Characters: []byte{0xe2, 0xa9, 0xaf}},
+ "ape": {Name: "ape", CodePoints: []int{8778}, Characters: []byte{0xe2, 0x89, 0x8a}},
+ "apid": {Name: "apid", CodePoints: []int{8779}, Characters: []byte{0xe2, 0x89, 0x8b}},
+ "apos": {Name: "apos", CodePoints: []int{39}, Characters: []byte{0x27}},
+ "approx": {Name: "approx", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
+ "approxeq": {Name: "approxeq", CodePoints: []int{8778}, Characters: []byte{0xe2, 0x89, 0x8a}},
+ "aring": {Name: "aring", CodePoints: []int{229}, Characters: []byte{0xc3, 0xa5}},
+ "ascr": {Name: "ascr", CodePoints: []int{119990}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb6}},
+ "ast": {Name: "ast", CodePoints: []int{42}, Characters: []byte{0x2a}},
+ "asymp": {Name: "asymp", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
+ "asympeq": {Name: "asympeq", CodePoints: []int{8781}, Characters: []byte{0xe2, 0x89, 0x8d}},
+ "atilde": {Name: "atilde", CodePoints: []int{227}, Characters: []byte{0xc3, 0xa3}},
+ "auml": {Name: "auml", CodePoints: []int{228}, Characters: []byte{0xc3, 0xa4}},
+ "awconint": {Name: "awconint", CodePoints: []int{8755}, Characters: []byte{0xe2, 0x88, 0xb3}},
+ "awint": {Name: "awint", CodePoints: []int{10769}, Characters: []byte{0xe2, 0xa8, 0x91}},
+ "bNot": {Name: "bNot", CodePoints: []int{10989}, Characters: []byte{0xe2, 0xab, 0xad}},
+ "backcong": {Name: "backcong", CodePoints: []int{8780}, Characters: []byte{0xe2, 0x89, 0x8c}},
+ "backepsilon": {Name: "backepsilon", CodePoints: []int{1014}, Characters: []byte{0xcf, 0xb6}},
+ "backprime": {Name: "backprime", CodePoints: []int{8245}, Characters: []byte{0xe2, 0x80, 0xb5}},
+ "backsim": {Name: "backsim", CodePoints: []int{8765}, Characters: []byte{0xe2, 0x88, 0xbd}},
+ "backsimeq": {Name: "backsimeq", CodePoints: []int{8909}, Characters: []byte{0xe2, 0x8b, 0x8d}},
+ "barvee": {Name: "barvee", CodePoints: []int{8893}, Characters: []byte{0xe2, 0x8a, 0xbd}},
+ "barwed": {Name: "barwed", CodePoints: []int{8965}, Characters: []byte{0xe2, 0x8c, 0x85}},
+ "barwedge": {Name: "barwedge", CodePoints: []int{8965}, Characters: []byte{0xe2, 0x8c, 0x85}},
+ "bbrk": {Name: "bbrk", CodePoints: []int{9141}, Characters: []byte{0xe2, 0x8e, 0xb5}},
+ "bbrktbrk": {Name: "bbrktbrk", CodePoints: []int{9142}, Characters: []byte{0xe2, 0x8e, 0xb6}},
+ "bcong": {Name: "bcong", CodePoints: []int{8780}, Characters: []byte{0xe2, 0x89, 0x8c}},
+ "bcy": {Name: "bcy", CodePoints: []int{1073}, Characters: []byte{0xd0, 0xb1}},
+ "bdquo": {Name: "bdquo", CodePoints: []int{8222}, Characters: []byte{0xe2, 0x80, 0x9e}},
+ "becaus": {Name: "becaus", CodePoints: []int{8757}, Characters: []byte{0xe2, 0x88, 0xb5}},
+ "because": {Name: "because", CodePoints: []int{8757}, Characters: []byte{0xe2, 0x88, 0xb5}},
+ "bemptyv": {Name: "bemptyv", CodePoints: []int{10672}, Characters: []byte{0xe2, 0xa6, 0xb0}},
+ "bepsi": {Name: "bepsi", CodePoints: []int{1014}, Characters: []byte{0xcf, 0xb6}},
+ "bernou": {Name: "bernou", CodePoints: []int{8492}, Characters: []byte{0xe2, 0x84, 0xac}},
+ "beta": {Name: "beta", CodePoints: []int{946}, Characters: []byte{0xce, 0xb2}},
+ "beth": {Name: "beth", CodePoints: []int{8502}, Characters: []byte{0xe2, 0x84, 0xb6}},
+ "between": {Name: "between", CodePoints: []int{8812}, Characters: []byte{0xe2, 0x89, 0xac}},
+ "bfr": {Name: "bfr", CodePoints: []int{120095}, Characters: []byte{0xf0, 0x9d, 0x94, 0x9f}},
+ "bigcap": {Name: "bigcap", CodePoints: []int{8898}, Characters: []byte{0xe2, 0x8b, 0x82}},
+ "bigcirc": {Name: "bigcirc", CodePoints: []int{9711}, Characters: []byte{0xe2, 0x97, 0xaf}},
+ "bigcup": {Name: "bigcup", CodePoints: []int{8899}, Characters: []byte{0xe2, 0x8b, 0x83}},
+ "bigodot": {Name: "bigodot", CodePoints: []int{10752}, Characters: []byte{0xe2, 0xa8, 0x80}},
+ "bigoplus": {Name: "bigoplus", CodePoints: []int{10753}, Characters: []byte{0xe2, 0xa8, 0x81}},
+ "bigotimes": {Name: "bigotimes", CodePoints: []int{10754}, Characters: []byte{0xe2, 0xa8, 0x82}},
+ "bigsqcup": {Name: "bigsqcup", CodePoints: []int{10758}, Characters: []byte{0xe2, 0xa8, 0x86}},
+ "bigstar": {Name: "bigstar", CodePoints: []int{9733}, Characters: []byte{0xe2, 0x98, 0x85}},
+ "bigtriangledown": {Name: "bigtriangledown", CodePoints: []int{9661}, Characters: []byte{0xe2, 0x96, 0xbd}},
+ "bigtriangleup": {Name: "bigtriangleup", CodePoints: []int{9651}, Characters: []byte{0xe2, 0x96, 0xb3}},
+ "biguplus": {Name: "biguplus", CodePoints: []int{10756}, Characters: []byte{0xe2, 0xa8, 0x84}},
+ "bigvee": {Name: "bigvee", CodePoints: []int{8897}, Characters: []byte{0xe2, 0x8b, 0x81}},
+ "bigwedge": {Name: "bigwedge", CodePoints: []int{8896}, Characters: []byte{0xe2, 0x8b, 0x80}},
+ "bkarow": {Name: "bkarow", CodePoints: []int{10509}, Characters: []byte{0xe2, 0xa4, 0x8d}},
+ "blacklozenge": {Name: "blacklozenge", CodePoints: []int{10731}, Characters: []byte{0xe2, 0xa7, 0xab}},
+ "blacksquare": {Name: "blacksquare", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
+ "blacktriangle": {Name: "blacktriangle", CodePoints: []int{9652}, Characters: []byte{0xe2, 0x96, 0xb4}},
+ "blacktriangledown": {Name: "blacktriangledown", CodePoints: []int{9662}, Characters: []byte{0xe2, 0x96, 0xbe}},
+ "blacktriangleleft": {Name: "blacktriangleleft", CodePoints: []int{9666}, Characters: []byte{0xe2, 0x97, 0x82}},
+ "blacktriangleright": {Name: "blacktriangleright", CodePoints: []int{9656}, Characters: []byte{0xe2, 0x96, 0xb8}},
+ "blank": {Name: "blank", CodePoints: []int{9251}, Characters: []byte{0xe2, 0x90, 0xa3}},
+ "blk12": {Name: "blk12", CodePoints: []int{9618}, Characters: []byte{0xe2, 0x96, 0x92}},
+ "blk14": {Name: "blk14", CodePoints: []int{9617}, Characters: []byte{0xe2, 0x96, 0x91}},
+ "blk34": {Name: "blk34", CodePoints: []int{9619}, Characters: []byte{0xe2, 0x96, 0x93}},
+ "block": {Name: "block", CodePoints: []int{9608}, Characters: []byte{0xe2, 0x96, 0x88}},
+ "bne": {Name: "bne", CodePoints: []int{61, 8421}, Characters: []byte{0x3d, 0xe2, 0x83, 0xa5}},
+ "bnequiv": {Name: "bnequiv", CodePoints: []int{8801, 8421}, Characters: []byte{0xe2, 0x89, 0xa1, 0xe2, 0x83, 0xa5}},
+ "bnot": {Name: "bnot", CodePoints: []int{8976}, Characters: []byte{0xe2, 0x8c, 0x90}},
+ "bopf": {Name: "bopf", CodePoints: []int{120147}, Characters: []byte{0xf0, 0x9d, 0x95, 0x93}},
+ "bot": {Name: "bot", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
+ "bottom": {Name: "bottom", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
+ "bowtie": {Name: "bowtie", CodePoints: []int{8904}, Characters: []byte{0xe2, 0x8b, 0x88}},
+ "boxDL": {Name: "boxDL", CodePoints: []int{9559}, Characters: []byte{0xe2, 0x95, 0x97}},
+ "boxDR": {Name: "boxDR", CodePoints: []int{9556}, Characters: []byte{0xe2, 0x95, 0x94}},
+ "boxDl": {Name: "boxDl", CodePoints: []int{9558}, Characters: []byte{0xe2, 0x95, 0x96}},
+ "boxDr": {Name: "boxDr", CodePoints: []int{9555}, Characters: []byte{0xe2, 0x95, 0x93}},
+ "boxH": {Name: "boxH", CodePoints: []int{9552}, Characters: []byte{0xe2, 0x95, 0x90}},
+ "boxHD": {Name: "boxHD", CodePoints: []int{9574}, Characters: []byte{0xe2, 0x95, 0xa6}},
+ "boxHU": {Name: "boxHU", CodePoints: []int{9577}, Characters: []byte{0xe2, 0x95, 0xa9}},
+ "boxHd": {Name: "boxHd", CodePoints: []int{9572}, Characters: []byte{0xe2, 0x95, 0xa4}},
+ "boxHu": {Name: "boxHu", CodePoints: []int{9575}, Characters: []byte{0xe2, 0x95, 0xa7}},
+ "boxUL": {Name: "boxUL", CodePoints: []int{9565}, Characters: []byte{0xe2, 0x95, 0x9d}},
+ "boxUR": {Name: "boxUR", CodePoints: []int{9562}, Characters: []byte{0xe2, 0x95, 0x9a}},
+ "boxUl": {Name: "boxUl", CodePoints: []int{9564}, Characters: []byte{0xe2, 0x95, 0x9c}},
+ "boxUr": {Name: "boxUr", CodePoints: []int{9561}, Characters: []byte{0xe2, 0x95, 0x99}},
+ "boxV": {Name: "boxV", CodePoints: []int{9553}, Characters: []byte{0xe2, 0x95, 0x91}},
+ "boxVH": {Name: "boxVH", CodePoints: []int{9580}, Characters: []byte{0xe2, 0x95, 0xac}},
+ "boxVL": {Name: "boxVL", CodePoints: []int{9571}, Characters: []byte{0xe2, 0x95, 0xa3}},
+ "boxVR": {Name: "boxVR", CodePoints: []int{9568}, Characters: []byte{0xe2, 0x95, 0xa0}},
+ "boxVh": {Name: "boxVh", CodePoints: []int{9579}, Characters: []byte{0xe2, 0x95, 0xab}},
+ "boxVl": {Name: "boxVl", CodePoints: []int{9570}, Characters: []byte{0xe2, 0x95, 0xa2}},
+ "boxVr": {Name: "boxVr", CodePoints: []int{9567}, Characters: []byte{0xe2, 0x95, 0x9f}},
+ "boxbox": {Name: "boxbox", CodePoints: []int{10697}, Characters: []byte{0xe2, 0xa7, 0x89}},
+ "boxdL": {Name: "boxdL", CodePoints: []int{9557}, Characters: []byte{0xe2, 0x95, 0x95}},
+ "boxdR": {Name: "boxdR", CodePoints: []int{9554}, Characters: []byte{0xe2, 0x95, 0x92}},
+ "boxdl": {Name: "boxdl", CodePoints: []int{9488}, Characters: []byte{0xe2, 0x94, 0x90}},
+ "boxdr": {Name: "boxdr", CodePoints: []int{9484}, Characters: []byte{0xe2, 0x94, 0x8c}},
+ "boxh": {Name: "boxh", CodePoints: []int{9472}, Characters: []byte{0xe2, 0x94, 0x80}},
+ "boxhD": {Name: "boxhD", CodePoints: []int{9573}, Characters: []byte{0xe2, 0x95, 0xa5}},
+ "boxhU": {Name: "boxhU", CodePoints: []int{9576}, Characters: []byte{0xe2, 0x95, 0xa8}},
+ "boxhd": {Name: "boxhd", CodePoints: []int{9516}, Characters: []byte{0xe2, 0x94, 0xac}},
+ "boxhu": {Name: "boxhu", CodePoints: []int{9524}, Characters: []byte{0xe2, 0x94, 0xb4}},
+ "boxminus": {Name: "boxminus", CodePoints: []int{8863}, Characters: []byte{0xe2, 0x8a, 0x9f}},
+ "boxplus": {Name: "boxplus", CodePoints: []int{8862}, Characters: []byte{0xe2, 0x8a, 0x9e}},
+ "boxtimes": {Name: "boxtimes", CodePoints: []int{8864}, Characters: []byte{0xe2, 0x8a, 0xa0}},
+ "boxuL": {Name: "boxuL", CodePoints: []int{9563}, Characters: []byte{0xe2, 0x95, 0x9b}},
+ "boxuR": {Name: "boxuR", CodePoints: []int{9560}, Characters: []byte{0xe2, 0x95, 0x98}},
+ "boxul": {Name: "boxul", CodePoints: []int{9496}, Characters: []byte{0xe2, 0x94, 0x98}},
+ "boxur": {Name: "boxur", CodePoints: []int{9492}, Characters: []byte{0xe2, 0x94, 0x94}},
+ "boxv": {Name: "boxv", CodePoints: []int{9474}, Characters: []byte{0xe2, 0x94, 0x82}},
+ "boxvH": {Name: "boxvH", CodePoints: []int{9578}, Characters: []byte{0xe2, 0x95, 0xaa}},
+ "boxvL": {Name: "boxvL", CodePoints: []int{9569}, Characters: []byte{0xe2, 0x95, 0xa1}},
+ "boxvR": {Name: "boxvR", CodePoints: []int{9566}, Characters: []byte{0xe2, 0x95, 0x9e}},
+ "boxvh": {Name: "boxvh", CodePoints: []int{9532}, Characters: []byte{0xe2, 0x94, 0xbc}},
+ "boxvl": {Name: "boxvl", CodePoints: []int{9508}, Characters: []byte{0xe2, 0x94, 0xa4}},
+ "boxvr": {Name: "boxvr", CodePoints: []int{9500}, Characters: []byte{0xe2, 0x94, 0x9c}},
+ "bprime": {Name: "bprime", CodePoints: []int{8245}, Characters: []byte{0xe2, 0x80, 0xb5}},
+ "breve": {Name: "breve", CodePoints: []int{728}, Characters: []byte{0xcb, 0x98}},
+ "brvbar": {Name: "brvbar", CodePoints: []int{166}, Characters: []byte{0xc2, 0xa6}},
+ "bscr": {Name: "bscr", CodePoints: []int{119991}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb7}},
+ "bsemi": {Name: "bsemi", CodePoints: []int{8271}, Characters: []byte{0xe2, 0x81, 0x8f}},
+ "bsim": {Name: "bsim", CodePoints: []int{8765}, Characters: []byte{0xe2, 0x88, 0xbd}},
+ "bsime": {Name: "bsime", CodePoints: []int{8909}, Characters: []byte{0xe2, 0x8b, 0x8d}},
+ "bsol": {Name: "bsol", CodePoints: []int{92}, Characters: []byte{0x5c}},
+ "bsolb": {Name: "bsolb", CodePoints: []int{10693}, Characters: []byte{0xe2, 0xa7, 0x85}},
+ "bsolhsub": {Name: "bsolhsub", CodePoints: []int{10184}, Characters: []byte{0xe2, 0x9f, 0x88}},
+ "bull": {Name: "bull", CodePoints: []int{8226}, Characters: []byte{0xe2, 0x80, 0xa2}},
+ "bullet": {Name: "bullet", CodePoints: []int{8226}, Characters: []byte{0xe2, 0x80, 0xa2}},
+ "bump": {Name: "bump", CodePoints: []int{8782}, Characters: []byte{0xe2, 0x89, 0x8e}},
+ "bumpE": {Name: "bumpE", CodePoints: []int{10926}, Characters: []byte{0xe2, 0xaa, 0xae}},
+ "bumpe": {Name: "bumpe", CodePoints: []int{8783}, Characters: []byte{0xe2, 0x89, 0x8f}},
+ "bumpeq": {Name: "bumpeq", CodePoints: []int{8783}, Characters: []byte{0xe2, 0x89, 0x8f}},
+ "cacute": {Name: "cacute", CodePoints: []int{263}, Characters: []byte{0xc4, 0x87}},
+ "cap": {Name: "cap", CodePoints: []int{8745}, Characters: []byte{0xe2, 0x88, 0xa9}},
+ "capand": {Name: "capand", CodePoints: []int{10820}, Characters: []byte{0xe2, 0xa9, 0x84}},
+ "capbrcup": {Name: "capbrcup", CodePoints: []int{10825}, Characters: []byte{0xe2, 0xa9, 0x89}},
+ "capcap": {Name: "capcap", CodePoints: []int{10827}, Characters: []byte{0xe2, 0xa9, 0x8b}},
+ "capcup": {Name: "capcup", CodePoints: []int{10823}, Characters: []byte{0xe2, 0xa9, 0x87}},
+ "capdot": {Name: "capdot", CodePoints: []int{10816}, Characters: []byte{0xe2, 0xa9, 0x80}},
+ "caps": {Name: "caps", CodePoints: []int{8745, 65024}, Characters: []byte{0xe2, 0x88, 0xa9, 0xef, 0xb8, 0x80}},
+ "caret": {Name: "caret", CodePoints: []int{8257}, Characters: []byte{0xe2, 0x81, 0x81}},
+ "caron": {Name: "caron", CodePoints: []int{711}, Characters: []byte{0xcb, 0x87}},
+ "ccaps": {Name: "ccaps", CodePoints: []int{10829}, Characters: []byte{0xe2, 0xa9, 0x8d}},
+ "ccaron": {Name: "ccaron", CodePoints: []int{269}, Characters: []byte{0xc4, 0x8d}},
+ "ccedil": {Name: "ccedil", CodePoints: []int{231}, Characters: []byte{0xc3, 0xa7}},
+ "ccirc": {Name: "ccirc", CodePoints: []int{265}, Characters: []byte{0xc4, 0x89}},
+ "ccups": {Name: "ccups", CodePoints: []int{10828}, Characters: []byte{0xe2, 0xa9, 0x8c}},
+ "ccupssm": {Name: "ccupssm", CodePoints: []int{10832}, Characters: []byte{0xe2, 0xa9, 0x90}},
+ "cdot": {Name: "cdot", CodePoints: []int{267}, Characters: []byte{0xc4, 0x8b}},
+ "cedil": {Name: "cedil", CodePoints: []int{184}, Characters: []byte{0xc2, 0xb8}},
+ "cemptyv": {Name: "cemptyv", CodePoints: []int{10674}, Characters: []byte{0xe2, 0xa6, 0xb2}},
+ "cent": {Name: "cent", CodePoints: []int{162}, Characters: []byte{0xc2, 0xa2}},
+ "centerdot": {Name: "centerdot", CodePoints: []int{183}, Characters: []byte{0xc2, 0xb7}},
+ "cfr": {Name: "cfr", CodePoints: []int{120096}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa0}},
+ "chcy": {Name: "chcy", CodePoints: []int{1095}, Characters: []byte{0xd1, 0x87}},
+ "check": {Name: "check", CodePoints: []int{10003}, Characters: []byte{0xe2, 0x9c, 0x93}},
+ "checkmark": {Name: "checkmark", CodePoints: []int{10003}, Characters: []byte{0xe2, 0x9c, 0x93}},
+ "chi": {Name: "chi", CodePoints: []int{967}, Characters: []byte{0xcf, 0x87}},
+ "cir": {Name: "cir", CodePoints: []int{9675}, Characters: []byte{0xe2, 0x97, 0x8b}},
+ "cirE": {Name: "cirE", CodePoints: []int{10691}, Characters: []byte{0xe2, 0xa7, 0x83}},
+ "circ": {Name: "circ", CodePoints: []int{710}, Characters: []byte{0xcb, 0x86}},
+ "circeq": {Name: "circeq", CodePoints: []int{8791}, Characters: []byte{0xe2, 0x89, 0x97}},
+ "circlearrowleft": {Name: "circlearrowleft", CodePoints: []int{8634}, Characters: []byte{0xe2, 0x86, 0xba}},
+ "circlearrowright": {Name: "circlearrowright", CodePoints: []int{8635}, Characters: []byte{0xe2, 0x86, 0xbb}},
+ "circledR": {Name: "circledR", CodePoints: []int{174}, Characters: []byte{0xc2, 0xae}},
+ "circledS": {Name: "circledS", CodePoints: []int{9416}, Characters: []byte{0xe2, 0x93, 0x88}},
+ "circledast": {Name: "circledast", CodePoints: []int{8859}, Characters: []byte{0xe2, 0x8a, 0x9b}},
+ "circledcirc": {Name: "circledcirc", CodePoints: []int{8858}, Characters: []byte{0xe2, 0x8a, 0x9a}},
+ "circleddash": {Name: "circleddash", CodePoints: []int{8861}, Characters: []byte{0xe2, 0x8a, 0x9d}},
+ "cire": {Name: "cire", CodePoints: []int{8791}, Characters: []byte{0xe2, 0x89, 0x97}},
+ "cirfnint": {Name: "cirfnint", CodePoints: []int{10768}, Characters: []byte{0xe2, 0xa8, 0x90}},
+ "cirmid": {Name: "cirmid", CodePoints: []int{10991}, Characters: []byte{0xe2, 0xab, 0xaf}},
+ "cirscir": {Name: "cirscir", CodePoints: []int{10690}, Characters: []byte{0xe2, 0xa7, 0x82}},
+ "clubs": {Name: "clubs", CodePoints: []int{9827}, Characters: []byte{0xe2, 0x99, 0xa3}},
+ "clubsuit": {Name: "clubsuit", CodePoints: []int{9827}, Characters: []byte{0xe2, 0x99, 0xa3}},
+ "colon": {Name: "colon", CodePoints: []int{58}, Characters: []byte{0x3a}},
+ "colone": {Name: "colone", CodePoints: []int{8788}, Characters: []byte{0xe2, 0x89, 0x94}},
+ "coloneq": {Name: "coloneq", CodePoints: []int{8788}, Characters: []byte{0xe2, 0x89, 0x94}},
+ "comma": {Name: "comma", CodePoints: []int{44}, Characters: []byte{0x2c}},
+ "commat": {Name: "commat", CodePoints: []int{64}, Characters: []byte{0x40}},
+ "comp": {Name: "comp", CodePoints: []int{8705}, Characters: []byte{0xe2, 0x88, 0x81}},
+ "compfn": {Name: "compfn", CodePoints: []int{8728}, Characters: []byte{0xe2, 0x88, 0x98}},
+ "complement": {Name: "complement", CodePoints: []int{8705}, Characters: []byte{0xe2, 0x88, 0x81}},
+ "complexes": {Name: "complexes", CodePoints: []int{8450}, Characters: []byte{0xe2, 0x84, 0x82}},
+ "cong": {Name: "cong", CodePoints: []int{8773}, Characters: []byte{0xe2, 0x89, 0x85}},
+ "congdot": {Name: "congdot", CodePoints: []int{10861}, Characters: []byte{0xe2, 0xa9, 0xad}},
+ "conint": {Name: "conint", CodePoints: []int{8750}, Characters: []byte{0xe2, 0x88, 0xae}},
+ "copf": {Name: "copf", CodePoints: []int{120148}, Characters: []byte{0xf0, 0x9d, 0x95, 0x94}},
+ "coprod": {Name: "coprod", CodePoints: []int{8720}, Characters: []byte{0xe2, 0x88, 0x90}},
+ "copy": {Name: "copy", CodePoints: []int{169}, Characters: []byte{0xc2, 0xa9}},
+ "copysr": {Name: "copysr", CodePoints: []int{8471}, Characters: []byte{0xe2, 0x84, 0x97}},
+ "crarr": {Name: "crarr", CodePoints: []int{8629}, Characters: []byte{0xe2, 0x86, 0xb5}},
+ "cross": {Name: "cross", CodePoints: []int{10007}, Characters: []byte{0xe2, 0x9c, 0x97}},
+ "cscr": {Name: "cscr", CodePoints: []int{119992}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb8}},
+ "csub": {Name: "csub", CodePoints: []int{10959}, Characters: []byte{0xe2, 0xab, 0x8f}},
+ "csube": {Name: "csube", CodePoints: []int{10961}, Characters: []byte{0xe2, 0xab, 0x91}},
+ "csup": {Name: "csup", CodePoints: []int{10960}, Characters: []byte{0xe2, 0xab, 0x90}},
+ "csupe": {Name: "csupe", CodePoints: []int{10962}, Characters: []byte{0xe2, 0xab, 0x92}},
+ "ctdot": {Name: "ctdot", CodePoints: []int{8943}, Characters: []byte{0xe2, 0x8b, 0xaf}},
+ "cudarrl": {Name: "cudarrl", CodePoints: []int{10552}, Characters: []byte{0xe2, 0xa4, 0xb8}},
+ "cudarrr": {Name: "cudarrr", CodePoints: []int{10549}, Characters: []byte{0xe2, 0xa4, 0xb5}},
+ "cuepr": {Name: "cuepr", CodePoints: []int{8926}, Characters: []byte{0xe2, 0x8b, 0x9e}},
+ "cuesc": {Name: "cuesc", CodePoints: []int{8927}, Characters: []byte{0xe2, 0x8b, 0x9f}},
+ "cularr": {Name: "cularr", CodePoints: []int{8630}, Characters: []byte{0xe2, 0x86, 0xb6}},
+ "cularrp": {Name: "cularrp", CodePoints: []int{10557}, Characters: []byte{0xe2, 0xa4, 0xbd}},
+ "cup": {Name: "cup", CodePoints: []int{8746}, Characters: []byte{0xe2, 0x88, 0xaa}},
+ "cupbrcap": {Name: "cupbrcap", CodePoints: []int{10824}, Characters: []byte{0xe2, 0xa9, 0x88}},
+ "cupcap": {Name: "cupcap", CodePoints: []int{10822}, Characters: []byte{0xe2, 0xa9, 0x86}},
+ "cupcup": {Name: "cupcup", CodePoints: []int{10826}, Characters: []byte{0xe2, 0xa9, 0x8a}},
+ "cupdot": {Name: "cupdot", CodePoints: []int{8845}, Characters: []byte{0xe2, 0x8a, 0x8d}},
+ "cupor": {Name: "cupor", CodePoints: []int{10821}, Characters: []byte{0xe2, 0xa9, 0x85}},
+ "cups": {Name: "cups", CodePoints: []int{8746, 65024}, Characters: []byte{0xe2, 0x88, 0xaa, 0xef, 0xb8, 0x80}},
+ "curarr": {Name: "curarr", CodePoints: []int{8631}, Characters: []byte{0xe2, 0x86, 0xb7}},
+ "curarrm": {Name: "curarrm", CodePoints: []int{10556}, Characters: []byte{0xe2, 0xa4, 0xbc}},
+ "curlyeqprec": {Name: "curlyeqprec", CodePoints: []int{8926}, Characters: []byte{0xe2, 0x8b, 0x9e}},
+ "curlyeqsucc": {Name: "curlyeqsucc", CodePoints: []int{8927}, Characters: []byte{0xe2, 0x8b, 0x9f}},
+ "curlyvee": {Name: "curlyvee", CodePoints: []int{8910}, Characters: []byte{0xe2, 0x8b, 0x8e}},
+ "curlywedge": {Name: "curlywedge", CodePoints: []int{8911}, Characters: []byte{0xe2, 0x8b, 0x8f}},
+ "curren": {Name: "curren", CodePoints: []int{164}, Characters: []byte{0xc2, 0xa4}},
+ "curvearrowleft": {Name: "curvearrowleft", CodePoints: []int{8630}, Characters: []byte{0xe2, 0x86, 0xb6}},
+ "curvearrowright": {Name: "curvearrowright", CodePoints: []int{8631}, Characters: []byte{0xe2, 0x86, 0xb7}},
+ "cuvee": {Name: "cuvee", CodePoints: []int{8910}, Characters: []byte{0xe2, 0x8b, 0x8e}},
+ "cuwed": {Name: "cuwed", CodePoints: []int{8911}, Characters: []byte{0xe2, 0x8b, 0x8f}},
+ "cwconint": {Name: "cwconint", CodePoints: []int{8754}, Characters: []byte{0xe2, 0x88, 0xb2}},
+ "cwint": {Name: "cwint", CodePoints: []int{8753}, Characters: []byte{0xe2, 0x88, 0xb1}},
+ "cylcty": {Name: "cylcty", CodePoints: []int{9005}, Characters: []byte{0xe2, 0x8c, 0xad}},
+ "dArr": {Name: "dArr", CodePoints: []int{8659}, Characters: []byte{0xe2, 0x87, 0x93}},
+ "dHar": {Name: "dHar", CodePoints: []int{10597}, Characters: []byte{0xe2, 0xa5, 0xa5}},
+ "dagger": {Name: "dagger", CodePoints: []int{8224}, Characters: []byte{0xe2, 0x80, 0xa0}},
+ "daleth": {Name: "daleth", CodePoints: []int{8504}, Characters: []byte{0xe2, 0x84, 0xb8}},
+ "darr": {Name: "darr", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
+ "dash": {Name: "dash", CodePoints: []int{8208}, Characters: []byte{0xe2, 0x80, 0x90}},
+ "dashv": {Name: "dashv", CodePoints: []int{8867}, Characters: []byte{0xe2, 0x8a, 0xa3}},
+ "dbkarow": {Name: "dbkarow", CodePoints: []int{10511}, Characters: []byte{0xe2, 0xa4, 0x8f}},
+ "dblac": {Name: "dblac", CodePoints: []int{733}, Characters: []byte{0xcb, 0x9d}},
+ "dcaron": {Name: "dcaron", CodePoints: []int{271}, Characters: []byte{0xc4, 0x8f}},
+ "dcy": {Name: "dcy", CodePoints: []int{1076}, Characters: []byte{0xd0, 0xb4}},
+ "dd": {Name: "dd", CodePoints: []int{8518}, Characters: []byte{0xe2, 0x85, 0x86}},
+ "ddagger": {Name: "ddagger", CodePoints: []int{8225}, Characters: []byte{0xe2, 0x80, 0xa1}},
+ "ddarr": {Name: "ddarr", CodePoints: []int{8650}, Characters: []byte{0xe2, 0x87, 0x8a}},
+ "ddotseq": {Name: "ddotseq", CodePoints: []int{10871}, Characters: []byte{0xe2, 0xa9, 0xb7}},
+ "deg": {Name: "deg", CodePoints: []int{176}, Characters: []byte{0xc2, 0xb0}},
+ "delta": {Name: "delta", CodePoints: []int{948}, Characters: []byte{0xce, 0xb4}},
+ "demptyv": {Name: "demptyv", CodePoints: []int{10673}, Characters: []byte{0xe2, 0xa6, 0xb1}},
+ "dfisht": {Name: "dfisht", CodePoints: []int{10623}, Characters: []byte{0xe2, 0xa5, 0xbf}},
+ "dfr": {Name: "dfr", CodePoints: []int{120097}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa1}},
+ "dharl": {Name: "dharl", CodePoints: []int{8643}, Characters: []byte{0xe2, 0x87, 0x83}},
+ "dharr": {Name: "dharr", CodePoints: []int{8642}, Characters: []byte{0xe2, 0x87, 0x82}},
+ "diam": {Name: "diam", CodePoints: []int{8900}, Characters: []byte{0xe2, 0x8b, 0x84}},
+ "diamond": {Name: "diamond", CodePoints: []int{8900}, Characters: []byte{0xe2, 0x8b, 0x84}},
+ "diamondsuit": {Name: "diamondsuit", CodePoints: []int{9830}, Characters: []byte{0xe2, 0x99, 0xa6}},
+ "diams": {Name: "diams", CodePoints: []int{9830}, Characters: []byte{0xe2, 0x99, 0xa6}},
+ "die": {Name: "die", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
+ "digamma": {Name: "digamma", CodePoints: []int{989}, Characters: []byte{0xcf, 0x9d}},
+ "disin": {Name: "disin", CodePoints: []int{8946}, Characters: []byte{0xe2, 0x8b, 0xb2}},
+ "div": {Name: "div", CodePoints: []int{247}, Characters: []byte{0xc3, 0xb7}},
+ "divide": {Name: "divide", CodePoints: []int{247}, Characters: []byte{0xc3, 0xb7}},
+ "divideontimes": {Name: "divideontimes", CodePoints: []int{8903}, Characters: []byte{0xe2, 0x8b, 0x87}},
+ "divonx": {Name: "divonx", CodePoints: []int{8903}, Characters: []byte{0xe2, 0x8b, 0x87}},
+ "djcy": {Name: "djcy", CodePoints: []int{1106}, Characters: []byte{0xd1, 0x92}},
+ "dlcorn": {Name: "dlcorn", CodePoints: []int{8990}, Characters: []byte{0xe2, 0x8c, 0x9e}},
+ "dlcrop": {Name: "dlcrop", CodePoints: []int{8973}, Characters: []byte{0xe2, 0x8c, 0x8d}},
+ "dollar": {Name: "dollar", CodePoints: []int{36}, Characters: []byte{0x24}},
+ "dopf": {Name: "dopf", CodePoints: []int{120149}, Characters: []byte{0xf0, 0x9d, 0x95, 0x95}},
+ "dot": {Name: "dot", CodePoints: []int{729}, Characters: []byte{0xcb, 0x99}},
+ "doteq": {Name: "doteq", CodePoints: []int{8784}, Characters: []byte{0xe2, 0x89, 0x90}},
+ "doteqdot": {Name: "doteqdot", CodePoints: []int{8785}, Characters: []byte{0xe2, 0x89, 0x91}},
+ "dotminus": {Name: "dotminus", CodePoints: []int{8760}, Characters: []byte{0xe2, 0x88, 0xb8}},
+ "dotplus": {Name: "dotplus", CodePoints: []int{8724}, Characters: []byte{0xe2, 0x88, 0x94}},
+ "dotsquare": {Name: "dotsquare", CodePoints: []int{8865}, Characters: []byte{0xe2, 0x8a, 0xa1}},
+ "doublebarwedge": {Name: "doublebarwedge", CodePoints: []int{8966}, Characters: []byte{0xe2, 0x8c, 0x86}},
+ "downarrow": {Name: "downarrow", CodePoints: []int{8595}, Characters: []byte{0xe2, 0x86, 0x93}},
+ "downdownarrows": {Name: "downdownarrows", CodePoints: []int{8650}, Characters: []byte{0xe2, 0x87, 0x8a}},
+ "downharpoonleft": {Name: "downharpoonleft", CodePoints: []int{8643}, Characters: []byte{0xe2, 0x87, 0x83}},
+ "downharpoonright": {Name: "downharpoonright", CodePoints: []int{8642}, Characters: []byte{0xe2, 0x87, 0x82}},
+ "drbkarow": {Name: "drbkarow", CodePoints: []int{10512}, Characters: []byte{0xe2, 0xa4, 0x90}},
+ "drcorn": {Name: "drcorn", CodePoints: []int{8991}, Characters: []byte{0xe2, 0x8c, 0x9f}},
+ "drcrop": {Name: "drcrop", CodePoints: []int{8972}, Characters: []byte{0xe2, 0x8c, 0x8c}},
+ "dscr": {Name: "dscr", CodePoints: []int{119993}, Characters: []byte{0xf0, 0x9d, 0x92, 0xb9}},
+ "dscy": {Name: "dscy", CodePoints: []int{1109}, Characters: []byte{0xd1, 0x95}},
+ "dsol": {Name: "dsol", CodePoints: []int{10742}, Characters: []byte{0xe2, 0xa7, 0xb6}},
+ "dstrok": {Name: "dstrok", CodePoints: []int{273}, Characters: []byte{0xc4, 0x91}},
+ "dtdot": {Name: "dtdot", CodePoints: []int{8945}, Characters: []byte{0xe2, 0x8b, 0xb1}},
+ "dtri": {Name: "dtri", CodePoints: []int{9663}, Characters: []byte{0xe2, 0x96, 0xbf}},
+ "dtrif": {Name: "dtrif", CodePoints: []int{9662}, Characters: []byte{0xe2, 0x96, 0xbe}},
+ "duarr": {Name: "duarr", CodePoints: []int{8693}, Characters: []byte{0xe2, 0x87, 0xb5}},
+ "duhar": {Name: "duhar", CodePoints: []int{10607}, Characters: []byte{0xe2, 0xa5, 0xaf}},
+ "dwangle": {Name: "dwangle", CodePoints: []int{10662}, Characters: []byte{0xe2, 0xa6, 0xa6}},
+ "dzcy": {Name: "dzcy", CodePoints: []int{1119}, Characters: []byte{0xd1, 0x9f}},
+ "dzigrarr": {Name: "dzigrarr", CodePoints: []int{10239}, Characters: []byte{0xe2, 0x9f, 0xbf}},
+ "eDDot": {Name: "eDDot", CodePoints: []int{10871}, Characters: []byte{0xe2, 0xa9, 0xb7}},
+ "eDot": {Name: "eDot", CodePoints: []int{8785}, Characters: []byte{0xe2, 0x89, 0x91}},
+ "eacute": {Name: "eacute", CodePoints: []int{233}, Characters: []byte{0xc3, 0xa9}},
+ "easter": {Name: "easter", CodePoints: []int{10862}, Characters: []byte{0xe2, 0xa9, 0xae}},
+ "ecaron": {Name: "ecaron", CodePoints: []int{283}, Characters: []byte{0xc4, 0x9b}},
+ "ecir": {Name: "ecir", CodePoints: []int{8790}, Characters: []byte{0xe2, 0x89, 0x96}},
+ "ecirc": {Name: "ecirc", CodePoints: []int{234}, Characters: []byte{0xc3, 0xaa}},
+ "ecolon": {Name: "ecolon", CodePoints: []int{8789}, Characters: []byte{0xe2, 0x89, 0x95}},
+ "ecy": {Name: "ecy", CodePoints: []int{1101}, Characters: []byte{0xd1, 0x8d}},
+ "edot": {Name: "edot", CodePoints: []int{279}, Characters: []byte{0xc4, 0x97}},
+ "ee": {Name: "ee", CodePoints: []int{8519}, Characters: []byte{0xe2, 0x85, 0x87}},
+ "efDot": {Name: "efDot", CodePoints: []int{8786}, Characters: []byte{0xe2, 0x89, 0x92}},
+ "efr": {Name: "efr", CodePoints: []int{120098}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa2}},
+ "eg": {Name: "eg", CodePoints: []int{10906}, Characters: []byte{0xe2, 0xaa, 0x9a}},
+ "egrave": {Name: "egrave", CodePoints: []int{232}, Characters: []byte{0xc3, 0xa8}},
+ "egs": {Name: "egs", CodePoints: []int{10902}, Characters: []byte{0xe2, 0xaa, 0x96}},
+ "egsdot": {Name: "egsdot", CodePoints: []int{10904}, Characters: []byte{0xe2, 0xaa, 0x98}},
+ "el": {Name: "el", CodePoints: []int{10905}, Characters: []byte{0xe2, 0xaa, 0x99}},
+ "elinters": {Name: "elinters", CodePoints: []int{9191}, Characters: []byte{0xe2, 0x8f, 0xa7}},
+ "ell": {Name: "ell", CodePoints: []int{8467}, Characters: []byte{0xe2, 0x84, 0x93}},
+ "els": {Name: "els", CodePoints: []int{10901}, Characters: []byte{0xe2, 0xaa, 0x95}},
+ "elsdot": {Name: "elsdot", CodePoints: []int{10903}, Characters: []byte{0xe2, 0xaa, 0x97}},
+ "emacr": {Name: "emacr", CodePoints: []int{275}, Characters: []byte{0xc4, 0x93}},
+ "empty": {Name: "empty", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
+ "emptyset": {Name: "emptyset", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
+ "emptyv": {Name: "emptyv", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
+ "emsp": {Name: "emsp", CodePoints: []int{8195}, Characters: []byte{0xe2, 0x80, 0x83}},
+ "emsp13": {Name: "emsp13", CodePoints: []int{8196}, Characters: []byte{0xe2, 0x80, 0x84}},
+ "emsp14": {Name: "emsp14", CodePoints: []int{8197}, Characters: []byte{0xe2, 0x80, 0x85}},
+ "eng": {Name: "eng", CodePoints: []int{331}, Characters: []byte{0xc5, 0x8b}},
+ "ensp": {Name: "ensp", CodePoints: []int{8194}, Characters: []byte{0xe2, 0x80, 0x82}},
+ "eogon": {Name: "eogon", CodePoints: []int{281}, Characters: []byte{0xc4, 0x99}},
+ "eopf": {Name: "eopf", CodePoints: []int{120150}, Characters: []byte{0xf0, 0x9d, 0x95, 0x96}},
+ "epar": {Name: "epar", CodePoints: []int{8917}, Characters: []byte{0xe2, 0x8b, 0x95}},
+ "eparsl": {Name: "eparsl", CodePoints: []int{10723}, Characters: []byte{0xe2, 0xa7, 0xa3}},
+ "eplus": {Name: "eplus", CodePoints: []int{10865}, Characters: []byte{0xe2, 0xa9, 0xb1}},
+ "epsi": {Name: "epsi", CodePoints: []int{949}, Characters: []byte{0xce, 0xb5}},
+ "epsilon": {Name: "epsilon", CodePoints: []int{949}, Characters: []byte{0xce, 0xb5}},
+ "epsiv": {Name: "epsiv", CodePoints: []int{1013}, Characters: []byte{0xcf, 0xb5}},
+ "eqcirc": {Name: "eqcirc", CodePoints: []int{8790}, Characters: []byte{0xe2, 0x89, 0x96}},
+ "eqcolon": {Name: "eqcolon", CodePoints: []int{8789}, Characters: []byte{0xe2, 0x89, 0x95}},
+ "eqsim": {Name: "eqsim", CodePoints: []int{8770}, Characters: []byte{0xe2, 0x89, 0x82}},
+ "eqslantgtr": {Name: "eqslantgtr", CodePoints: []int{10902}, Characters: []byte{0xe2, 0xaa, 0x96}},
+ "eqslantless": {Name: "eqslantless", CodePoints: []int{10901}, Characters: []byte{0xe2, 0xaa, 0x95}},
+ "equals": {Name: "equals", CodePoints: []int{61}, Characters: []byte{0x3d}},
+ "equest": {Name: "equest", CodePoints: []int{8799}, Characters: []byte{0xe2, 0x89, 0x9f}},
+ "equiv": {Name: "equiv", CodePoints: []int{8801}, Characters: []byte{0xe2, 0x89, 0xa1}},
+ "equivDD": {Name: "equivDD", CodePoints: []int{10872}, Characters: []byte{0xe2, 0xa9, 0xb8}},
+ "eqvparsl": {Name: "eqvparsl", CodePoints: []int{10725}, Characters: []byte{0xe2, 0xa7, 0xa5}},
+ "erDot": {Name: "erDot", CodePoints: []int{8787}, Characters: []byte{0xe2, 0x89, 0x93}},
+ "erarr": {Name: "erarr", CodePoints: []int{10609}, Characters: []byte{0xe2, 0xa5, 0xb1}},
+ "escr": {Name: "escr", CodePoints: []int{8495}, Characters: []byte{0xe2, 0x84, 0xaf}},
+ "esdot": {Name: "esdot", CodePoints: []int{8784}, Characters: []byte{0xe2, 0x89, 0x90}},
+ "esim": {Name: "esim", CodePoints: []int{8770}, Characters: []byte{0xe2, 0x89, 0x82}},
+ "eta": {Name: "eta", CodePoints: []int{951}, Characters: []byte{0xce, 0xb7}},
+ "eth": {Name: "eth", CodePoints: []int{240}, Characters: []byte{0xc3, 0xb0}},
+ "euml": {Name: "euml", CodePoints: []int{235}, Characters: []byte{0xc3, 0xab}},
+ "euro": {Name: "euro", CodePoints: []int{8364}, Characters: []byte{0xe2, 0x82, 0xac}},
+ "excl": {Name: "excl", CodePoints: []int{33}, Characters: []byte{0x21}},
+ "exist": {Name: "exist", CodePoints: []int{8707}, Characters: []byte{0xe2, 0x88, 0x83}},
+ "expectation": {Name: "expectation", CodePoints: []int{8496}, Characters: []byte{0xe2, 0x84, 0xb0}},
+ "exponentiale": {Name: "exponentiale", CodePoints: []int{8519}, Characters: []byte{0xe2, 0x85, 0x87}},
+ "fallingdotseq": {Name: "fallingdotseq", CodePoints: []int{8786}, Characters: []byte{0xe2, 0x89, 0x92}},
+ "fcy": {Name: "fcy", CodePoints: []int{1092}, Characters: []byte{0xd1, 0x84}},
+ "female": {Name: "female", CodePoints: []int{9792}, Characters: []byte{0xe2, 0x99, 0x80}},
+ "ffilig": {Name: "ffilig", CodePoints: []int{64259}, Characters: []byte{0xef, 0xac, 0x83}},
+ "fflig": {Name: "fflig", CodePoints: []int{64256}, Characters: []byte{0xef, 0xac, 0x80}},
+ "ffllig": {Name: "ffllig", CodePoints: []int{64260}, Characters: []byte{0xef, 0xac, 0x84}},
+ "ffr": {Name: "ffr", CodePoints: []int{120099}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa3}},
+ "filig": {Name: "filig", CodePoints: []int{64257}, Characters: []byte{0xef, 0xac, 0x81}},
+ "fjlig": {Name: "fjlig", CodePoints: []int{102, 106}, Characters: []byte{0x66, 0x6a}},
+ "flat": {Name: "flat", CodePoints: []int{9837}, Characters: []byte{0xe2, 0x99, 0xad}},
+ "fllig": {Name: "fllig", CodePoints: []int{64258}, Characters: []byte{0xef, 0xac, 0x82}},
+ "fltns": {Name: "fltns", CodePoints: []int{9649}, Characters: []byte{0xe2, 0x96, 0xb1}},
+ "fnof": {Name: "fnof", CodePoints: []int{402}, Characters: []byte{0xc6, 0x92}},
+ "fopf": {Name: "fopf", CodePoints: []int{120151}, Characters: []byte{0xf0, 0x9d, 0x95, 0x97}},
+ "forall": {Name: "forall", CodePoints: []int{8704}, Characters: []byte{0xe2, 0x88, 0x80}},
+ "fork": {Name: "fork", CodePoints: []int{8916}, Characters: []byte{0xe2, 0x8b, 0x94}},
+ "forkv": {Name: "forkv", CodePoints: []int{10969}, Characters: []byte{0xe2, 0xab, 0x99}},
+ "fpartint": {Name: "fpartint", CodePoints: []int{10765}, Characters: []byte{0xe2, 0xa8, 0x8d}},
+ "frac12": {Name: "frac12", CodePoints: []int{189}, Characters: []byte{0xc2, 0xbd}},
+ "frac13": {Name: "frac13", CodePoints: []int{8531}, Characters: []byte{0xe2, 0x85, 0x93}},
+ "frac14": {Name: "frac14", CodePoints: []int{188}, Characters: []byte{0xc2, 0xbc}},
+ "frac15": {Name: "frac15", CodePoints: []int{8533}, Characters: []byte{0xe2, 0x85, 0x95}},
+ "frac16": {Name: "frac16", CodePoints: []int{8537}, Characters: []byte{0xe2, 0x85, 0x99}},
+ "frac18": {Name: "frac18", CodePoints: []int{8539}, Characters: []byte{0xe2, 0x85, 0x9b}},
+ "frac23": {Name: "frac23", CodePoints: []int{8532}, Characters: []byte{0xe2, 0x85, 0x94}},
+ "frac25": {Name: "frac25", CodePoints: []int{8534}, Characters: []byte{0xe2, 0x85, 0x96}},
+ "frac34": {Name: "frac34", CodePoints: []int{190}, Characters: []byte{0xc2, 0xbe}},
+ "frac35": {Name: "frac35", CodePoints: []int{8535}, Characters: []byte{0xe2, 0x85, 0x97}},
+ "frac38": {Name: "frac38", CodePoints: []int{8540}, Characters: []byte{0xe2, 0x85, 0x9c}},
+ "frac45": {Name: "frac45", CodePoints: []int{8536}, Characters: []byte{0xe2, 0x85, 0x98}},
+ "frac56": {Name: "frac56", CodePoints: []int{8538}, Characters: []byte{0xe2, 0x85, 0x9a}},
+ "frac58": {Name: "frac58", CodePoints: []int{8541}, Characters: []byte{0xe2, 0x85, 0x9d}},
+ "frac78": {Name: "frac78", CodePoints: []int{8542}, Characters: []byte{0xe2, 0x85, 0x9e}},
+ "frasl": {Name: "frasl", CodePoints: []int{8260}, Characters: []byte{0xe2, 0x81, 0x84}},
+ "frown": {Name: "frown", CodePoints: []int{8994}, Characters: []byte{0xe2, 0x8c, 0xa2}},
+ "fscr": {Name: "fscr", CodePoints: []int{119995}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbb}},
+ "gE": {Name: "gE", CodePoints: []int{8807}, Characters: []byte{0xe2, 0x89, 0xa7}},
+ "gEl": {Name: "gEl", CodePoints: []int{10892}, Characters: []byte{0xe2, 0xaa, 0x8c}},
+ "gacute": {Name: "gacute", CodePoints: []int{501}, Characters: []byte{0xc7, 0xb5}},
+ "gamma": {Name: "gamma", CodePoints: []int{947}, Characters: []byte{0xce, 0xb3}},
+ "gammad": {Name: "gammad", CodePoints: []int{989}, Characters: []byte{0xcf, 0x9d}},
+ "gap": {Name: "gap", CodePoints: []int{10886}, Characters: []byte{0xe2, 0xaa, 0x86}},
+ "gbreve": {Name: "gbreve", CodePoints: []int{287}, Characters: []byte{0xc4, 0x9f}},
+ "gcirc": {Name: "gcirc", CodePoints: []int{285}, Characters: []byte{0xc4, 0x9d}},
+ "gcy": {Name: "gcy", CodePoints: []int{1075}, Characters: []byte{0xd0, 0xb3}},
+ "gdot": {Name: "gdot", CodePoints: []int{289}, Characters: []byte{0xc4, 0xa1}},
+ "ge": {Name: "ge", CodePoints: []int{8805}, Characters: []byte{0xe2, 0x89, 0xa5}},
+ "gel": {Name: "gel", CodePoints: []int{8923}, Characters: []byte{0xe2, 0x8b, 0x9b}},
+ "geq": {Name: "geq", CodePoints: []int{8805}, Characters: []byte{0xe2, 0x89, 0xa5}},
+ "geqq": {Name: "geqq", CodePoints: []int{8807}, Characters: []byte{0xe2, 0x89, 0xa7}},
+ "geqslant": {Name: "geqslant", CodePoints: []int{10878}, Characters: []byte{0xe2, 0xa9, 0xbe}},
+ "ges": {Name: "ges", CodePoints: []int{10878}, Characters: []byte{0xe2, 0xa9, 0xbe}},
+ "gescc": {Name: "gescc", CodePoints: []int{10921}, Characters: []byte{0xe2, 0xaa, 0xa9}},
+ "gesdot": {Name: "gesdot", CodePoints: []int{10880}, Characters: []byte{0xe2, 0xaa, 0x80}},
+ "gesdoto": {Name: "gesdoto", CodePoints: []int{10882}, Characters: []byte{0xe2, 0xaa, 0x82}},
+ "gesdotol": {Name: "gesdotol", CodePoints: []int{10884}, Characters: []byte{0xe2, 0xaa, 0x84}},
+ "gesl": {Name: "gesl", CodePoints: []int{8923, 65024}, Characters: []byte{0xe2, 0x8b, 0x9b, 0xef, 0xb8, 0x80}},
+ "gesles": {Name: "gesles", CodePoints: []int{10900}, Characters: []byte{0xe2, 0xaa, 0x94}},
+ "gfr": {Name: "gfr", CodePoints: []int{120100}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa4}},
+ "gg": {Name: "gg", CodePoints: []int{8811}, Characters: []byte{0xe2, 0x89, 0xab}},
+ "ggg": {Name: "ggg", CodePoints: []int{8921}, Characters: []byte{0xe2, 0x8b, 0x99}},
+ "gimel": {Name: "gimel", CodePoints: []int{8503}, Characters: []byte{0xe2, 0x84, 0xb7}},
+ "gjcy": {Name: "gjcy", CodePoints: []int{1107}, Characters: []byte{0xd1, 0x93}},
+ "gl": {Name: "gl", CodePoints: []int{8823}, Characters: []byte{0xe2, 0x89, 0xb7}},
+ "glE": {Name: "glE", CodePoints: []int{10898}, Characters: []byte{0xe2, 0xaa, 0x92}},
+ "gla": {Name: "gla", CodePoints: []int{10917}, Characters: []byte{0xe2, 0xaa, 0xa5}},
+ "glj": {Name: "glj", CodePoints: []int{10916}, Characters: []byte{0xe2, 0xaa, 0xa4}},
+ "gnE": {Name: "gnE", CodePoints: []int{8809}, Characters: []byte{0xe2, 0x89, 0xa9}},
+ "gnap": {Name: "gnap", CodePoints: []int{10890}, Characters: []byte{0xe2, 0xaa, 0x8a}},
+ "gnapprox": {Name: "gnapprox", CodePoints: []int{10890}, Characters: []byte{0xe2, 0xaa, 0x8a}},
+ "gne": {Name: "gne", CodePoints: []int{10888}, Characters: []byte{0xe2, 0xaa, 0x88}},
+ "gneq": {Name: "gneq", CodePoints: []int{10888}, Characters: []byte{0xe2, 0xaa, 0x88}},
+ "gneqq": {Name: "gneqq", CodePoints: []int{8809}, Characters: []byte{0xe2, 0x89, 0xa9}},
+ "gnsim": {Name: "gnsim", CodePoints: []int{8935}, Characters: []byte{0xe2, 0x8b, 0xa7}},
+ "gopf": {Name: "gopf", CodePoints: []int{120152}, Characters: []byte{0xf0, 0x9d, 0x95, 0x98}},
+ "grave": {Name: "grave", CodePoints: []int{96}, Characters: []byte{0x60}},
+ "gscr": {Name: "gscr", CodePoints: []int{8458}, Characters: []byte{0xe2, 0x84, 0x8a}},
+ "gsim": {Name: "gsim", CodePoints: []int{8819}, Characters: []byte{0xe2, 0x89, 0xb3}},
+ "gsime": {Name: "gsime", CodePoints: []int{10894}, Characters: []byte{0xe2, 0xaa, 0x8e}},
+ "gsiml": {Name: "gsiml", CodePoints: []int{10896}, Characters: []byte{0xe2, 0xaa, 0x90}},
+ "gt": {Name: "gt", CodePoints: []int{62}, Characters: []byte{0x3e}},
+ "gtcc": {Name: "gtcc", CodePoints: []int{10919}, Characters: []byte{0xe2, 0xaa, 0xa7}},
+ "gtcir": {Name: "gtcir", CodePoints: []int{10874}, Characters: []byte{0xe2, 0xa9, 0xba}},
+ "gtdot": {Name: "gtdot", CodePoints: []int{8919}, Characters: []byte{0xe2, 0x8b, 0x97}},
+ "gtlPar": {Name: "gtlPar", CodePoints: []int{10645}, Characters: []byte{0xe2, 0xa6, 0x95}},
+ "gtquest": {Name: "gtquest", CodePoints: []int{10876}, Characters: []byte{0xe2, 0xa9, 0xbc}},
+ "gtrapprox": {Name: "gtrapprox", CodePoints: []int{10886}, Characters: []byte{0xe2, 0xaa, 0x86}},
+ "gtrarr": {Name: "gtrarr", CodePoints: []int{10616}, Characters: []byte{0xe2, 0xa5, 0xb8}},
+ "gtrdot": {Name: "gtrdot", CodePoints: []int{8919}, Characters: []byte{0xe2, 0x8b, 0x97}},
+ "gtreqless": {Name: "gtreqless", CodePoints: []int{8923}, Characters: []byte{0xe2, 0x8b, 0x9b}},
+ "gtreqqless": {Name: "gtreqqless", CodePoints: []int{10892}, Characters: []byte{0xe2, 0xaa, 0x8c}},
+ "gtrless": {Name: "gtrless", CodePoints: []int{8823}, Characters: []byte{0xe2, 0x89, 0xb7}},
+ "gtrsim": {Name: "gtrsim", CodePoints: []int{8819}, Characters: []byte{0xe2, 0x89, 0xb3}},
+ "gvertneqq": {Name: "gvertneqq", CodePoints: []int{8809, 65024}, Characters: []byte{0xe2, 0x89, 0xa9, 0xef, 0xb8, 0x80}},
+ "gvnE": {Name: "gvnE", CodePoints: []int{8809, 65024}, Characters: []byte{0xe2, 0x89, 0xa9, 0xef, 0xb8, 0x80}},
+ "hArr": {Name: "hArr", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
+ "hairsp": {Name: "hairsp", CodePoints: []int{8202}, Characters: []byte{0xe2, 0x80, 0x8a}},
+ "half": {Name: "half", CodePoints: []int{189}, Characters: []byte{0xc2, 0xbd}},
+ "hamilt": {Name: "hamilt", CodePoints: []int{8459}, Characters: []byte{0xe2, 0x84, 0x8b}},
+ "hardcy": {Name: "hardcy", CodePoints: []int{1098}, Characters: []byte{0xd1, 0x8a}},
+ "harr": {Name: "harr", CodePoints: []int{8596}, Characters: []byte{0xe2, 0x86, 0x94}},
+ "harrcir": {Name: "harrcir", CodePoints: []int{10568}, Characters: []byte{0xe2, 0xa5, 0x88}},
+ "harrw": {Name: "harrw", CodePoints: []int{8621}, Characters: []byte{0xe2, 0x86, 0xad}},
+ "hbar": {Name: "hbar", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
+ "hcirc": {Name: "hcirc", CodePoints: []int{293}, Characters: []byte{0xc4, 0xa5}},
+ "hearts": {Name: "hearts", CodePoints: []int{9829}, Characters: []byte{0xe2, 0x99, 0xa5}},
+ "heartsuit": {Name: "heartsuit", CodePoints: []int{9829}, Characters: []byte{0xe2, 0x99, 0xa5}},
+ "hellip": {Name: "hellip", CodePoints: []int{8230}, Characters: []byte{0xe2, 0x80, 0xa6}},
+ "hercon": {Name: "hercon", CodePoints: []int{8889}, Characters: []byte{0xe2, 0x8a, 0xb9}},
+ "hfr": {Name: "hfr", CodePoints: []int{120101}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa5}},
+ "hksearow": {Name: "hksearow", CodePoints: []int{10533}, Characters: []byte{0xe2, 0xa4, 0xa5}},
+ "hkswarow": {Name: "hkswarow", CodePoints: []int{10534}, Characters: []byte{0xe2, 0xa4, 0xa6}},
+ "hoarr": {Name: "hoarr", CodePoints: []int{8703}, Characters: []byte{0xe2, 0x87, 0xbf}},
+ "homtht": {Name: "homtht", CodePoints: []int{8763}, Characters: []byte{0xe2, 0x88, 0xbb}},
+ "hookleftarrow": {Name: "hookleftarrow", CodePoints: []int{8617}, Characters: []byte{0xe2, 0x86, 0xa9}},
+ "hookrightarrow": {Name: "hookrightarrow", CodePoints: []int{8618}, Characters: []byte{0xe2, 0x86, 0xaa}},
+ "hopf": {Name: "hopf", CodePoints: []int{120153}, Characters: []byte{0xf0, 0x9d, 0x95, 0x99}},
+ "horbar": {Name: "horbar", CodePoints: []int{8213}, Characters: []byte{0xe2, 0x80, 0x95}},
+ "hscr": {Name: "hscr", CodePoints: []int{119997}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbd}},
+ "hslash": {Name: "hslash", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
+ "hstrok": {Name: "hstrok", CodePoints: []int{295}, Characters: []byte{0xc4, 0xa7}},
+ "hybull": {Name: "hybull", CodePoints: []int{8259}, Characters: []byte{0xe2, 0x81, 0x83}},
+ "hyphen": {Name: "hyphen", CodePoints: []int{8208}, Characters: []byte{0xe2, 0x80, 0x90}},
+ "iacute": {Name: "iacute", CodePoints: []int{237}, Characters: []byte{0xc3, 0xad}},
+ "ic": {Name: "ic", CodePoints: []int{8291}, Characters: []byte{0xe2, 0x81, 0xa3}},
+ "icirc": {Name: "icirc", CodePoints: []int{238}, Characters: []byte{0xc3, 0xae}},
+ "icy": {Name: "icy", CodePoints: []int{1080}, Characters: []byte{0xd0, 0xb8}},
+ "iecy": {Name: "iecy", CodePoints: []int{1077}, Characters: []byte{0xd0, 0xb5}},
+ "iexcl": {Name: "iexcl", CodePoints: []int{161}, Characters: []byte{0xc2, 0xa1}},
+ "iff": {Name: "iff", CodePoints: []int{8660}, Characters: []byte{0xe2, 0x87, 0x94}},
+ "ifr": {Name: "ifr", CodePoints: []int{120102}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa6}},
+ "igrave": {Name: "igrave", CodePoints: []int{236}, Characters: []byte{0xc3, 0xac}},
+ "ii": {Name: "ii", CodePoints: []int{8520}, Characters: []byte{0xe2, 0x85, 0x88}},
+ "iiiint": {Name: "iiiint", CodePoints: []int{10764}, Characters: []byte{0xe2, 0xa8, 0x8c}},
+ "iiint": {Name: "iiint", CodePoints: []int{8749}, Characters: []byte{0xe2, 0x88, 0xad}},
+ "iinfin": {Name: "iinfin", CodePoints: []int{10716}, Characters: []byte{0xe2, 0xa7, 0x9c}},
+ "iiota": {Name: "iiota", CodePoints: []int{8489}, Characters: []byte{0xe2, 0x84, 0xa9}},
+ "ijlig": {Name: "ijlig", CodePoints: []int{307}, Characters: []byte{0xc4, 0xb3}},
+ "imacr": {Name: "imacr", CodePoints: []int{299}, Characters: []byte{0xc4, 0xab}},
+ "image": {Name: "image", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
+ "imagline": {Name: "imagline", CodePoints: []int{8464}, Characters: []byte{0xe2, 0x84, 0x90}},
+ "imagpart": {Name: "imagpart", CodePoints: []int{8465}, Characters: []byte{0xe2, 0x84, 0x91}},
+ "imath": {Name: "imath", CodePoints: []int{305}, Characters: []byte{0xc4, 0xb1}},
+ "imof": {Name: "imof", CodePoints: []int{8887}, Characters: []byte{0xe2, 0x8a, 0xb7}},
+ "imped": {Name: "imped", CodePoints: []int{437}, Characters: []byte{0xc6, 0xb5}},
+ "in": {Name: "in", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
+ "incare": {Name: "incare", CodePoints: []int{8453}, Characters: []byte{0xe2, 0x84, 0x85}},
+ "infin": {Name: "infin", CodePoints: []int{8734}, Characters: []byte{0xe2, 0x88, 0x9e}},
+ "infintie": {Name: "infintie", CodePoints: []int{10717}, Characters: []byte{0xe2, 0xa7, 0x9d}},
+ "inodot": {Name: "inodot", CodePoints: []int{305}, Characters: []byte{0xc4, 0xb1}},
+ "int": {Name: "int", CodePoints: []int{8747}, Characters: []byte{0xe2, 0x88, 0xab}},
+ "intcal": {Name: "intcal", CodePoints: []int{8890}, Characters: []byte{0xe2, 0x8a, 0xba}},
+ "integers": {Name: "integers", CodePoints: []int{8484}, Characters: []byte{0xe2, 0x84, 0xa4}},
+ "intercal": {Name: "intercal", CodePoints: []int{8890}, Characters: []byte{0xe2, 0x8a, 0xba}},
+ "intlarhk": {Name: "intlarhk", CodePoints: []int{10775}, Characters: []byte{0xe2, 0xa8, 0x97}},
+ "intprod": {Name: "intprod", CodePoints: []int{10812}, Characters: []byte{0xe2, 0xa8, 0xbc}},
+ "iocy": {Name: "iocy", CodePoints: []int{1105}, Characters: []byte{0xd1, 0x91}},
+ "iogon": {Name: "iogon", CodePoints: []int{303}, Characters: []byte{0xc4, 0xaf}},
+ "iopf": {Name: "iopf", CodePoints: []int{120154}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9a}},
+ "iota": {Name: "iota", CodePoints: []int{953}, Characters: []byte{0xce, 0xb9}},
+ "iprod": {Name: "iprod", CodePoints: []int{10812}, Characters: []byte{0xe2, 0xa8, 0xbc}},
+ "iquest": {Name: "iquest", CodePoints: []int{191}, Characters: []byte{0xc2, 0xbf}},
+ "iscr": {Name: "iscr", CodePoints: []int{119998}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbe}},
+ "isin": {Name: "isin", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
+ "isinE": {Name: "isinE", CodePoints: []int{8953}, Characters: []byte{0xe2, 0x8b, 0xb9}},
+ "isindot": {Name: "isindot", CodePoints: []int{8949}, Characters: []byte{0xe2, 0x8b, 0xb5}},
+ "isins": {Name: "isins", CodePoints: []int{8948}, Characters: []byte{0xe2, 0x8b, 0xb4}},
+ "isinsv": {Name: "isinsv", CodePoints: []int{8947}, Characters: []byte{0xe2, 0x8b, 0xb3}},
+ "isinv": {Name: "isinv", CodePoints: []int{8712}, Characters: []byte{0xe2, 0x88, 0x88}},
+ "it": {Name: "it", CodePoints: []int{8290}, Characters: []byte{0xe2, 0x81, 0xa2}},
+ "itilde": {Name: "itilde", CodePoints: []int{297}, Characters: []byte{0xc4, 0xa9}},
+ "iukcy": {Name: "iukcy", CodePoints: []int{1110}, Characters: []byte{0xd1, 0x96}},
+ "iuml": {Name: "iuml", CodePoints: []int{239}, Characters: []byte{0xc3, 0xaf}},
+ "jcirc": {Name: "jcirc", CodePoints: []int{309}, Characters: []byte{0xc4, 0xb5}},
+ "jcy": {Name: "jcy", CodePoints: []int{1081}, Characters: []byte{0xd0, 0xb9}},
+ "jfr": {Name: "jfr", CodePoints: []int{120103}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa7}},
+ "jmath": {Name: "jmath", CodePoints: []int{567}, Characters: []byte{0xc8, 0xb7}},
+ "jopf": {Name: "jopf", CodePoints: []int{120155}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9b}},
+ "jscr": {Name: "jscr", CodePoints: []int{119999}, Characters: []byte{0xf0, 0x9d, 0x92, 0xbf}},
+ "jsercy": {Name: "jsercy", CodePoints: []int{1112}, Characters: []byte{0xd1, 0x98}},
+ "jukcy": {Name: "jukcy", CodePoints: []int{1108}, Characters: []byte{0xd1, 0x94}},
+ "kappa": {Name: "kappa", CodePoints: []int{954}, Characters: []byte{0xce, 0xba}},
+ "kappav": {Name: "kappav", CodePoints: []int{1008}, Characters: []byte{0xcf, 0xb0}},
+ "kcedil": {Name: "kcedil", CodePoints: []int{311}, Characters: []byte{0xc4, 0xb7}},
+ "kcy": {Name: "kcy", CodePoints: []int{1082}, Characters: []byte{0xd0, 0xba}},
+ "kfr": {Name: "kfr", CodePoints: []int{120104}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa8}},
+ "kgreen": {Name: "kgreen", CodePoints: []int{312}, Characters: []byte{0xc4, 0xb8}},
+ "khcy": {Name: "khcy", CodePoints: []int{1093}, Characters: []byte{0xd1, 0x85}},
+ "kjcy": {Name: "kjcy", CodePoints: []int{1116}, Characters: []byte{0xd1, 0x9c}},
+ "kopf": {Name: "kopf", CodePoints: []int{120156}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9c}},
+ "kscr": {Name: "kscr", CodePoints: []int{120000}, Characters: []byte{0xf0, 0x9d, 0x93, 0x80}},
+ "lAarr": {Name: "lAarr", CodePoints: []int{8666}, Characters: []byte{0xe2, 0x87, 0x9a}},
+ "lArr": {Name: "lArr", CodePoints: []int{8656}, Characters: []byte{0xe2, 0x87, 0x90}},
+ "lAtail": {Name: "lAtail", CodePoints: []int{10523}, Characters: []byte{0xe2, 0xa4, 0x9b}},
+ "lBarr": {Name: "lBarr", CodePoints: []int{10510}, Characters: []byte{0xe2, 0xa4, 0x8e}},
+ "lE": {Name: "lE", CodePoints: []int{8806}, Characters: []byte{0xe2, 0x89, 0xa6}},
+ "lEg": {Name: "lEg", CodePoints: []int{10891}, Characters: []byte{0xe2, 0xaa, 0x8b}},
+ "lHar": {Name: "lHar", CodePoints: []int{10594}, Characters: []byte{0xe2, 0xa5, 0xa2}},
+ "lacute": {Name: "lacute", CodePoints: []int{314}, Characters: []byte{0xc4, 0xba}},
+ "laemptyv": {Name: "laemptyv", CodePoints: []int{10676}, Characters: []byte{0xe2, 0xa6, 0xb4}},
+ "lagran": {Name: "lagran", CodePoints: []int{8466}, Characters: []byte{0xe2, 0x84, 0x92}},
+ "lambda": {Name: "lambda", CodePoints: []int{955}, Characters: []byte{0xce, 0xbb}},
+ "lang": {Name: "lang", CodePoints: []int{10216}, Characters: []byte{0xe2, 0x9f, 0xa8}},
+ "langd": {Name: "langd", CodePoints: []int{10641}, Characters: []byte{0xe2, 0xa6, 0x91}},
+ "langle": {Name: "langle", CodePoints: []int{10216}, Characters: []byte{0xe2, 0x9f, 0xa8}},
+ "lap": {Name: "lap", CodePoints: []int{10885}, Characters: []byte{0xe2, 0xaa, 0x85}},
+ "laquo": {Name: "laquo", CodePoints: []int{171}, Characters: []byte{0xc2, 0xab}},
+ "larr": {Name: "larr", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
+ "larrb": {Name: "larrb", CodePoints: []int{8676}, Characters: []byte{0xe2, 0x87, 0xa4}},
+ "larrbfs": {Name: "larrbfs", CodePoints: []int{10527}, Characters: []byte{0xe2, 0xa4, 0x9f}},
+ "larrfs": {Name: "larrfs", CodePoints: []int{10525}, Characters: []byte{0xe2, 0xa4, 0x9d}},
+ "larrhk": {Name: "larrhk", CodePoints: []int{8617}, Characters: []byte{0xe2, 0x86, 0xa9}},
+ "larrlp": {Name: "larrlp", CodePoints: []int{8619}, Characters: []byte{0xe2, 0x86, 0xab}},
+ "larrpl": {Name: "larrpl", CodePoints: []int{10553}, Characters: []byte{0xe2, 0xa4, 0xb9}},
+ "larrsim": {Name: "larrsim", CodePoints: []int{10611}, Characters: []byte{0xe2, 0xa5, 0xb3}},
+ "larrtl": {Name: "larrtl", CodePoints: []int{8610}, Characters: []byte{0xe2, 0x86, 0xa2}},
+ "lat": {Name: "lat", CodePoints: []int{10923}, Characters: []byte{0xe2, 0xaa, 0xab}},
+ "latail": {Name: "latail", CodePoints: []int{10521}, Characters: []byte{0xe2, 0xa4, 0x99}},
+ "late": {Name: "late", CodePoints: []int{10925}, Characters: []byte{0xe2, 0xaa, 0xad}},
+ "lates": {Name: "lates", CodePoints: []int{10925, 65024}, Characters: []byte{0xe2, 0xaa, 0xad, 0xef, 0xb8, 0x80}},
+ "lbarr": {Name: "lbarr", CodePoints: []int{10508}, Characters: []byte{0xe2, 0xa4, 0x8c}},
+ "lbbrk": {Name: "lbbrk", CodePoints: []int{10098}, Characters: []byte{0xe2, 0x9d, 0xb2}},
+ "lbrace": {Name: "lbrace", CodePoints: []int{123}, Characters: []byte{0x7b}},
+ "lbrack": {Name: "lbrack", CodePoints: []int{91}, Characters: []byte{0x5b}},
+ "lbrke": {Name: "lbrke", CodePoints: []int{10635}, Characters: []byte{0xe2, 0xa6, 0x8b}},
+ "lbrksld": {Name: "lbrksld", CodePoints: []int{10639}, Characters: []byte{0xe2, 0xa6, 0x8f}},
+ "lbrkslu": {Name: "lbrkslu", CodePoints: []int{10637}, Characters: []byte{0xe2, 0xa6, 0x8d}},
+ "lcaron": {Name: "lcaron", CodePoints: []int{318}, Characters: []byte{0xc4, 0xbe}},
+ "lcedil": {Name: "lcedil", CodePoints: []int{316}, Characters: []byte{0xc4, 0xbc}},
+ "lceil": {Name: "lceil", CodePoints: []int{8968}, Characters: []byte{0xe2, 0x8c, 0x88}},
+ "lcub": {Name: "lcub", CodePoints: []int{123}, Characters: []byte{0x7b}},
+ "lcy": {Name: "lcy", CodePoints: []int{1083}, Characters: []byte{0xd0, 0xbb}},
+ "ldca": {Name: "ldca", CodePoints: []int{10550}, Characters: []byte{0xe2, 0xa4, 0xb6}},
+ "ldquo": {Name: "ldquo", CodePoints: []int{8220}, Characters: []byte{0xe2, 0x80, 0x9c}},
+ "ldquor": {Name: "ldquor", CodePoints: []int{8222}, Characters: []byte{0xe2, 0x80, 0x9e}},
+ "ldrdhar": {Name: "ldrdhar", CodePoints: []int{10599}, Characters: []byte{0xe2, 0xa5, 0xa7}},
+ "ldrushar": {Name: "ldrushar", CodePoints: []int{10571}, Characters: []byte{0xe2, 0xa5, 0x8b}},
+ "ldsh": {Name: "ldsh", CodePoints: []int{8626}, Characters: []byte{0xe2, 0x86, 0xb2}},
+ "le": {Name: "le", CodePoints: []int{8804}, Characters: []byte{0xe2, 0x89, 0xa4}},
+ "leftarrow": {Name: "leftarrow", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
+ "leftarrowtail": {Name: "leftarrowtail", CodePoints: []int{8610}, Characters: []byte{0xe2, 0x86, 0xa2}},
+ "leftharpoondown": {Name: "leftharpoondown", CodePoints: []int{8637}, Characters: []byte{0xe2, 0x86, 0xbd}},
+ "leftharpoonup": {Name: "leftharpoonup", CodePoints: []int{8636}, Characters: []byte{0xe2, 0x86, 0xbc}},
+ "leftleftarrows": {Name: "leftleftarrows", CodePoints: []int{8647}, Characters: []byte{0xe2, 0x87, 0x87}},
+ "leftrightarrow": {Name: "leftrightarrow", CodePoints: []int{8596}, Characters: []byte{0xe2, 0x86, 0x94}},
+ "leftrightarrows": {Name: "leftrightarrows", CodePoints: []int{8646}, Characters: []byte{0xe2, 0x87, 0x86}},
+ "leftrightharpoons": {Name: "leftrightharpoons", CodePoints: []int{8651}, Characters: []byte{0xe2, 0x87, 0x8b}},
+ "leftrightsquigarrow": {Name: "leftrightsquigarrow", CodePoints: []int{8621}, Characters: []byte{0xe2, 0x86, 0xad}},
+ "leftthreetimes": {Name: "leftthreetimes", CodePoints: []int{8907}, Characters: []byte{0xe2, 0x8b, 0x8b}},
+ "leg": {Name: "leg", CodePoints: []int{8922}, Characters: []byte{0xe2, 0x8b, 0x9a}},
+ "leq": {Name: "leq", CodePoints: []int{8804}, Characters: []byte{0xe2, 0x89, 0xa4}},
+ "leqq": {Name: "leqq", CodePoints: []int{8806}, Characters: []byte{0xe2, 0x89, 0xa6}},
+ "leqslant": {Name: "leqslant", CodePoints: []int{10877}, Characters: []byte{0xe2, 0xa9, 0xbd}},
+ "les": {Name: "les", CodePoints: []int{10877}, Characters: []byte{0xe2, 0xa9, 0xbd}},
+ "lescc": {Name: "lescc", CodePoints: []int{10920}, Characters: []byte{0xe2, 0xaa, 0xa8}},
+ "lesdot": {Name: "lesdot", CodePoints: []int{10879}, Characters: []byte{0xe2, 0xa9, 0xbf}},
+ "lesdoto": {Name: "lesdoto", CodePoints: []int{10881}, Characters: []byte{0xe2, 0xaa, 0x81}},
+ "lesdotor": {Name: "lesdotor", CodePoints: []int{10883}, Characters: []byte{0xe2, 0xaa, 0x83}},
+ "lesg": {Name: "lesg", CodePoints: []int{8922, 65024}, Characters: []byte{0xe2, 0x8b, 0x9a, 0xef, 0xb8, 0x80}},
+ "lesges": {Name: "lesges", CodePoints: []int{10899}, Characters: []byte{0xe2, 0xaa, 0x93}},
+ "lessapprox": {Name: "lessapprox", CodePoints: []int{10885}, Characters: []byte{0xe2, 0xaa, 0x85}},
+ "lessdot": {Name: "lessdot", CodePoints: []int{8918}, Characters: []byte{0xe2, 0x8b, 0x96}},
+ "lesseqgtr": {Name: "lesseqgtr", CodePoints: []int{8922}, Characters: []byte{0xe2, 0x8b, 0x9a}},
+ "lesseqqgtr": {Name: "lesseqqgtr", CodePoints: []int{10891}, Characters: []byte{0xe2, 0xaa, 0x8b}},
+ "lessgtr": {Name: "lessgtr", CodePoints: []int{8822}, Characters: []byte{0xe2, 0x89, 0xb6}},
+ "lesssim": {Name: "lesssim", CodePoints: []int{8818}, Characters: []byte{0xe2, 0x89, 0xb2}},
+ "lfisht": {Name: "lfisht", CodePoints: []int{10620}, Characters: []byte{0xe2, 0xa5, 0xbc}},
+ "lfloor": {Name: "lfloor", CodePoints: []int{8970}, Characters: []byte{0xe2, 0x8c, 0x8a}},
+ "lfr": {Name: "lfr", CodePoints: []int{120105}, Characters: []byte{0xf0, 0x9d, 0x94, 0xa9}},
+ "lg": {Name: "lg", CodePoints: []int{8822}, Characters: []byte{0xe2, 0x89, 0xb6}},
+ "lgE": {Name: "lgE", CodePoints: []int{10897}, Characters: []byte{0xe2, 0xaa, 0x91}},
+ "lhard": {Name: "lhard", CodePoints: []int{8637}, Characters: []byte{0xe2, 0x86, 0xbd}},
+ "lharu": {Name: "lharu", CodePoints: []int{8636}, Characters: []byte{0xe2, 0x86, 0xbc}},
+ "lharul": {Name: "lharul", CodePoints: []int{10602}, Characters: []byte{0xe2, 0xa5, 0xaa}},
+ "lhblk": {Name: "lhblk", CodePoints: []int{9604}, Characters: []byte{0xe2, 0x96, 0x84}},
+ "ljcy": {Name: "ljcy", CodePoints: []int{1113}, Characters: []byte{0xd1, 0x99}},
+ "ll": {Name: "ll", CodePoints: []int{8810}, Characters: []byte{0xe2, 0x89, 0xaa}},
+ "llarr": {Name: "llarr", CodePoints: []int{8647}, Characters: []byte{0xe2, 0x87, 0x87}},
+ "llcorner": {Name: "llcorner", CodePoints: []int{8990}, Characters: []byte{0xe2, 0x8c, 0x9e}},
+ "llhard": {Name: "llhard", CodePoints: []int{10603}, Characters: []byte{0xe2, 0xa5, 0xab}},
+ "lltri": {Name: "lltri", CodePoints: []int{9722}, Characters: []byte{0xe2, 0x97, 0xba}},
+ "lmidot": {Name: "lmidot", CodePoints: []int{320}, Characters: []byte{0xc5, 0x80}},
+ "lmoust": {Name: "lmoust", CodePoints: []int{9136}, Characters: []byte{0xe2, 0x8e, 0xb0}},
+ "lmoustache": {Name: "lmoustache", CodePoints: []int{9136}, Characters: []byte{0xe2, 0x8e, 0xb0}},
+ "lnE": {Name: "lnE", CodePoints: []int{8808}, Characters: []byte{0xe2, 0x89, 0xa8}},
+ "lnap": {Name: "lnap", CodePoints: []int{10889}, Characters: []byte{0xe2, 0xaa, 0x89}},
+ "lnapprox": {Name: "lnapprox", CodePoints: []int{10889}, Characters: []byte{0xe2, 0xaa, 0x89}},
+ "lne": {Name: "lne", CodePoints: []int{10887}, Characters: []byte{0xe2, 0xaa, 0x87}},
+ "lneq": {Name: "lneq", CodePoints: []int{10887}, Characters: []byte{0xe2, 0xaa, 0x87}},
+ "lneqq": {Name: "lneqq", CodePoints: []int{8808}, Characters: []byte{0xe2, 0x89, 0xa8}},
+ "lnsim": {Name: "lnsim", CodePoints: []int{8934}, Characters: []byte{0xe2, 0x8b, 0xa6}},
+ "loang": {Name: "loang", CodePoints: []int{10220}, Characters: []byte{0xe2, 0x9f, 0xac}},
+ "loarr": {Name: "loarr", CodePoints: []int{8701}, Characters: []byte{0xe2, 0x87, 0xbd}},
+ "lobrk": {Name: "lobrk", CodePoints: []int{10214}, Characters: []byte{0xe2, 0x9f, 0xa6}},
+ "longleftarrow": {Name: "longleftarrow", CodePoints: []int{10229}, Characters: []byte{0xe2, 0x9f, 0xb5}},
+ "longleftrightarrow": {Name: "longleftrightarrow", CodePoints: []int{10231}, Characters: []byte{0xe2, 0x9f, 0xb7}},
+ "longmapsto": {Name: "longmapsto", CodePoints: []int{10236}, Characters: []byte{0xe2, 0x9f, 0xbc}},
+ "longrightarrow": {Name: "longrightarrow", CodePoints: []int{10230}, Characters: []byte{0xe2, 0x9f, 0xb6}},
+ "looparrowleft": {Name: "looparrowleft", CodePoints: []int{8619}, Characters: []byte{0xe2, 0x86, 0xab}},
+ "looparrowright": {Name: "looparrowright", CodePoints: []int{8620}, Characters: []byte{0xe2, 0x86, 0xac}},
+ "lopar": {Name: "lopar", CodePoints: []int{10629}, Characters: []byte{0xe2, 0xa6, 0x85}},
+ "lopf": {Name: "lopf", CodePoints: []int{120157}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9d}},
+ "loplus": {Name: "loplus", CodePoints: []int{10797}, Characters: []byte{0xe2, 0xa8, 0xad}},
+ "lotimes": {Name: "lotimes", CodePoints: []int{10804}, Characters: []byte{0xe2, 0xa8, 0xb4}},
+ "lowast": {Name: "lowast", CodePoints: []int{8727}, Characters: []byte{0xe2, 0x88, 0x97}},
+ "lowbar": {Name: "lowbar", CodePoints: []int{95}, Characters: []byte{0x5f}},
+ "loz": {Name: "loz", CodePoints: []int{9674}, Characters: []byte{0xe2, 0x97, 0x8a}},
+ "lozenge": {Name: "lozenge", CodePoints: []int{9674}, Characters: []byte{0xe2, 0x97, 0x8a}},
+ "lozf": {Name: "lozf", CodePoints: []int{10731}, Characters: []byte{0xe2, 0xa7, 0xab}},
+ "lpar": {Name: "lpar", CodePoints: []int{40}, Characters: []byte{0x28}},
+ "lparlt": {Name: "lparlt", CodePoints: []int{10643}, Characters: []byte{0xe2, 0xa6, 0x93}},
+ "lrarr": {Name: "lrarr", CodePoints: []int{8646}, Characters: []byte{0xe2, 0x87, 0x86}},
+ "lrcorner": {Name: "lrcorner", CodePoints: []int{8991}, Characters: []byte{0xe2, 0x8c, 0x9f}},
+ "lrhar": {Name: "lrhar", CodePoints: []int{8651}, Characters: []byte{0xe2, 0x87, 0x8b}},
+ "lrhard": {Name: "lrhard", CodePoints: []int{10605}, Characters: []byte{0xe2, 0xa5, 0xad}},
+ "lrm": {Name: "lrm", CodePoints: []int{8206}, Characters: []byte{0xe2, 0x80, 0x8e}},
+ "lrtri": {Name: "lrtri", CodePoints: []int{8895}, Characters: []byte{0xe2, 0x8a, 0xbf}},
+ "lsaquo": {Name: "lsaquo", CodePoints: []int{8249}, Characters: []byte{0xe2, 0x80, 0xb9}},
+ "lscr": {Name: "lscr", CodePoints: []int{120001}, Characters: []byte{0xf0, 0x9d, 0x93, 0x81}},
+ "lsh": {Name: "lsh", CodePoints: []int{8624}, Characters: []byte{0xe2, 0x86, 0xb0}},
+ "lsim": {Name: "lsim", CodePoints: []int{8818}, Characters: []byte{0xe2, 0x89, 0xb2}},
+ "lsime": {Name: "lsime", CodePoints: []int{10893}, Characters: []byte{0xe2, 0xaa, 0x8d}},
+ "lsimg": {Name: "lsimg", CodePoints: []int{10895}, Characters: []byte{0xe2, 0xaa, 0x8f}},
+ "lsqb": {Name: "lsqb", CodePoints: []int{91}, Characters: []byte{0x5b}},
+ "lsquo": {Name: "lsquo", CodePoints: []int{8216}, Characters: []byte{0xe2, 0x80, 0x98}},
+ "lsquor": {Name: "lsquor", CodePoints: []int{8218}, Characters: []byte{0xe2, 0x80, 0x9a}},
+ "lstrok": {Name: "lstrok", CodePoints: []int{322}, Characters: []byte{0xc5, 0x82}},
+ "lt": {Name: "lt", CodePoints: []int{60}, Characters: []byte{0x3c}},
+ "ltcc": {Name: "ltcc", CodePoints: []int{10918}, Characters: []byte{0xe2, 0xaa, 0xa6}},
+ "ltcir": {Name: "ltcir", CodePoints: []int{10873}, Characters: []byte{0xe2, 0xa9, 0xb9}},
+ "ltdot": {Name: "ltdot", CodePoints: []int{8918}, Characters: []byte{0xe2, 0x8b, 0x96}},
+ "lthree": {Name: "lthree", CodePoints: []int{8907}, Characters: []byte{0xe2, 0x8b, 0x8b}},
+ "ltimes": {Name: "ltimes", CodePoints: []int{8905}, Characters: []byte{0xe2, 0x8b, 0x89}},
+ "ltlarr": {Name: "ltlarr", CodePoints: []int{10614}, Characters: []byte{0xe2, 0xa5, 0xb6}},
+ "ltquest": {Name: "ltquest", CodePoints: []int{10875}, Characters: []byte{0xe2, 0xa9, 0xbb}},
+ "ltrPar": {Name: "ltrPar", CodePoints: []int{10646}, Characters: []byte{0xe2, 0xa6, 0x96}},
+ "ltri": {Name: "ltri", CodePoints: []int{9667}, Characters: []byte{0xe2, 0x97, 0x83}},
+ "ltrie": {Name: "ltrie", CodePoints: []int{8884}, Characters: []byte{0xe2, 0x8a, 0xb4}},
+ "ltrif": {Name: "ltrif", CodePoints: []int{9666}, Characters: []byte{0xe2, 0x97, 0x82}},
+ "lurdshar": {Name: "lurdshar", CodePoints: []int{10570}, Characters: []byte{0xe2, 0xa5, 0x8a}},
+ "luruhar": {Name: "luruhar", CodePoints: []int{10598}, Characters: []byte{0xe2, 0xa5, 0xa6}},
+ "lvertneqq": {Name: "lvertneqq", CodePoints: []int{8808, 65024}, Characters: []byte{0xe2, 0x89, 0xa8, 0xef, 0xb8, 0x80}},
+ "lvnE": {Name: "lvnE", CodePoints: []int{8808, 65024}, Characters: []byte{0xe2, 0x89, 0xa8, 0xef, 0xb8, 0x80}},
+ "mDDot": {Name: "mDDot", CodePoints: []int{8762}, Characters: []byte{0xe2, 0x88, 0xba}},
+ "macr": {Name: "macr", CodePoints: []int{175}, Characters: []byte{0xc2, 0xaf}},
+ "male": {Name: "male", CodePoints: []int{9794}, Characters: []byte{0xe2, 0x99, 0x82}},
+ "malt": {Name: "malt", CodePoints: []int{10016}, Characters: []byte{0xe2, 0x9c, 0xa0}},
+ "maltese": {Name: "maltese", CodePoints: []int{10016}, Characters: []byte{0xe2, 0x9c, 0xa0}},
+ "map": {Name: "map", CodePoints: []int{8614}, Characters: []byte{0xe2, 0x86, 0xa6}},
+ "mapsto": {Name: "mapsto", CodePoints: []int{8614}, Characters: []byte{0xe2, 0x86, 0xa6}},
+ "mapstodown": {Name: "mapstodown", CodePoints: []int{8615}, Characters: []byte{0xe2, 0x86, 0xa7}},
+ "mapstoleft": {Name: "mapstoleft", CodePoints: []int{8612}, Characters: []byte{0xe2, 0x86, 0xa4}},
+ "mapstoup": {Name: "mapstoup", CodePoints: []int{8613}, Characters: []byte{0xe2, 0x86, 0xa5}},
+ "marker": {Name: "marker", CodePoints: []int{9646}, Characters: []byte{0xe2, 0x96, 0xae}},
+ "mcomma": {Name: "mcomma", CodePoints: []int{10793}, Characters: []byte{0xe2, 0xa8, 0xa9}},
+ "mcy": {Name: "mcy", CodePoints: []int{1084}, Characters: []byte{0xd0, 0xbc}},
+ "mdash": {Name: "mdash", CodePoints: []int{8212}, Characters: []byte{0xe2, 0x80, 0x94}},
+ "measuredangle": {Name: "measuredangle", CodePoints: []int{8737}, Characters: []byte{0xe2, 0x88, 0xa1}},
+ "mfr": {Name: "mfr", CodePoints: []int{120106}, Characters: []byte{0xf0, 0x9d, 0x94, 0xaa}},
+ "mho": {Name: "mho", CodePoints: []int{8487}, Characters: []byte{0xe2, 0x84, 0xa7}},
+ "micro": {Name: "micro", CodePoints: []int{181}, Characters: []byte{0xc2, 0xb5}},
+ "mid": {Name: "mid", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
+ "midast": {Name: "midast", CodePoints: []int{42}, Characters: []byte{0x2a}},
+ "midcir": {Name: "midcir", CodePoints: []int{10992}, Characters: []byte{0xe2, 0xab, 0xb0}},
+ "middot": {Name: "middot", CodePoints: []int{183}, Characters: []byte{0xc2, 0xb7}},
+ "minus": {Name: "minus", CodePoints: []int{8722}, Characters: []byte{0xe2, 0x88, 0x92}},
+ "minusb": {Name: "minusb", CodePoints: []int{8863}, Characters: []byte{0xe2, 0x8a, 0x9f}},
+ "minusd": {Name: "minusd", CodePoints: []int{8760}, Characters: []byte{0xe2, 0x88, 0xb8}},
+ "minusdu": {Name: "minusdu", CodePoints: []int{10794}, Characters: []byte{0xe2, 0xa8, 0xaa}},
+ "mlcp": {Name: "mlcp", CodePoints: []int{10971}, Characters: []byte{0xe2, 0xab, 0x9b}},
+ "mldr": {Name: "mldr", CodePoints: []int{8230}, Characters: []byte{0xe2, 0x80, 0xa6}},
+ "mnplus": {Name: "mnplus", CodePoints: []int{8723}, Characters: []byte{0xe2, 0x88, 0x93}},
+ "models": {Name: "models", CodePoints: []int{8871}, Characters: []byte{0xe2, 0x8a, 0xa7}},
+ "mopf": {Name: "mopf", CodePoints: []int{120158}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9e}},
+ "mp": {Name: "mp", CodePoints: []int{8723}, Characters: []byte{0xe2, 0x88, 0x93}},
+ "mscr": {Name: "mscr", CodePoints: []int{120002}, Characters: []byte{0xf0, 0x9d, 0x93, 0x82}},
+ "mstpos": {Name: "mstpos", CodePoints: []int{8766}, Characters: []byte{0xe2, 0x88, 0xbe}},
+ "mu": {Name: "mu", CodePoints: []int{956}, Characters: []byte{0xce, 0xbc}},
+ "multimap": {Name: "multimap", CodePoints: []int{8888}, Characters: []byte{0xe2, 0x8a, 0xb8}},
+ "mumap": {Name: "mumap", CodePoints: []int{8888}, Characters: []byte{0xe2, 0x8a, 0xb8}},
+ "nGg": {Name: "nGg", CodePoints: []int{8921, 824}, Characters: []byte{0xe2, 0x8b, 0x99, 0xcc, 0xb8}},
+ "nGt": {Name: "nGt", CodePoints: []int{8811, 8402}, Characters: []byte{0xe2, 0x89, 0xab, 0xe2, 0x83, 0x92}},
+ "nGtv": {Name: "nGtv", CodePoints: []int{8811, 824}, Characters: []byte{0xe2, 0x89, 0xab, 0xcc, 0xb8}},
+ "nLeftarrow": {Name: "nLeftarrow", CodePoints: []int{8653}, Characters: []byte{0xe2, 0x87, 0x8d}},
+ "nLeftrightarrow": {Name: "nLeftrightarrow", CodePoints: []int{8654}, Characters: []byte{0xe2, 0x87, 0x8e}},
+ "nLl": {Name: "nLl", CodePoints: []int{8920, 824}, Characters: []byte{0xe2, 0x8b, 0x98, 0xcc, 0xb8}},
+ "nLt": {Name: "nLt", CodePoints: []int{8810, 8402}, Characters: []byte{0xe2, 0x89, 0xaa, 0xe2, 0x83, 0x92}},
+ "nLtv": {Name: "nLtv", CodePoints: []int{8810, 824}, Characters: []byte{0xe2, 0x89, 0xaa, 0xcc, 0xb8}},
+ "nRightarrow": {Name: "nRightarrow", CodePoints: []int{8655}, Characters: []byte{0xe2, 0x87, 0x8f}},
+ "nVDash": {Name: "nVDash", CodePoints: []int{8879}, Characters: []byte{0xe2, 0x8a, 0xaf}},
+ "nVdash": {Name: "nVdash", CodePoints: []int{8878}, Characters: []byte{0xe2, 0x8a, 0xae}},
+ "nabla": {Name: "nabla", CodePoints: []int{8711}, Characters: []byte{0xe2, 0x88, 0x87}},
+ "nacute": {Name: "nacute", CodePoints: []int{324}, Characters: []byte{0xc5, 0x84}},
+ "nang": {Name: "nang", CodePoints: []int{8736, 8402}, Characters: []byte{0xe2, 0x88, 0xa0, 0xe2, 0x83, 0x92}},
+ "nap": {Name: "nap", CodePoints: []int{8777}, Characters: []byte{0xe2, 0x89, 0x89}},
+ "napE": {Name: "napE", CodePoints: []int{10864, 824}, Characters: []byte{0xe2, 0xa9, 0xb0, 0xcc, 0xb8}},
+ "napid": {Name: "napid", CodePoints: []int{8779, 824}, Characters: []byte{0xe2, 0x89, 0x8b, 0xcc, 0xb8}},
+ "napos": {Name: "napos", CodePoints: []int{329}, Characters: []byte{0xc5, 0x89}},
+ "napprox": {Name: "napprox", CodePoints: []int{8777}, Characters: []byte{0xe2, 0x89, 0x89}},
+ "natur": {Name: "natur", CodePoints: []int{9838}, Characters: []byte{0xe2, 0x99, 0xae}},
+ "natural": {Name: "natural", CodePoints: []int{9838}, Characters: []byte{0xe2, 0x99, 0xae}},
+ "naturals": {Name: "naturals", CodePoints: []int{8469}, Characters: []byte{0xe2, 0x84, 0x95}},
+ "nbsp": {Name: "nbsp", CodePoints: []int{160}, Characters: []byte{0xc2, 0xa0}},
+ "nbump": {Name: "nbump", CodePoints: []int{8782, 824}, Characters: []byte{0xe2, 0x89, 0x8e, 0xcc, 0xb8}},
+ "nbumpe": {Name: "nbumpe", CodePoints: []int{8783, 824}, Characters: []byte{0xe2, 0x89, 0x8f, 0xcc, 0xb8}},
+ "ncap": {Name: "ncap", CodePoints: []int{10819}, Characters: []byte{0xe2, 0xa9, 0x83}},
+ "ncaron": {Name: "ncaron", CodePoints: []int{328}, Characters: []byte{0xc5, 0x88}},
+ "ncedil": {Name: "ncedil", CodePoints: []int{326}, Characters: []byte{0xc5, 0x86}},
+ "ncong": {Name: "ncong", CodePoints: []int{8775}, Characters: []byte{0xe2, 0x89, 0x87}},
+ "ncongdot": {Name: "ncongdot", CodePoints: []int{10861, 824}, Characters: []byte{0xe2, 0xa9, 0xad, 0xcc, 0xb8}},
+ "ncup": {Name: "ncup", CodePoints: []int{10818}, Characters: []byte{0xe2, 0xa9, 0x82}},
+ "ncy": {Name: "ncy", CodePoints: []int{1085}, Characters: []byte{0xd0, 0xbd}},
+ "ndash": {Name: "ndash", CodePoints: []int{8211}, Characters: []byte{0xe2, 0x80, 0x93}},
+ "ne": {Name: "ne", CodePoints: []int{8800}, Characters: []byte{0xe2, 0x89, 0xa0}},
+ "neArr": {Name: "neArr", CodePoints: []int{8663}, Characters: []byte{0xe2, 0x87, 0x97}},
+ "nearhk": {Name: "nearhk", CodePoints: []int{10532}, Characters: []byte{0xe2, 0xa4, 0xa4}},
+ "nearr": {Name: "nearr", CodePoints: []int{8599}, Characters: []byte{0xe2, 0x86, 0x97}},
+ "nearrow": {Name: "nearrow", CodePoints: []int{8599}, Characters: []byte{0xe2, 0x86, 0x97}},
+ "nedot": {Name: "nedot", CodePoints: []int{8784, 824}, Characters: []byte{0xe2, 0x89, 0x90, 0xcc, 0xb8}},
+ "nequiv": {Name: "nequiv", CodePoints: []int{8802}, Characters: []byte{0xe2, 0x89, 0xa2}},
+ "nesear": {Name: "nesear", CodePoints: []int{10536}, Characters: []byte{0xe2, 0xa4, 0xa8}},
+ "nesim": {Name: "nesim", CodePoints: []int{8770, 824}, Characters: []byte{0xe2, 0x89, 0x82, 0xcc, 0xb8}},
+ "nexist": {Name: "nexist", CodePoints: []int{8708}, Characters: []byte{0xe2, 0x88, 0x84}},
+ "nexists": {Name: "nexists", CodePoints: []int{8708}, Characters: []byte{0xe2, 0x88, 0x84}},
+ "nfr": {Name: "nfr", CodePoints: []int{120107}, Characters: []byte{0xf0, 0x9d, 0x94, 0xab}},
+ "ngE": {Name: "ngE", CodePoints: []int{8807, 824}, Characters: []byte{0xe2, 0x89, 0xa7, 0xcc, 0xb8}},
+ "nge": {Name: "nge", CodePoints: []int{8817}, Characters: []byte{0xe2, 0x89, 0xb1}},
+ "ngeq": {Name: "ngeq", CodePoints: []int{8817}, Characters: []byte{0xe2, 0x89, 0xb1}},
+ "ngeqq": {Name: "ngeqq", CodePoints: []int{8807, 824}, Characters: []byte{0xe2, 0x89, 0xa7, 0xcc, 0xb8}},
+ "ngeqslant": {Name: "ngeqslant", CodePoints: []int{10878, 824}, Characters: []byte{0xe2, 0xa9, 0xbe, 0xcc, 0xb8}},
+ "nges": {Name: "nges", CodePoints: []int{10878, 824}, Characters: []byte{0xe2, 0xa9, 0xbe, 0xcc, 0xb8}},
+ "ngsim": {Name: "ngsim", CodePoints: []int{8821}, Characters: []byte{0xe2, 0x89, 0xb5}},
+ "ngt": {Name: "ngt", CodePoints: []int{8815}, Characters: []byte{0xe2, 0x89, 0xaf}},
+ "ngtr": {Name: "ngtr", CodePoints: []int{8815}, Characters: []byte{0xe2, 0x89, 0xaf}},
+ "nhArr": {Name: "nhArr", CodePoints: []int{8654}, Characters: []byte{0xe2, 0x87, 0x8e}},
+ "nharr": {Name: "nharr", CodePoints: []int{8622}, Characters: []byte{0xe2, 0x86, 0xae}},
+ "nhpar": {Name: "nhpar", CodePoints: []int{10994}, Characters: []byte{0xe2, 0xab, 0xb2}},
+ "ni": {Name: "ni", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
+ "nis": {Name: "nis", CodePoints: []int{8956}, Characters: []byte{0xe2, 0x8b, 0xbc}},
+ "nisd": {Name: "nisd", CodePoints: []int{8954}, Characters: []byte{0xe2, 0x8b, 0xba}},
+ "niv": {Name: "niv", CodePoints: []int{8715}, Characters: []byte{0xe2, 0x88, 0x8b}},
+ "njcy": {Name: "njcy", CodePoints: []int{1114}, Characters: []byte{0xd1, 0x9a}},
+ "nlArr": {Name: "nlArr", CodePoints: []int{8653}, Characters: []byte{0xe2, 0x87, 0x8d}},
+ "nlE": {Name: "nlE", CodePoints: []int{8806, 824}, Characters: []byte{0xe2, 0x89, 0xa6, 0xcc, 0xb8}},
+ "nlarr": {Name: "nlarr", CodePoints: []int{8602}, Characters: []byte{0xe2, 0x86, 0x9a}},
+ "nldr": {Name: "nldr", CodePoints: []int{8229}, Characters: []byte{0xe2, 0x80, 0xa5}},
+ "nle": {Name: "nle", CodePoints: []int{8816}, Characters: []byte{0xe2, 0x89, 0xb0}},
+ "nleftarrow": {Name: "nleftarrow", CodePoints: []int{8602}, Characters: []byte{0xe2, 0x86, 0x9a}},
+ "nleftrightarrow": {Name: "nleftrightarrow", CodePoints: []int{8622}, Characters: []byte{0xe2, 0x86, 0xae}},
+ "nleq": {Name: "nleq", CodePoints: []int{8816}, Characters: []byte{0xe2, 0x89, 0xb0}},
+ "nleqq": {Name: "nleqq", CodePoints: []int{8806, 824}, Characters: []byte{0xe2, 0x89, 0xa6, 0xcc, 0xb8}},
+ "nleqslant": {Name: "nleqslant", CodePoints: []int{10877, 824}, Characters: []byte{0xe2, 0xa9, 0xbd, 0xcc, 0xb8}},
+ "nles": {Name: "nles", CodePoints: []int{10877, 824}, Characters: []byte{0xe2, 0xa9, 0xbd, 0xcc, 0xb8}},
+ "nless": {Name: "nless", CodePoints: []int{8814}, Characters: []byte{0xe2, 0x89, 0xae}},
+ "nlsim": {Name: "nlsim", CodePoints: []int{8820}, Characters: []byte{0xe2, 0x89, 0xb4}},
+ "nlt": {Name: "nlt", CodePoints: []int{8814}, Characters: []byte{0xe2, 0x89, 0xae}},
+ "nltri": {Name: "nltri", CodePoints: []int{8938}, Characters: []byte{0xe2, 0x8b, 0xaa}},
+ "nltrie": {Name: "nltrie", CodePoints: []int{8940}, Characters: []byte{0xe2, 0x8b, 0xac}},
+ "nmid": {Name: "nmid", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
+ "nopf": {Name: "nopf", CodePoints: []int{120159}, Characters: []byte{0xf0, 0x9d, 0x95, 0x9f}},
+ "not": {Name: "not", CodePoints: []int{172}, Characters: []byte{0xc2, 0xac}},
+ "notin": {Name: "notin", CodePoints: []int{8713}, Characters: []byte{0xe2, 0x88, 0x89}},
+ "notinE": {Name: "notinE", CodePoints: []int{8953, 824}, Characters: []byte{0xe2, 0x8b, 0xb9, 0xcc, 0xb8}},
+ "notindot": {Name: "notindot", CodePoints: []int{8949, 824}, Characters: []byte{0xe2, 0x8b, 0xb5, 0xcc, 0xb8}},
+ "notinva": {Name: "notinva", CodePoints: []int{8713}, Characters: []byte{0xe2, 0x88, 0x89}},
+ "notinvb": {Name: "notinvb", CodePoints: []int{8951}, Characters: []byte{0xe2, 0x8b, 0xb7}},
+ "notinvc": {Name: "notinvc", CodePoints: []int{8950}, Characters: []byte{0xe2, 0x8b, 0xb6}},
+ "notni": {Name: "notni", CodePoints: []int{8716}, Characters: []byte{0xe2, 0x88, 0x8c}},
+ "notniva": {Name: "notniva", CodePoints: []int{8716}, Characters: []byte{0xe2, 0x88, 0x8c}},
+ "notnivb": {Name: "notnivb", CodePoints: []int{8958}, Characters: []byte{0xe2, 0x8b, 0xbe}},
+ "notnivc": {Name: "notnivc", CodePoints: []int{8957}, Characters: []byte{0xe2, 0x8b, 0xbd}},
+ "npar": {Name: "npar", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
+ "nparallel": {Name: "nparallel", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
+ "nparsl": {Name: "nparsl", CodePoints: []int{11005, 8421}, Characters: []byte{0xe2, 0xab, 0xbd, 0xe2, 0x83, 0xa5}},
+ "npart": {Name: "npart", CodePoints: []int{8706, 824}, Characters: []byte{0xe2, 0x88, 0x82, 0xcc, 0xb8}},
+ "npolint": {Name: "npolint", CodePoints: []int{10772}, Characters: []byte{0xe2, 0xa8, 0x94}},
+ "npr": {Name: "npr", CodePoints: []int{8832}, Characters: []byte{0xe2, 0x8a, 0x80}},
+ "nprcue": {Name: "nprcue", CodePoints: []int{8928}, Characters: []byte{0xe2, 0x8b, 0xa0}},
+ "npre": {Name: "npre", CodePoints: []int{10927, 824}, Characters: []byte{0xe2, 0xaa, 0xaf, 0xcc, 0xb8}},
+ "nprec": {Name: "nprec", CodePoints: []int{8832}, Characters: []byte{0xe2, 0x8a, 0x80}},
+ "npreceq": {Name: "npreceq", CodePoints: []int{10927, 824}, Characters: []byte{0xe2, 0xaa, 0xaf, 0xcc, 0xb8}},
+ "nrArr": {Name: "nrArr", CodePoints: []int{8655}, Characters: []byte{0xe2, 0x87, 0x8f}},
+ "nrarr": {Name: "nrarr", CodePoints: []int{8603}, Characters: []byte{0xe2, 0x86, 0x9b}},
+ "nrarrc": {Name: "nrarrc", CodePoints: []int{10547, 824}, Characters: []byte{0xe2, 0xa4, 0xb3, 0xcc, 0xb8}},
+ "nrarrw": {Name: "nrarrw", CodePoints: []int{8605, 824}, Characters: []byte{0xe2, 0x86, 0x9d, 0xcc, 0xb8}},
+ "nrightarrow": {Name: "nrightarrow", CodePoints: []int{8603}, Characters: []byte{0xe2, 0x86, 0x9b}},
+ "nrtri": {Name: "nrtri", CodePoints: []int{8939}, Characters: []byte{0xe2, 0x8b, 0xab}},
+ "nrtrie": {Name: "nrtrie", CodePoints: []int{8941}, Characters: []byte{0xe2, 0x8b, 0xad}},
+ "nsc": {Name: "nsc", CodePoints: []int{8833}, Characters: []byte{0xe2, 0x8a, 0x81}},
+ "nsccue": {Name: "nsccue", CodePoints: []int{8929}, Characters: []byte{0xe2, 0x8b, 0xa1}},
+ "nsce": {Name: "nsce", CodePoints: []int{10928, 824}, Characters: []byte{0xe2, 0xaa, 0xb0, 0xcc, 0xb8}},
+ "nscr": {Name: "nscr", CodePoints: []int{120003}, Characters: []byte{0xf0, 0x9d, 0x93, 0x83}},
+ "nshortmid": {Name: "nshortmid", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
+ "nshortparallel": {Name: "nshortparallel", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
+ "nsim": {Name: "nsim", CodePoints: []int{8769}, Characters: []byte{0xe2, 0x89, 0x81}},
+ "nsime": {Name: "nsime", CodePoints: []int{8772}, Characters: []byte{0xe2, 0x89, 0x84}},
+ "nsimeq": {Name: "nsimeq", CodePoints: []int{8772}, Characters: []byte{0xe2, 0x89, 0x84}},
+ "nsmid": {Name: "nsmid", CodePoints: []int{8740}, Characters: []byte{0xe2, 0x88, 0xa4}},
+ "nspar": {Name: "nspar", CodePoints: []int{8742}, Characters: []byte{0xe2, 0x88, 0xa6}},
+ "nsqsube": {Name: "nsqsube", CodePoints: []int{8930}, Characters: []byte{0xe2, 0x8b, 0xa2}},
+ "nsqsupe": {Name: "nsqsupe", CodePoints: []int{8931}, Characters: []byte{0xe2, 0x8b, 0xa3}},
+ "nsub": {Name: "nsub", CodePoints: []int{8836}, Characters: []byte{0xe2, 0x8a, 0x84}},
+ "nsubE": {Name: "nsubE", CodePoints: []int{10949, 824}, Characters: []byte{0xe2, 0xab, 0x85, 0xcc, 0xb8}},
+ "nsube": {Name: "nsube", CodePoints: []int{8840}, Characters: []byte{0xe2, 0x8a, 0x88}},
+ "nsubset": {Name: "nsubset", CodePoints: []int{8834, 8402}, Characters: []byte{0xe2, 0x8a, 0x82, 0xe2, 0x83, 0x92}},
+ "nsubseteq": {Name: "nsubseteq", CodePoints: []int{8840}, Characters: []byte{0xe2, 0x8a, 0x88}},
+ "nsubseteqq": {Name: "nsubseteqq", CodePoints: []int{10949, 824}, Characters: []byte{0xe2, 0xab, 0x85, 0xcc, 0xb8}},
+ "nsucc": {Name: "nsucc", CodePoints: []int{8833}, Characters: []byte{0xe2, 0x8a, 0x81}},
+ "nsucceq": {Name: "nsucceq", CodePoints: []int{10928, 824}, Characters: []byte{0xe2, 0xaa, 0xb0, 0xcc, 0xb8}},
+ "nsup": {Name: "nsup", CodePoints: []int{8837}, Characters: []byte{0xe2, 0x8a, 0x85}},
+ "nsupE": {Name: "nsupE", CodePoints: []int{10950, 824}, Characters: []byte{0xe2, 0xab, 0x86, 0xcc, 0xb8}},
+ "nsupe": {Name: "nsupe", CodePoints: []int{8841}, Characters: []byte{0xe2, 0x8a, 0x89}},
+ "nsupset": {Name: "nsupset", CodePoints: []int{8835, 8402}, Characters: []byte{0xe2, 0x8a, 0x83, 0xe2, 0x83, 0x92}},
+ "nsupseteq": {Name: "nsupseteq", CodePoints: []int{8841}, Characters: []byte{0xe2, 0x8a, 0x89}},
+ "nsupseteqq": {Name: "nsupseteqq", CodePoints: []int{10950, 824}, Characters: []byte{0xe2, 0xab, 0x86, 0xcc, 0xb8}},
+ "ntgl": {Name: "ntgl", CodePoints: []int{8825}, Characters: []byte{0xe2, 0x89, 0xb9}},
+ "ntilde": {Name: "ntilde", CodePoints: []int{241}, Characters: []byte{0xc3, 0xb1}},
+ "ntlg": {Name: "ntlg", CodePoints: []int{8824}, Characters: []byte{0xe2, 0x89, 0xb8}},
+ "ntriangleleft": {Name: "ntriangleleft", CodePoints: []int{8938}, Characters: []byte{0xe2, 0x8b, 0xaa}},
+ "ntrianglelefteq": {Name: "ntrianglelefteq", CodePoints: []int{8940}, Characters: []byte{0xe2, 0x8b, 0xac}},
+ "ntriangleright": {Name: "ntriangleright", CodePoints: []int{8939}, Characters: []byte{0xe2, 0x8b, 0xab}},
+ "ntrianglerighteq": {Name: "ntrianglerighteq", CodePoints: []int{8941}, Characters: []byte{0xe2, 0x8b, 0xad}},
+ "nu": {Name: "nu", CodePoints: []int{957}, Characters: []byte{0xce, 0xbd}},
+ "num": {Name: "num", CodePoints: []int{35}, Characters: []byte{0x23}},
+ "numero": {Name: "numero", CodePoints: []int{8470}, Characters: []byte{0xe2, 0x84, 0x96}},
+ "numsp": {Name: "numsp", CodePoints: []int{8199}, Characters: []byte{0xe2, 0x80, 0x87}},
+ "nvDash": {Name: "nvDash", CodePoints: []int{8877}, Characters: []byte{0xe2, 0x8a, 0xad}},
+ "nvHarr": {Name: "nvHarr", CodePoints: []int{10500}, Characters: []byte{0xe2, 0xa4, 0x84}},
+ "nvap": {Name: "nvap", CodePoints: []int{8781, 8402}, Characters: []byte{0xe2, 0x89, 0x8d, 0xe2, 0x83, 0x92}},
+ "nvdash": {Name: "nvdash", CodePoints: []int{8876}, Characters: []byte{0xe2, 0x8a, 0xac}},
+ "nvge": {Name: "nvge", CodePoints: []int{8805, 8402}, Characters: []byte{0xe2, 0x89, 0xa5, 0xe2, 0x83, 0x92}},
+ "nvgt": {Name: "nvgt", CodePoints: []int{62, 8402}, Characters: []byte{0x3e, 0xe2, 0x83, 0x92}},
+ "nvinfin": {Name: "nvinfin", CodePoints: []int{10718}, Characters: []byte{0xe2, 0xa7, 0x9e}},
+ "nvlArr": {Name: "nvlArr", CodePoints: []int{10498}, Characters: []byte{0xe2, 0xa4, 0x82}},
+ "nvle": {Name: "nvle", CodePoints: []int{8804, 8402}, Characters: []byte{0xe2, 0x89, 0xa4, 0xe2, 0x83, 0x92}},
+ "nvlt": {Name: "nvlt", CodePoints: []int{60, 8402}, Characters: []byte{0x3c, 0xe2, 0x83, 0x92}},
+ "nvltrie": {Name: "nvltrie", CodePoints: []int{8884, 8402}, Characters: []byte{0xe2, 0x8a, 0xb4, 0xe2, 0x83, 0x92}},
+ "nvrArr": {Name: "nvrArr", CodePoints: []int{10499}, Characters: []byte{0xe2, 0xa4, 0x83}},
+ "nvrtrie": {Name: "nvrtrie", CodePoints: []int{8885, 8402}, Characters: []byte{0xe2, 0x8a, 0xb5, 0xe2, 0x83, 0x92}},
+ "nvsim": {Name: "nvsim", CodePoints: []int{8764, 8402}, Characters: []byte{0xe2, 0x88, 0xbc, 0xe2, 0x83, 0x92}},
+ "nwArr": {Name: "nwArr", CodePoints: []int{8662}, Characters: []byte{0xe2, 0x87, 0x96}},
+ "nwarhk": {Name: "nwarhk", CodePoints: []int{10531}, Characters: []byte{0xe2, 0xa4, 0xa3}},
+ "nwarr": {Name: "nwarr", CodePoints: []int{8598}, Characters: []byte{0xe2, 0x86, 0x96}},
+ "nwarrow": {Name: "nwarrow", CodePoints: []int{8598}, Characters: []byte{0xe2, 0x86, 0x96}},
+ "nwnear": {Name: "nwnear", CodePoints: []int{10535}, Characters: []byte{0xe2, 0xa4, 0xa7}},
+ "oS": {Name: "oS", CodePoints: []int{9416}, Characters: []byte{0xe2, 0x93, 0x88}},
+ "oacute": {Name: "oacute", CodePoints: []int{243}, Characters: []byte{0xc3, 0xb3}},
+ "oast": {Name: "oast", CodePoints: []int{8859}, Characters: []byte{0xe2, 0x8a, 0x9b}},
+ "ocir": {Name: "ocir", CodePoints: []int{8858}, Characters: []byte{0xe2, 0x8a, 0x9a}},
+ "ocirc": {Name: "ocirc", CodePoints: []int{244}, Characters: []byte{0xc3, 0xb4}},
+ "ocy": {Name: "ocy", CodePoints: []int{1086}, Characters: []byte{0xd0, 0xbe}},
+ "odash": {Name: "odash", CodePoints: []int{8861}, Characters: []byte{0xe2, 0x8a, 0x9d}},
+ "odblac": {Name: "odblac", CodePoints: []int{337}, Characters: []byte{0xc5, 0x91}},
+ "odiv": {Name: "odiv", CodePoints: []int{10808}, Characters: []byte{0xe2, 0xa8, 0xb8}},
+ "odot": {Name: "odot", CodePoints: []int{8857}, Characters: []byte{0xe2, 0x8a, 0x99}},
+ "odsold": {Name: "odsold", CodePoints: []int{10684}, Characters: []byte{0xe2, 0xa6, 0xbc}},
+ "oelig": {Name: "oelig", CodePoints: []int{339}, Characters: []byte{0xc5, 0x93}},
+ "ofcir": {Name: "ofcir", CodePoints: []int{10687}, Characters: []byte{0xe2, 0xa6, 0xbf}},
+ "ofr": {Name: "ofr", CodePoints: []int{120108}, Characters: []byte{0xf0, 0x9d, 0x94, 0xac}},
+ "ogon": {Name: "ogon", CodePoints: []int{731}, Characters: []byte{0xcb, 0x9b}},
+ "ograve": {Name: "ograve", CodePoints: []int{242}, Characters: []byte{0xc3, 0xb2}},
+ "ogt": {Name: "ogt", CodePoints: []int{10689}, Characters: []byte{0xe2, 0xa7, 0x81}},
+ "ohbar": {Name: "ohbar", CodePoints: []int{10677}, Characters: []byte{0xe2, 0xa6, 0xb5}},
+ "ohm": {Name: "ohm", CodePoints: []int{937}, Characters: []byte{0xce, 0xa9}},
+ "oint": {Name: "oint", CodePoints: []int{8750}, Characters: []byte{0xe2, 0x88, 0xae}},
+ "olarr": {Name: "olarr", CodePoints: []int{8634}, Characters: []byte{0xe2, 0x86, 0xba}},
+ "olcir": {Name: "olcir", CodePoints: []int{10686}, Characters: []byte{0xe2, 0xa6, 0xbe}},
+ "olcross": {Name: "olcross", CodePoints: []int{10683}, Characters: []byte{0xe2, 0xa6, 0xbb}},
+ "oline": {Name: "oline", CodePoints: []int{8254}, Characters: []byte{0xe2, 0x80, 0xbe}},
+ "olt": {Name: "olt", CodePoints: []int{10688}, Characters: []byte{0xe2, 0xa7, 0x80}},
+ "omacr": {Name: "omacr", CodePoints: []int{333}, Characters: []byte{0xc5, 0x8d}},
+ "omega": {Name: "omega", CodePoints: []int{969}, Characters: []byte{0xcf, 0x89}},
+ "omicron": {Name: "omicron", CodePoints: []int{959}, Characters: []byte{0xce, 0xbf}},
+ "omid": {Name: "omid", CodePoints: []int{10678}, Characters: []byte{0xe2, 0xa6, 0xb6}},
+ "ominus": {Name: "ominus", CodePoints: []int{8854}, Characters: []byte{0xe2, 0x8a, 0x96}},
+ "oopf": {Name: "oopf", CodePoints: []int{120160}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa0}},
+ "opar": {Name: "opar", CodePoints: []int{10679}, Characters: []byte{0xe2, 0xa6, 0xb7}},
+ "operp": {Name: "operp", CodePoints: []int{10681}, Characters: []byte{0xe2, 0xa6, 0xb9}},
+ "oplus": {Name: "oplus", CodePoints: []int{8853}, Characters: []byte{0xe2, 0x8a, 0x95}},
+ "or": {Name: "or", CodePoints: []int{8744}, Characters: []byte{0xe2, 0x88, 0xa8}},
+ "orarr": {Name: "orarr", CodePoints: []int{8635}, Characters: []byte{0xe2, 0x86, 0xbb}},
+ "ord": {Name: "ord", CodePoints: []int{10845}, Characters: []byte{0xe2, 0xa9, 0x9d}},
+ "order": {Name: "order", CodePoints: []int{8500}, Characters: []byte{0xe2, 0x84, 0xb4}},
+ "orderof": {Name: "orderof", CodePoints: []int{8500}, Characters: []byte{0xe2, 0x84, 0xb4}},
+ "ordf": {Name: "ordf", CodePoints: []int{170}, Characters: []byte{0xc2, 0xaa}},
+ "ordm": {Name: "ordm", CodePoints: []int{186}, Characters: []byte{0xc2, 0xba}},
+ "origof": {Name: "origof", CodePoints: []int{8886}, Characters: []byte{0xe2, 0x8a, 0xb6}},
+ "oror": {Name: "oror", CodePoints: []int{10838}, Characters: []byte{0xe2, 0xa9, 0x96}},
+ "orslope": {Name: "orslope", CodePoints: []int{10839}, Characters: []byte{0xe2, 0xa9, 0x97}},
+ "orv": {Name: "orv", CodePoints: []int{10843}, Characters: []byte{0xe2, 0xa9, 0x9b}},
+ "oscr": {Name: "oscr", CodePoints: []int{8500}, Characters: []byte{0xe2, 0x84, 0xb4}},
+ "oslash": {Name: "oslash", CodePoints: []int{248}, Characters: []byte{0xc3, 0xb8}},
+ "osol": {Name: "osol", CodePoints: []int{8856}, Characters: []byte{0xe2, 0x8a, 0x98}},
+ "otilde": {Name: "otilde", CodePoints: []int{245}, Characters: []byte{0xc3, 0xb5}},
+ "otimes": {Name: "otimes", CodePoints: []int{8855}, Characters: []byte{0xe2, 0x8a, 0x97}},
+ "otimesas": {Name: "otimesas", CodePoints: []int{10806}, Characters: []byte{0xe2, 0xa8, 0xb6}},
+ "ouml": {Name: "ouml", CodePoints: []int{246}, Characters: []byte{0xc3, 0xb6}},
+ "ovbar": {Name: "ovbar", CodePoints: []int{9021}, Characters: []byte{0xe2, 0x8c, 0xbd}},
+ "par": {Name: "par", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
+ "para": {Name: "para", CodePoints: []int{182}, Characters: []byte{0xc2, 0xb6}},
+ "parallel": {Name: "parallel", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
+ "parsim": {Name: "parsim", CodePoints: []int{10995}, Characters: []byte{0xe2, 0xab, 0xb3}},
+ "parsl": {Name: "parsl", CodePoints: []int{11005}, Characters: []byte{0xe2, 0xab, 0xbd}},
+ "part": {Name: "part", CodePoints: []int{8706}, Characters: []byte{0xe2, 0x88, 0x82}},
+ "pcy": {Name: "pcy", CodePoints: []int{1087}, Characters: []byte{0xd0, 0xbf}},
+ "percnt": {Name: "percnt", CodePoints: []int{37}, Characters: []byte{0x25}},
+ "period": {Name: "period", CodePoints: []int{46}, Characters: []byte{0x2e}},
+ "permil": {Name: "permil", CodePoints: []int{8240}, Characters: []byte{0xe2, 0x80, 0xb0}},
+ "perp": {Name: "perp", CodePoints: []int{8869}, Characters: []byte{0xe2, 0x8a, 0xa5}},
+ "pertenk": {Name: "pertenk", CodePoints: []int{8241}, Characters: []byte{0xe2, 0x80, 0xb1}},
+ "pfr": {Name: "pfr", CodePoints: []int{120109}, Characters: []byte{0xf0, 0x9d, 0x94, 0xad}},
+ "phi": {Name: "phi", CodePoints: []int{966}, Characters: []byte{0xcf, 0x86}},
+ "phiv": {Name: "phiv", CodePoints: []int{981}, Characters: []byte{0xcf, 0x95}},
+ "phmmat": {Name: "phmmat", CodePoints: []int{8499}, Characters: []byte{0xe2, 0x84, 0xb3}},
+ "phone": {Name: "phone", CodePoints: []int{9742}, Characters: []byte{0xe2, 0x98, 0x8e}},
+ "pi": {Name: "pi", CodePoints: []int{960}, Characters: []byte{0xcf, 0x80}},
+ "pitchfork": {Name: "pitchfork", CodePoints: []int{8916}, Characters: []byte{0xe2, 0x8b, 0x94}},
+ "piv": {Name: "piv", CodePoints: []int{982}, Characters: []byte{0xcf, 0x96}},
+ "planck": {Name: "planck", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
+ "planckh": {Name: "planckh", CodePoints: []int{8462}, Characters: []byte{0xe2, 0x84, 0x8e}},
+ "plankv": {Name: "plankv", CodePoints: []int{8463}, Characters: []byte{0xe2, 0x84, 0x8f}},
+ "plus": {Name: "plus", CodePoints: []int{43}, Characters: []byte{0x2b}},
+ "plusacir": {Name: "plusacir", CodePoints: []int{10787}, Characters: []byte{0xe2, 0xa8, 0xa3}},
+ "plusb": {Name: "plusb", CodePoints: []int{8862}, Characters: []byte{0xe2, 0x8a, 0x9e}},
+ "pluscir": {Name: "pluscir", CodePoints: []int{10786}, Characters: []byte{0xe2, 0xa8, 0xa2}},
+ "plusdo": {Name: "plusdo", CodePoints: []int{8724}, Characters: []byte{0xe2, 0x88, 0x94}},
+ "plusdu": {Name: "plusdu", CodePoints: []int{10789}, Characters: []byte{0xe2, 0xa8, 0xa5}},
+ "pluse": {Name: "pluse", CodePoints: []int{10866}, Characters: []byte{0xe2, 0xa9, 0xb2}},
+ "plusmn": {Name: "plusmn", CodePoints: []int{177}, Characters: []byte{0xc2, 0xb1}},
+ "plussim": {Name: "plussim", CodePoints: []int{10790}, Characters: []byte{0xe2, 0xa8, 0xa6}},
+ "plustwo": {Name: "plustwo", CodePoints: []int{10791}, Characters: []byte{0xe2, 0xa8, 0xa7}},
+ "pm": {Name: "pm", CodePoints: []int{177}, Characters: []byte{0xc2, 0xb1}},
+ "pointint": {Name: "pointint", CodePoints: []int{10773}, Characters: []byte{0xe2, 0xa8, 0x95}},
+ "popf": {Name: "popf", CodePoints: []int{120161}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa1}},
+ "pound": {Name: "pound", CodePoints: []int{163}, Characters: []byte{0xc2, 0xa3}},
+ "pr": {Name: "pr", CodePoints: []int{8826}, Characters: []byte{0xe2, 0x89, 0xba}},
+ "prE": {Name: "prE", CodePoints: []int{10931}, Characters: []byte{0xe2, 0xaa, 0xb3}},
+ "prap": {Name: "prap", CodePoints: []int{10935}, Characters: []byte{0xe2, 0xaa, 0xb7}},
+ "prcue": {Name: "prcue", CodePoints: []int{8828}, Characters: []byte{0xe2, 0x89, 0xbc}},
+ "pre": {Name: "pre", CodePoints: []int{10927}, Characters: []byte{0xe2, 0xaa, 0xaf}},
+ "prec": {Name: "prec", CodePoints: []int{8826}, Characters: []byte{0xe2, 0x89, 0xba}},
+ "precapprox": {Name: "precapprox", CodePoints: []int{10935}, Characters: []byte{0xe2, 0xaa, 0xb7}},
+ "preccurlyeq": {Name: "preccurlyeq", CodePoints: []int{8828}, Characters: []byte{0xe2, 0x89, 0xbc}},
+ "preceq": {Name: "preceq", CodePoints: []int{10927}, Characters: []byte{0xe2, 0xaa, 0xaf}},
+ "precnapprox": {Name: "precnapprox", CodePoints: []int{10937}, Characters: []byte{0xe2, 0xaa, 0xb9}},
+ "precneqq": {Name: "precneqq", CodePoints: []int{10933}, Characters: []byte{0xe2, 0xaa, 0xb5}},
+ "precnsim": {Name: "precnsim", CodePoints: []int{8936}, Characters: []byte{0xe2, 0x8b, 0xa8}},
+ "precsim": {Name: "precsim", CodePoints: []int{8830}, Characters: []byte{0xe2, 0x89, 0xbe}},
+ "prime": {Name: "prime", CodePoints: []int{8242}, Characters: []byte{0xe2, 0x80, 0xb2}},
+ "primes": {Name: "primes", CodePoints: []int{8473}, Characters: []byte{0xe2, 0x84, 0x99}},
+ "prnE": {Name: "prnE", CodePoints: []int{10933}, Characters: []byte{0xe2, 0xaa, 0xb5}},
+ "prnap": {Name: "prnap", CodePoints: []int{10937}, Characters: []byte{0xe2, 0xaa, 0xb9}},
+ "prnsim": {Name: "prnsim", CodePoints: []int{8936}, Characters: []byte{0xe2, 0x8b, 0xa8}},
+ "prod": {Name: "prod", CodePoints: []int{8719}, Characters: []byte{0xe2, 0x88, 0x8f}},
+ "profalar": {Name: "profalar", CodePoints: []int{9006}, Characters: []byte{0xe2, 0x8c, 0xae}},
+ "profline": {Name: "profline", CodePoints: []int{8978}, Characters: []byte{0xe2, 0x8c, 0x92}},
+ "profsurf": {Name: "profsurf", CodePoints: []int{8979}, Characters: []byte{0xe2, 0x8c, 0x93}},
+ "prop": {Name: "prop", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
+ "propto": {Name: "propto", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
+ "prsim": {Name: "prsim", CodePoints: []int{8830}, Characters: []byte{0xe2, 0x89, 0xbe}},
+ "prurel": {Name: "prurel", CodePoints: []int{8880}, Characters: []byte{0xe2, 0x8a, 0xb0}},
+ "pscr": {Name: "pscr", CodePoints: []int{120005}, Characters: []byte{0xf0, 0x9d, 0x93, 0x85}},
+ "psi": {Name: "psi", CodePoints: []int{968}, Characters: []byte{0xcf, 0x88}},
+ "puncsp": {Name: "puncsp", CodePoints: []int{8200}, Characters: []byte{0xe2, 0x80, 0x88}},
+ "qfr": {Name: "qfr", CodePoints: []int{120110}, Characters: []byte{0xf0, 0x9d, 0x94, 0xae}},
+ "qint": {Name: "qint", CodePoints: []int{10764}, Characters: []byte{0xe2, 0xa8, 0x8c}},
+ "qopf": {Name: "qopf", CodePoints: []int{120162}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa2}},
+ "qprime": {Name: "qprime", CodePoints: []int{8279}, Characters: []byte{0xe2, 0x81, 0x97}},
+ "qscr": {Name: "qscr", CodePoints: []int{120006}, Characters: []byte{0xf0, 0x9d, 0x93, 0x86}},
+ "quaternions": {Name: "quaternions", CodePoints: []int{8461}, Characters: []byte{0xe2, 0x84, 0x8d}},
+ "quatint": {Name: "quatint", CodePoints: []int{10774}, Characters: []byte{0xe2, 0xa8, 0x96}},
+ "quest": {Name: "quest", CodePoints: []int{63}, Characters: []byte{0x3f}},
+ "questeq": {Name: "questeq", CodePoints: []int{8799}, Characters: []byte{0xe2, 0x89, 0x9f}},
+ "quot": {Name: "quot", CodePoints: []int{34}, Characters: []byte{0x22}},
+ "rAarr": {Name: "rAarr", CodePoints: []int{8667}, Characters: []byte{0xe2, 0x87, 0x9b}},
+ "rArr": {Name: "rArr", CodePoints: []int{8658}, Characters: []byte{0xe2, 0x87, 0x92}},
+ "rAtail": {Name: "rAtail", CodePoints: []int{10524}, Characters: []byte{0xe2, 0xa4, 0x9c}},
+ "rBarr": {Name: "rBarr", CodePoints: []int{10511}, Characters: []byte{0xe2, 0xa4, 0x8f}},
+ "rHar": {Name: "rHar", CodePoints: []int{10596}, Characters: []byte{0xe2, 0xa5, 0xa4}},
+ "race": {Name: "race", CodePoints: []int{8765, 817}, Characters: []byte{0xe2, 0x88, 0xbd, 0xcc, 0xb1}},
+ "racute": {Name: "racute", CodePoints: []int{341}, Characters: []byte{0xc5, 0x95}},
+ "radic": {Name: "radic", CodePoints: []int{8730}, Characters: []byte{0xe2, 0x88, 0x9a}},
+ "raemptyv": {Name: "raemptyv", CodePoints: []int{10675}, Characters: []byte{0xe2, 0xa6, 0xb3}},
+ "rang": {Name: "rang", CodePoints: []int{10217}, Characters: []byte{0xe2, 0x9f, 0xa9}},
+ "rangd": {Name: "rangd", CodePoints: []int{10642}, Characters: []byte{0xe2, 0xa6, 0x92}},
+ "range": {Name: "range", CodePoints: []int{10661}, Characters: []byte{0xe2, 0xa6, 0xa5}},
+ "rangle": {Name: "rangle", CodePoints: []int{10217}, Characters: []byte{0xe2, 0x9f, 0xa9}},
+ "raquo": {Name: "raquo", CodePoints: []int{187}, Characters: []byte{0xc2, 0xbb}},
+ "rarr": {Name: "rarr", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
+ "rarrap": {Name: "rarrap", CodePoints: []int{10613}, Characters: []byte{0xe2, 0xa5, 0xb5}},
+ "rarrb": {Name: "rarrb", CodePoints: []int{8677}, Characters: []byte{0xe2, 0x87, 0xa5}},
+ "rarrbfs": {Name: "rarrbfs", CodePoints: []int{10528}, Characters: []byte{0xe2, 0xa4, 0xa0}},
+ "rarrc": {Name: "rarrc", CodePoints: []int{10547}, Characters: []byte{0xe2, 0xa4, 0xb3}},
+ "rarrfs": {Name: "rarrfs", CodePoints: []int{10526}, Characters: []byte{0xe2, 0xa4, 0x9e}},
+ "rarrhk": {Name: "rarrhk", CodePoints: []int{8618}, Characters: []byte{0xe2, 0x86, 0xaa}},
+ "rarrlp": {Name: "rarrlp", CodePoints: []int{8620}, Characters: []byte{0xe2, 0x86, 0xac}},
+ "rarrpl": {Name: "rarrpl", CodePoints: []int{10565}, Characters: []byte{0xe2, 0xa5, 0x85}},
+ "rarrsim": {Name: "rarrsim", CodePoints: []int{10612}, Characters: []byte{0xe2, 0xa5, 0xb4}},
+ "rarrtl": {Name: "rarrtl", CodePoints: []int{8611}, Characters: []byte{0xe2, 0x86, 0xa3}},
+ "rarrw": {Name: "rarrw", CodePoints: []int{8605}, Characters: []byte{0xe2, 0x86, 0x9d}},
+ "ratail": {Name: "ratail", CodePoints: []int{10522}, Characters: []byte{0xe2, 0xa4, 0x9a}},
+ "ratio": {Name: "ratio", CodePoints: []int{8758}, Characters: []byte{0xe2, 0x88, 0xb6}},
+ "rationals": {Name: "rationals", CodePoints: []int{8474}, Characters: []byte{0xe2, 0x84, 0x9a}},
+ "rbarr": {Name: "rbarr", CodePoints: []int{10509}, Characters: []byte{0xe2, 0xa4, 0x8d}},
+ "rbbrk": {Name: "rbbrk", CodePoints: []int{10099}, Characters: []byte{0xe2, 0x9d, 0xb3}},
+ "rbrace": {Name: "rbrace", CodePoints: []int{125}, Characters: []byte{0x7d}},
+ "rbrack": {Name: "rbrack", CodePoints: []int{93}, Characters: []byte{0x5d}},
+ "rbrke": {Name: "rbrke", CodePoints: []int{10636}, Characters: []byte{0xe2, 0xa6, 0x8c}},
+ "rbrksld": {Name: "rbrksld", CodePoints: []int{10638}, Characters: []byte{0xe2, 0xa6, 0x8e}},
+ "rbrkslu": {Name: "rbrkslu", CodePoints: []int{10640}, Characters: []byte{0xe2, 0xa6, 0x90}},
+ "rcaron": {Name: "rcaron", CodePoints: []int{345}, Characters: []byte{0xc5, 0x99}},
+ "rcedil": {Name: "rcedil", CodePoints: []int{343}, Characters: []byte{0xc5, 0x97}},
+ "rceil": {Name: "rceil", CodePoints: []int{8969}, Characters: []byte{0xe2, 0x8c, 0x89}},
+ "rcub": {Name: "rcub", CodePoints: []int{125}, Characters: []byte{0x7d}},
+ "rcy": {Name: "rcy", CodePoints: []int{1088}, Characters: []byte{0xd1, 0x80}},
+ "rdca": {Name: "rdca", CodePoints: []int{10551}, Characters: []byte{0xe2, 0xa4, 0xb7}},
+ "rdldhar": {Name: "rdldhar", CodePoints: []int{10601}, Characters: []byte{0xe2, 0xa5, 0xa9}},
+ "rdquo": {Name: "rdquo", CodePoints: []int{8221}, Characters: []byte{0xe2, 0x80, 0x9d}},
+ "rdquor": {Name: "rdquor", CodePoints: []int{8221}, Characters: []byte{0xe2, 0x80, 0x9d}},
+ "rdsh": {Name: "rdsh", CodePoints: []int{8627}, Characters: []byte{0xe2, 0x86, 0xb3}},
+ "real": {Name: "real", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
+ "realine": {Name: "realine", CodePoints: []int{8475}, Characters: []byte{0xe2, 0x84, 0x9b}},
+ "realpart": {Name: "realpart", CodePoints: []int{8476}, Characters: []byte{0xe2, 0x84, 0x9c}},
+ "reals": {Name: "reals", CodePoints: []int{8477}, Characters: []byte{0xe2, 0x84, 0x9d}},
+ "rect": {Name: "rect", CodePoints: []int{9645}, Characters: []byte{0xe2, 0x96, 0xad}},
+ "reg": {Name: "reg", CodePoints: []int{174}, Characters: []byte{0xc2, 0xae}},
+ "rfisht": {Name: "rfisht", CodePoints: []int{10621}, Characters: []byte{0xe2, 0xa5, 0xbd}},
+ "rfloor": {Name: "rfloor", CodePoints: []int{8971}, Characters: []byte{0xe2, 0x8c, 0x8b}},
+ "rfr": {Name: "rfr", CodePoints: []int{120111}, Characters: []byte{0xf0, 0x9d, 0x94, 0xaf}},
+ "rhard": {Name: "rhard", CodePoints: []int{8641}, Characters: []byte{0xe2, 0x87, 0x81}},
+ "rharu": {Name: "rharu", CodePoints: []int{8640}, Characters: []byte{0xe2, 0x87, 0x80}},
+ "rharul": {Name: "rharul", CodePoints: []int{10604}, Characters: []byte{0xe2, 0xa5, 0xac}},
+ "rho": {Name: "rho", CodePoints: []int{961}, Characters: []byte{0xcf, 0x81}},
+ "rhov": {Name: "rhov", CodePoints: []int{1009}, Characters: []byte{0xcf, 0xb1}},
+ "rightarrow": {Name: "rightarrow", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
+ "rightarrowtail": {Name: "rightarrowtail", CodePoints: []int{8611}, Characters: []byte{0xe2, 0x86, 0xa3}},
+ "rightharpoondown": {Name: "rightharpoondown", CodePoints: []int{8641}, Characters: []byte{0xe2, 0x87, 0x81}},
+ "rightharpoonup": {Name: "rightharpoonup", CodePoints: []int{8640}, Characters: []byte{0xe2, 0x87, 0x80}},
+ "rightleftarrows": {Name: "rightleftarrows", CodePoints: []int{8644}, Characters: []byte{0xe2, 0x87, 0x84}},
+ "rightleftharpoons": {Name: "rightleftharpoons", CodePoints: []int{8652}, Characters: []byte{0xe2, 0x87, 0x8c}},
+ "rightrightarrows": {Name: "rightrightarrows", CodePoints: []int{8649}, Characters: []byte{0xe2, 0x87, 0x89}},
+ "rightsquigarrow": {Name: "rightsquigarrow", CodePoints: []int{8605}, Characters: []byte{0xe2, 0x86, 0x9d}},
+ "rightthreetimes": {Name: "rightthreetimes", CodePoints: []int{8908}, Characters: []byte{0xe2, 0x8b, 0x8c}},
+ "ring": {Name: "ring", CodePoints: []int{730}, Characters: []byte{0xcb, 0x9a}},
+ "risingdotseq": {Name: "risingdotseq", CodePoints: []int{8787}, Characters: []byte{0xe2, 0x89, 0x93}},
+ "rlarr": {Name: "rlarr", CodePoints: []int{8644}, Characters: []byte{0xe2, 0x87, 0x84}},
+ "rlhar": {Name: "rlhar", CodePoints: []int{8652}, Characters: []byte{0xe2, 0x87, 0x8c}},
+ "rlm": {Name: "rlm", CodePoints: []int{8207}, Characters: []byte{0xe2, 0x80, 0x8f}},
+ "rmoust": {Name: "rmoust", CodePoints: []int{9137}, Characters: []byte{0xe2, 0x8e, 0xb1}},
+ "rmoustache": {Name: "rmoustache", CodePoints: []int{9137}, Characters: []byte{0xe2, 0x8e, 0xb1}},
+ "rnmid": {Name: "rnmid", CodePoints: []int{10990}, Characters: []byte{0xe2, 0xab, 0xae}},
+ "roang": {Name: "roang", CodePoints: []int{10221}, Characters: []byte{0xe2, 0x9f, 0xad}},
+ "roarr": {Name: "roarr", CodePoints: []int{8702}, Characters: []byte{0xe2, 0x87, 0xbe}},
+ "robrk": {Name: "robrk", CodePoints: []int{10215}, Characters: []byte{0xe2, 0x9f, 0xa7}},
+ "ropar": {Name: "ropar", CodePoints: []int{10630}, Characters: []byte{0xe2, 0xa6, 0x86}},
+ "ropf": {Name: "ropf", CodePoints: []int{120163}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa3}},
+ "roplus": {Name: "roplus", CodePoints: []int{10798}, Characters: []byte{0xe2, 0xa8, 0xae}},
+ "rotimes": {Name: "rotimes", CodePoints: []int{10805}, Characters: []byte{0xe2, 0xa8, 0xb5}},
+ "rpar": {Name: "rpar", CodePoints: []int{41}, Characters: []byte{0x29}},
+ "rpargt": {Name: "rpargt", CodePoints: []int{10644}, Characters: []byte{0xe2, 0xa6, 0x94}},
+ "rppolint": {Name: "rppolint", CodePoints: []int{10770}, Characters: []byte{0xe2, 0xa8, 0x92}},
+ "rrarr": {Name: "rrarr", CodePoints: []int{8649}, Characters: []byte{0xe2, 0x87, 0x89}},
+ "rsaquo": {Name: "rsaquo", CodePoints: []int{8250}, Characters: []byte{0xe2, 0x80, 0xba}},
+ "rscr": {Name: "rscr", CodePoints: []int{120007}, Characters: []byte{0xf0, 0x9d, 0x93, 0x87}},
+ "rsh": {Name: "rsh", CodePoints: []int{8625}, Characters: []byte{0xe2, 0x86, 0xb1}},
+ "rsqb": {Name: "rsqb", CodePoints: []int{93}, Characters: []byte{0x5d}},
+ "rsquo": {Name: "rsquo", CodePoints: []int{8217}, Characters: []byte{0xe2, 0x80, 0x99}},
+ "rsquor": {Name: "rsquor", CodePoints: []int{8217}, Characters: []byte{0xe2, 0x80, 0x99}},
+ "rthree": {Name: "rthree", CodePoints: []int{8908}, Characters: []byte{0xe2, 0x8b, 0x8c}},
+ "rtimes": {Name: "rtimes", CodePoints: []int{8906}, Characters: []byte{0xe2, 0x8b, 0x8a}},
+ "rtri": {Name: "rtri", CodePoints: []int{9657}, Characters: []byte{0xe2, 0x96, 0xb9}},
+ "rtrie": {Name: "rtrie", CodePoints: []int{8885}, Characters: []byte{0xe2, 0x8a, 0xb5}},
+ "rtrif": {Name: "rtrif", CodePoints: []int{9656}, Characters: []byte{0xe2, 0x96, 0xb8}},
+ "rtriltri": {Name: "rtriltri", CodePoints: []int{10702}, Characters: []byte{0xe2, 0xa7, 0x8e}},
+ "ruluhar": {Name: "ruluhar", CodePoints: []int{10600}, Characters: []byte{0xe2, 0xa5, 0xa8}},
+ "rx": {Name: "rx", CodePoints: []int{8478}, Characters: []byte{0xe2, 0x84, 0x9e}},
+ "sacute": {Name: "sacute", CodePoints: []int{347}, Characters: []byte{0xc5, 0x9b}},
+ "sbquo": {Name: "sbquo", CodePoints: []int{8218}, Characters: []byte{0xe2, 0x80, 0x9a}},
+ "sc": {Name: "sc", CodePoints: []int{8827}, Characters: []byte{0xe2, 0x89, 0xbb}},
+ "scE": {Name: "scE", CodePoints: []int{10932}, Characters: []byte{0xe2, 0xaa, 0xb4}},
+ "scap": {Name: "scap", CodePoints: []int{10936}, Characters: []byte{0xe2, 0xaa, 0xb8}},
+ "scaron": {Name: "scaron", CodePoints: []int{353}, Characters: []byte{0xc5, 0xa1}},
+ "sccue": {Name: "sccue", CodePoints: []int{8829}, Characters: []byte{0xe2, 0x89, 0xbd}},
+ "sce": {Name: "sce", CodePoints: []int{10928}, Characters: []byte{0xe2, 0xaa, 0xb0}},
+ "scedil": {Name: "scedil", CodePoints: []int{351}, Characters: []byte{0xc5, 0x9f}},
+ "scirc": {Name: "scirc", CodePoints: []int{349}, Characters: []byte{0xc5, 0x9d}},
+ "scnE": {Name: "scnE", CodePoints: []int{10934}, Characters: []byte{0xe2, 0xaa, 0xb6}},
+ "scnap": {Name: "scnap", CodePoints: []int{10938}, Characters: []byte{0xe2, 0xaa, 0xba}},
+ "scnsim": {Name: "scnsim", CodePoints: []int{8937}, Characters: []byte{0xe2, 0x8b, 0xa9}},
+ "scpolint": {Name: "scpolint", CodePoints: []int{10771}, Characters: []byte{0xe2, 0xa8, 0x93}},
+ "scsim": {Name: "scsim", CodePoints: []int{8831}, Characters: []byte{0xe2, 0x89, 0xbf}},
+ "scy": {Name: "scy", CodePoints: []int{1089}, Characters: []byte{0xd1, 0x81}},
+ "sdot": {Name: "sdot", CodePoints: []int{8901}, Characters: []byte{0xe2, 0x8b, 0x85}},
+ "sdotb": {Name: "sdotb", CodePoints: []int{8865}, Characters: []byte{0xe2, 0x8a, 0xa1}},
+ "sdote": {Name: "sdote", CodePoints: []int{10854}, Characters: []byte{0xe2, 0xa9, 0xa6}},
+ "seArr": {Name: "seArr", CodePoints: []int{8664}, Characters: []byte{0xe2, 0x87, 0x98}},
+ "searhk": {Name: "searhk", CodePoints: []int{10533}, Characters: []byte{0xe2, 0xa4, 0xa5}},
+ "searr": {Name: "searr", CodePoints: []int{8600}, Characters: []byte{0xe2, 0x86, 0x98}},
+ "searrow": {Name: "searrow", CodePoints: []int{8600}, Characters: []byte{0xe2, 0x86, 0x98}},
+ "sect": {Name: "sect", CodePoints: []int{167}, Characters: []byte{0xc2, 0xa7}},
+ "semi": {Name: "semi", CodePoints: []int{59}, Characters: []byte{0x3b}},
+ "seswar": {Name: "seswar", CodePoints: []int{10537}, Characters: []byte{0xe2, 0xa4, 0xa9}},
+ "setminus": {Name: "setminus", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
+ "setmn": {Name: "setmn", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
+ "sext": {Name: "sext", CodePoints: []int{10038}, Characters: []byte{0xe2, 0x9c, 0xb6}},
+ "sfr": {Name: "sfr", CodePoints: []int{120112}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb0}},
+ "sfrown": {Name: "sfrown", CodePoints: []int{8994}, Characters: []byte{0xe2, 0x8c, 0xa2}},
+ "sharp": {Name: "sharp", CodePoints: []int{9839}, Characters: []byte{0xe2, 0x99, 0xaf}},
+ "shchcy": {Name: "shchcy", CodePoints: []int{1097}, Characters: []byte{0xd1, 0x89}},
+ "shcy": {Name: "shcy", CodePoints: []int{1096}, Characters: []byte{0xd1, 0x88}},
+ "shortmid": {Name: "shortmid", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
+ "shortparallel": {Name: "shortparallel", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
+ "shy": {Name: "shy", CodePoints: []int{173}, Characters: []byte{0xc2, 0xad}},
+ "sigma": {Name: "sigma", CodePoints: []int{963}, Characters: []byte{0xcf, 0x83}},
+ "sigmaf": {Name: "sigmaf", CodePoints: []int{962}, Characters: []byte{0xcf, 0x82}},
+ "sigmav": {Name: "sigmav", CodePoints: []int{962}, Characters: []byte{0xcf, 0x82}},
+ "sim": {Name: "sim", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
+ "simdot": {Name: "simdot", CodePoints: []int{10858}, Characters: []byte{0xe2, 0xa9, 0xaa}},
+ "sime": {Name: "sime", CodePoints: []int{8771}, Characters: []byte{0xe2, 0x89, 0x83}},
+ "simeq": {Name: "simeq", CodePoints: []int{8771}, Characters: []byte{0xe2, 0x89, 0x83}},
+ "simg": {Name: "simg", CodePoints: []int{10910}, Characters: []byte{0xe2, 0xaa, 0x9e}},
+ "simgE": {Name: "simgE", CodePoints: []int{10912}, Characters: []byte{0xe2, 0xaa, 0xa0}},
+ "siml": {Name: "siml", CodePoints: []int{10909}, Characters: []byte{0xe2, 0xaa, 0x9d}},
+ "simlE": {Name: "simlE", CodePoints: []int{10911}, Characters: []byte{0xe2, 0xaa, 0x9f}},
+ "simne": {Name: "simne", CodePoints: []int{8774}, Characters: []byte{0xe2, 0x89, 0x86}},
+ "simplus": {Name: "simplus", CodePoints: []int{10788}, Characters: []byte{0xe2, 0xa8, 0xa4}},
+ "simrarr": {Name: "simrarr", CodePoints: []int{10610}, Characters: []byte{0xe2, 0xa5, 0xb2}},
+ "slarr": {Name: "slarr", CodePoints: []int{8592}, Characters: []byte{0xe2, 0x86, 0x90}},
+ "smallsetminus": {Name: "smallsetminus", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
+ "smashp": {Name: "smashp", CodePoints: []int{10803}, Characters: []byte{0xe2, 0xa8, 0xb3}},
+ "smeparsl": {Name: "smeparsl", CodePoints: []int{10724}, Characters: []byte{0xe2, 0xa7, 0xa4}},
+ "smid": {Name: "smid", CodePoints: []int{8739}, Characters: []byte{0xe2, 0x88, 0xa3}},
+ "smile": {Name: "smile", CodePoints: []int{8995}, Characters: []byte{0xe2, 0x8c, 0xa3}},
+ "smt": {Name: "smt", CodePoints: []int{10922}, Characters: []byte{0xe2, 0xaa, 0xaa}},
+ "smte": {Name: "smte", CodePoints: []int{10924}, Characters: []byte{0xe2, 0xaa, 0xac}},
+ "smtes": {Name: "smtes", CodePoints: []int{10924, 65024}, Characters: []byte{0xe2, 0xaa, 0xac, 0xef, 0xb8, 0x80}},
+ "softcy": {Name: "softcy", CodePoints: []int{1100}, Characters: []byte{0xd1, 0x8c}},
+ "sol": {Name: "sol", CodePoints: []int{47}, Characters: []byte{0x2f}},
+ "solb": {Name: "solb", CodePoints: []int{10692}, Characters: []byte{0xe2, 0xa7, 0x84}},
+ "solbar": {Name: "solbar", CodePoints: []int{9023}, Characters: []byte{0xe2, 0x8c, 0xbf}},
+ "sopf": {Name: "sopf", CodePoints: []int{120164}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa4}},
+ "spades": {Name: "spades", CodePoints: []int{9824}, Characters: []byte{0xe2, 0x99, 0xa0}},
+ "spadesuit": {Name: "spadesuit", CodePoints: []int{9824}, Characters: []byte{0xe2, 0x99, 0xa0}},
+ "spar": {Name: "spar", CodePoints: []int{8741}, Characters: []byte{0xe2, 0x88, 0xa5}},
+ "sqcap": {Name: "sqcap", CodePoints: []int{8851}, Characters: []byte{0xe2, 0x8a, 0x93}},
+ "sqcaps": {Name: "sqcaps", CodePoints: []int{8851, 65024}, Characters: []byte{0xe2, 0x8a, 0x93, 0xef, 0xb8, 0x80}},
+ "sqcup": {Name: "sqcup", CodePoints: []int{8852}, Characters: []byte{0xe2, 0x8a, 0x94}},
+ "sqcups": {Name: "sqcups", CodePoints: []int{8852, 65024}, Characters: []byte{0xe2, 0x8a, 0x94, 0xef, 0xb8, 0x80}},
+ "sqsub": {Name: "sqsub", CodePoints: []int{8847}, Characters: []byte{0xe2, 0x8a, 0x8f}},
+ "sqsube": {Name: "sqsube", CodePoints: []int{8849}, Characters: []byte{0xe2, 0x8a, 0x91}},
+ "sqsubset": {Name: "sqsubset", CodePoints: []int{8847}, Characters: []byte{0xe2, 0x8a, 0x8f}},
+ "sqsubseteq": {Name: "sqsubseteq", CodePoints: []int{8849}, Characters: []byte{0xe2, 0x8a, 0x91}},
+ "sqsup": {Name: "sqsup", CodePoints: []int{8848}, Characters: []byte{0xe2, 0x8a, 0x90}},
+ "sqsupe": {Name: "sqsupe", CodePoints: []int{8850}, Characters: []byte{0xe2, 0x8a, 0x92}},
+ "sqsupset": {Name: "sqsupset", CodePoints: []int{8848}, Characters: []byte{0xe2, 0x8a, 0x90}},
+ "sqsupseteq": {Name: "sqsupseteq", CodePoints: []int{8850}, Characters: []byte{0xe2, 0x8a, 0x92}},
+ "squ": {Name: "squ", CodePoints: []int{9633}, Characters: []byte{0xe2, 0x96, 0xa1}},
+ "square": {Name: "square", CodePoints: []int{9633}, Characters: []byte{0xe2, 0x96, 0xa1}},
+ "squarf": {Name: "squarf", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
+ "squf": {Name: "squf", CodePoints: []int{9642}, Characters: []byte{0xe2, 0x96, 0xaa}},
+ "srarr": {Name: "srarr", CodePoints: []int{8594}, Characters: []byte{0xe2, 0x86, 0x92}},
+ "sscr": {Name: "sscr", CodePoints: []int{120008}, Characters: []byte{0xf0, 0x9d, 0x93, 0x88}},
+ "ssetmn": {Name: "ssetmn", CodePoints: []int{8726}, Characters: []byte{0xe2, 0x88, 0x96}},
+ "ssmile": {Name: "ssmile", CodePoints: []int{8995}, Characters: []byte{0xe2, 0x8c, 0xa3}},
+ "sstarf": {Name: "sstarf", CodePoints: []int{8902}, Characters: []byte{0xe2, 0x8b, 0x86}},
+ "star": {Name: "star", CodePoints: []int{9734}, Characters: []byte{0xe2, 0x98, 0x86}},
+ "starf": {Name: "starf", CodePoints: []int{9733}, Characters: []byte{0xe2, 0x98, 0x85}},
+ "straightepsilon": {Name: "straightepsilon", CodePoints: []int{1013}, Characters: []byte{0xcf, 0xb5}},
+ "straightphi": {Name: "straightphi", CodePoints: []int{981}, Characters: []byte{0xcf, 0x95}},
+ "strns": {Name: "strns", CodePoints: []int{175}, Characters: []byte{0xc2, 0xaf}},
+ "sub": {Name: "sub", CodePoints: []int{8834}, Characters: []byte{0xe2, 0x8a, 0x82}},
+ "subE": {Name: "subE", CodePoints: []int{10949}, Characters: []byte{0xe2, 0xab, 0x85}},
+ "subdot": {Name: "subdot", CodePoints: []int{10941}, Characters: []byte{0xe2, 0xaa, 0xbd}},
+ "sube": {Name: "sube", CodePoints: []int{8838}, Characters: []byte{0xe2, 0x8a, 0x86}},
+ "subedot": {Name: "subedot", CodePoints: []int{10947}, Characters: []byte{0xe2, 0xab, 0x83}},
+ "submult": {Name: "submult", CodePoints: []int{10945}, Characters: []byte{0xe2, 0xab, 0x81}},
+ "subnE": {Name: "subnE", CodePoints: []int{10955}, Characters: []byte{0xe2, 0xab, 0x8b}},
+ "subne": {Name: "subne", CodePoints: []int{8842}, Characters: []byte{0xe2, 0x8a, 0x8a}},
+ "subplus": {Name: "subplus", CodePoints: []int{10943}, Characters: []byte{0xe2, 0xaa, 0xbf}},
+ "subrarr": {Name: "subrarr", CodePoints: []int{10617}, Characters: []byte{0xe2, 0xa5, 0xb9}},
+ "subset": {Name: "subset", CodePoints: []int{8834}, Characters: []byte{0xe2, 0x8a, 0x82}},
+ "subseteq": {Name: "subseteq", CodePoints: []int{8838}, Characters: []byte{0xe2, 0x8a, 0x86}},
+ "subseteqq": {Name: "subseteqq", CodePoints: []int{10949}, Characters: []byte{0xe2, 0xab, 0x85}},
+ "subsetneq": {Name: "subsetneq", CodePoints: []int{8842}, Characters: []byte{0xe2, 0x8a, 0x8a}},
+ "subsetneqq": {Name: "subsetneqq", CodePoints: []int{10955}, Characters: []byte{0xe2, 0xab, 0x8b}},
+ "subsim": {Name: "subsim", CodePoints: []int{10951}, Characters: []byte{0xe2, 0xab, 0x87}},
+ "subsub": {Name: "subsub", CodePoints: []int{10965}, Characters: []byte{0xe2, 0xab, 0x95}},
+ "subsup": {Name: "subsup", CodePoints: []int{10963}, Characters: []byte{0xe2, 0xab, 0x93}},
+ "succ": {Name: "succ", CodePoints: []int{8827}, Characters: []byte{0xe2, 0x89, 0xbb}},
+ "succapprox": {Name: "succapprox", CodePoints: []int{10936}, Characters: []byte{0xe2, 0xaa, 0xb8}},
+ "succcurlyeq": {Name: "succcurlyeq", CodePoints: []int{8829}, Characters: []byte{0xe2, 0x89, 0xbd}},
+ "succeq": {Name: "succeq", CodePoints: []int{10928}, Characters: []byte{0xe2, 0xaa, 0xb0}},
+ "succnapprox": {Name: "succnapprox", CodePoints: []int{10938}, Characters: []byte{0xe2, 0xaa, 0xba}},
+ "succneqq": {Name: "succneqq", CodePoints: []int{10934}, Characters: []byte{0xe2, 0xaa, 0xb6}},
+ "succnsim": {Name: "succnsim", CodePoints: []int{8937}, Characters: []byte{0xe2, 0x8b, 0xa9}},
+ "succsim": {Name: "succsim", CodePoints: []int{8831}, Characters: []byte{0xe2, 0x89, 0xbf}},
+ "sum": {Name: "sum", CodePoints: []int{8721}, Characters: []byte{0xe2, 0x88, 0x91}},
+ "sung": {Name: "sung", CodePoints: []int{9834}, Characters: []byte{0xe2, 0x99, 0xaa}},
+ "sup": {Name: "sup", CodePoints: []int{8835}, Characters: []byte{0xe2, 0x8a, 0x83}},
+ "sup1": {Name: "sup1", CodePoints: []int{185}, Characters: []byte{0xc2, 0xb9}},
+ "sup2": {Name: "sup2", CodePoints: []int{178}, Characters: []byte{0xc2, 0xb2}},
+ "sup3": {Name: "sup3", CodePoints: []int{179}, Characters: []byte{0xc2, 0xb3}},
+ "supE": {Name: "supE", CodePoints: []int{10950}, Characters: []byte{0xe2, 0xab, 0x86}},
+ "supdot": {Name: "supdot", CodePoints: []int{10942}, Characters: []byte{0xe2, 0xaa, 0xbe}},
+ "supdsub": {Name: "supdsub", CodePoints: []int{10968}, Characters: []byte{0xe2, 0xab, 0x98}},
+ "supe": {Name: "supe", CodePoints: []int{8839}, Characters: []byte{0xe2, 0x8a, 0x87}},
+ "supedot": {Name: "supedot", CodePoints: []int{10948}, Characters: []byte{0xe2, 0xab, 0x84}},
+ "suphsol": {Name: "suphsol", CodePoints: []int{10185}, Characters: []byte{0xe2, 0x9f, 0x89}},
+ "suphsub": {Name: "suphsub", CodePoints: []int{10967}, Characters: []byte{0xe2, 0xab, 0x97}},
+ "suplarr": {Name: "suplarr", CodePoints: []int{10619}, Characters: []byte{0xe2, 0xa5, 0xbb}},
+ "supmult": {Name: "supmult", CodePoints: []int{10946}, Characters: []byte{0xe2, 0xab, 0x82}},
+ "supnE": {Name: "supnE", CodePoints: []int{10956}, Characters: []byte{0xe2, 0xab, 0x8c}},
+ "supne": {Name: "supne", CodePoints: []int{8843}, Characters: []byte{0xe2, 0x8a, 0x8b}},
+ "supplus": {Name: "supplus", CodePoints: []int{10944}, Characters: []byte{0xe2, 0xab, 0x80}},
+ "supset": {Name: "supset", CodePoints: []int{8835}, Characters: []byte{0xe2, 0x8a, 0x83}},
+ "supseteq": {Name: "supseteq", CodePoints: []int{8839}, Characters: []byte{0xe2, 0x8a, 0x87}},
+ "supseteqq": {Name: "supseteqq", CodePoints: []int{10950}, Characters: []byte{0xe2, 0xab, 0x86}},
+ "supsetneq": {Name: "supsetneq", CodePoints: []int{8843}, Characters: []byte{0xe2, 0x8a, 0x8b}},
+ "supsetneqq": {Name: "supsetneqq", CodePoints: []int{10956}, Characters: []byte{0xe2, 0xab, 0x8c}},
+ "supsim": {Name: "supsim", CodePoints: []int{10952}, Characters: []byte{0xe2, 0xab, 0x88}},
+ "supsub": {Name: "supsub", CodePoints: []int{10964}, Characters: []byte{0xe2, 0xab, 0x94}},
+ "supsup": {Name: "supsup", CodePoints: []int{10966}, Characters: []byte{0xe2, 0xab, 0x96}},
+ "swArr": {Name: "swArr", CodePoints: []int{8665}, Characters: []byte{0xe2, 0x87, 0x99}},
+ "swarhk": {Name: "swarhk", CodePoints: []int{10534}, Characters: []byte{0xe2, 0xa4, 0xa6}},
+ "swarr": {Name: "swarr", CodePoints: []int{8601}, Characters: []byte{0xe2, 0x86, 0x99}},
+ "swarrow": {Name: "swarrow", CodePoints: []int{8601}, Characters: []byte{0xe2, 0x86, 0x99}},
+ "swnwar": {Name: "swnwar", CodePoints: []int{10538}, Characters: []byte{0xe2, 0xa4, 0xaa}},
+ "szlig": {Name: "szlig", CodePoints: []int{223}, Characters: []byte{0xc3, 0x9f}},
+ "target": {Name: "target", CodePoints: []int{8982}, Characters: []byte{0xe2, 0x8c, 0x96}},
+ "tau": {Name: "tau", CodePoints: []int{964}, Characters: []byte{0xcf, 0x84}},
+ "tbrk": {Name: "tbrk", CodePoints: []int{9140}, Characters: []byte{0xe2, 0x8e, 0xb4}},
+ "tcaron": {Name: "tcaron", CodePoints: []int{357}, Characters: []byte{0xc5, 0xa5}},
+ "tcedil": {Name: "tcedil", CodePoints: []int{355}, Characters: []byte{0xc5, 0xa3}},
+ "tcy": {Name: "tcy", CodePoints: []int{1090}, Characters: []byte{0xd1, 0x82}},
+ "tdot": {Name: "tdot", CodePoints: []int{8411}, Characters: []byte{0xe2, 0x83, 0x9b}},
+ "telrec": {Name: "telrec", CodePoints: []int{8981}, Characters: []byte{0xe2, 0x8c, 0x95}},
+ "tfr": {Name: "tfr", CodePoints: []int{120113}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb1}},
+ "there4": {Name: "there4", CodePoints: []int{8756}, Characters: []byte{0xe2, 0x88, 0xb4}},
+ "therefore": {Name: "therefore", CodePoints: []int{8756}, Characters: []byte{0xe2, 0x88, 0xb4}},
+ "theta": {Name: "theta", CodePoints: []int{952}, Characters: []byte{0xce, 0xb8}},
+ "thetasym": {Name: "thetasym", CodePoints: []int{977}, Characters: []byte{0xcf, 0x91}},
+ "thetav": {Name: "thetav", CodePoints: []int{977}, Characters: []byte{0xcf, 0x91}},
+ "thickapprox": {Name: "thickapprox", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
+ "thicksim": {Name: "thicksim", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
+ "thinsp": {Name: "thinsp", CodePoints: []int{8201}, Characters: []byte{0xe2, 0x80, 0x89}},
+ "thkap": {Name: "thkap", CodePoints: []int{8776}, Characters: []byte{0xe2, 0x89, 0x88}},
+ "thksim": {Name: "thksim", CodePoints: []int{8764}, Characters: []byte{0xe2, 0x88, 0xbc}},
+ "thorn": {Name: "thorn", CodePoints: []int{254}, Characters: []byte{0xc3, 0xbe}},
+ "tilde": {Name: "tilde", CodePoints: []int{732}, Characters: []byte{0xcb, 0x9c}},
+ "times": {Name: "times", CodePoints: []int{215}, Characters: []byte{0xc3, 0x97}},
+ "timesb": {Name: "timesb", CodePoints: []int{8864}, Characters: []byte{0xe2, 0x8a, 0xa0}},
+ "timesbar": {Name: "timesbar", CodePoints: []int{10801}, Characters: []byte{0xe2, 0xa8, 0xb1}},
+ "timesd": {Name: "timesd", CodePoints: []int{10800}, Characters: []byte{0xe2, 0xa8, 0xb0}},
+ "tint": {Name: "tint", CodePoints: []int{8749}, Characters: []byte{0xe2, 0x88, 0xad}},
+ "toea": {Name: "toea", CodePoints: []int{10536}, Characters: []byte{0xe2, 0xa4, 0xa8}},
+ "top": {Name: "top", CodePoints: []int{8868}, Characters: []byte{0xe2, 0x8a, 0xa4}},
+ "topbot": {Name: "topbot", CodePoints: []int{9014}, Characters: []byte{0xe2, 0x8c, 0xb6}},
+ "topcir": {Name: "topcir", CodePoints: []int{10993}, Characters: []byte{0xe2, 0xab, 0xb1}},
+ "topf": {Name: "topf", CodePoints: []int{120165}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa5}},
+ "topfork": {Name: "topfork", CodePoints: []int{10970}, Characters: []byte{0xe2, 0xab, 0x9a}},
+ "tosa": {Name: "tosa", CodePoints: []int{10537}, Characters: []byte{0xe2, 0xa4, 0xa9}},
+ "tprime": {Name: "tprime", CodePoints: []int{8244}, Characters: []byte{0xe2, 0x80, 0xb4}},
+ "trade": {Name: "trade", CodePoints: []int{8482}, Characters: []byte{0xe2, 0x84, 0xa2}},
+ "triangle": {Name: "triangle", CodePoints: []int{9653}, Characters: []byte{0xe2, 0x96, 0xb5}},
+ "triangledown": {Name: "triangledown", CodePoints: []int{9663}, Characters: []byte{0xe2, 0x96, 0xbf}},
+ "triangleleft": {Name: "triangleleft", CodePoints: []int{9667}, Characters: []byte{0xe2, 0x97, 0x83}},
+ "trianglelefteq": {Name: "trianglelefteq", CodePoints: []int{8884}, Characters: []byte{0xe2, 0x8a, 0xb4}},
+ "triangleq": {Name: "triangleq", CodePoints: []int{8796}, Characters: []byte{0xe2, 0x89, 0x9c}},
+ "triangleright": {Name: "triangleright", CodePoints: []int{9657}, Characters: []byte{0xe2, 0x96, 0xb9}},
+ "trianglerighteq": {Name: "trianglerighteq", CodePoints: []int{8885}, Characters: []byte{0xe2, 0x8a, 0xb5}},
+ "tridot": {Name: "tridot", CodePoints: []int{9708}, Characters: []byte{0xe2, 0x97, 0xac}},
+ "trie": {Name: "trie", CodePoints: []int{8796}, Characters: []byte{0xe2, 0x89, 0x9c}},
+ "triminus": {Name: "triminus", CodePoints: []int{10810}, Characters: []byte{0xe2, 0xa8, 0xba}},
+ "triplus": {Name: "triplus", CodePoints: []int{10809}, Characters: []byte{0xe2, 0xa8, 0xb9}},
+ "trisb": {Name: "trisb", CodePoints: []int{10701}, Characters: []byte{0xe2, 0xa7, 0x8d}},
+ "tritime": {Name: "tritime", CodePoints: []int{10811}, Characters: []byte{0xe2, 0xa8, 0xbb}},
+ "trpezium": {Name: "trpezium", CodePoints: []int{9186}, Characters: []byte{0xe2, 0x8f, 0xa2}},
+ "tscr": {Name: "tscr", CodePoints: []int{120009}, Characters: []byte{0xf0, 0x9d, 0x93, 0x89}},
+ "tscy": {Name: "tscy", CodePoints: []int{1094}, Characters: []byte{0xd1, 0x86}},
+ "tshcy": {Name: "tshcy", CodePoints: []int{1115}, Characters: []byte{0xd1, 0x9b}},
+ "tstrok": {Name: "tstrok", CodePoints: []int{359}, Characters: []byte{0xc5, 0xa7}},
+ "twixt": {Name: "twixt", CodePoints: []int{8812}, Characters: []byte{0xe2, 0x89, 0xac}},
+ "twoheadleftarrow": {Name: "twoheadleftarrow", CodePoints: []int{8606}, Characters: []byte{0xe2, 0x86, 0x9e}},
+ "twoheadrightarrow": {Name: "twoheadrightarrow", CodePoints: []int{8608}, Characters: []byte{0xe2, 0x86, 0xa0}},
+ "uArr": {Name: "uArr", CodePoints: []int{8657}, Characters: []byte{0xe2, 0x87, 0x91}},
+ "uHar": {Name: "uHar", CodePoints: []int{10595}, Characters: []byte{0xe2, 0xa5, 0xa3}},
+ "uacute": {Name: "uacute", CodePoints: []int{250}, Characters: []byte{0xc3, 0xba}},
+ "uarr": {Name: "uarr", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
+ "ubrcy": {Name: "ubrcy", CodePoints: []int{1118}, Characters: []byte{0xd1, 0x9e}},
+ "ubreve": {Name: "ubreve", CodePoints: []int{365}, Characters: []byte{0xc5, 0xad}},
+ "ucirc": {Name: "ucirc", CodePoints: []int{251}, Characters: []byte{0xc3, 0xbb}},
+ "ucy": {Name: "ucy", CodePoints: []int{1091}, Characters: []byte{0xd1, 0x83}},
+ "udarr": {Name: "udarr", CodePoints: []int{8645}, Characters: []byte{0xe2, 0x87, 0x85}},
+ "udblac": {Name: "udblac", CodePoints: []int{369}, Characters: []byte{0xc5, 0xb1}},
+ "udhar": {Name: "udhar", CodePoints: []int{10606}, Characters: []byte{0xe2, 0xa5, 0xae}},
+ "ufisht": {Name: "ufisht", CodePoints: []int{10622}, Characters: []byte{0xe2, 0xa5, 0xbe}},
+ "ufr": {Name: "ufr", CodePoints: []int{120114}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb2}},
+ "ugrave": {Name: "ugrave", CodePoints: []int{249}, Characters: []byte{0xc3, 0xb9}},
+ "uharl": {Name: "uharl", CodePoints: []int{8639}, Characters: []byte{0xe2, 0x86, 0xbf}},
+ "uharr": {Name: "uharr", CodePoints: []int{8638}, Characters: []byte{0xe2, 0x86, 0xbe}},
+ "uhblk": {Name: "uhblk", CodePoints: []int{9600}, Characters: []byte{0xe2, 0x96, 0x80}},
+ "ulcorn": {Name: "ulcorn", CodePoints: []int{8988}, Characters: []byte{0xe2, 0x8c, 0x9c}},
+ "ulcorner": {Name: "ulcorner", CodePoints: []int{8988}, Characters: []byte{0xe2, 0x8c, 0x9c}},
+ "ulcrop": {Name: "ulcrop", CodePoints: []int{8975}, Characters: []byte{0xe2, 0x8c, 0x8f}},
+ "ultri": {Name: "ultri", CodePoints: []int{9720}, Characters: []byte{0xe2, 0x97, 0xb8}},
+ "umacr": {Name: "umacr", CodePoints: []int{363}, Characters: []byte{0xc5, 0xab}},
+ "uml": {Name: "uml", CodePoints: []int{168}, Characters: []byte{0xc2, 0xa8}},
+ "uogon": {Name: "uogon", CodePoints: []int{371}, Characters: []byte{0xc5, 0xb3}},
+ "uopf": {Name: "uopf", CodePoints: []int{120166}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa6}},
+ "uparrow": {Name: "uparrow", CodePoints: []int{8593}, Characters: []byte{0xe2, 0x86, 0x91}},
+ "updownarrow": {Name: "updownarrow", CodePoints: []int{8597}, Characters: []byte{0xe2, 0x86, 0x95}},
+ "upharpoonleft": {Name: "upharpoonleft", CodePoints: []int{8639}, Characters: []byte{0xe2, 0x86, 0xbf}},
+ "upharpoonright": {Name: "upharpoonright", CodePoints: []int{8638}, Characters: []byte{0xe2, 0x86, 0xbe}},
+ "uplus": {Name: "uplus", CodePoints: []int{8846}, Characters: []byte{0xe2, 0x8a, 0x8e}},
+ "upsi": {Name: "upsi", CodePoints: []int{965}, Characters: []byte{0xcf, 0x85}},
+ "upsih": {Name: "upsih", CodePoints: []int{978}, Characters: []byte{0xcf, 0x92}},
+ "upsilon": {Name: "upsilon", CodePoints: []int{965}, Characters: []byte{0xcf, 0x85}},
+ "upuparrows": {Name: "upuparrows", CodePoints: []int{8648}, Characters: []byte{0xe2, 0x87, 0x88}},
+ "urcorn": {Name: "urcorn", CodePoints: []int{8989}, Characters: []byte{0xe2, 0x8c, 0x9d}},
+ "urcorner": {Name: "urcorner", CodePoints: []int{8989}, Characters: []byte{0xe2, 0x8c, 0x9d}},
+ "urcrop": {Name: "urcrop", CodePoints: []int{8974}, Characters: []byte{0xe2, 0x8c, 0x8e}},
+ "uring": {Name: "uring", CodePoints: []int{367}, Characters: []byte{0xc5, 0xaf}},
+ "urtri": {Name: "urtri", CodePoints: []int{9721}, Characters: []byte{0xe2, 0x97, 0xb9}},
+ "uscr": {Name: "uscr", CodePoints: []int{120010}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8a}},
+ "utdot": {Name: "utdot", CodePoints: []int{8944}, Characters: []byte{0xe2, 0x8b, 0xb0}},
+ "utilde": {Name: "utilde", CodePoints: []int{361}, Characters: []byte{0xc5, 0xa9}},
+ "utri": {Name: "utri", CodePoints: []int{9653}, Characters: []byte{0xe2, 0x96, 0xb5}},
+ "utrif": {Name: "utrif", CodePoints: []int{9652}, Characters: []byte{0xe2, 0x96, 0xb4}},
+ "uuarr": {Name: "uuarr", CodePoints: []int{8648}, Characters: []byte{0xe2, 0x87, 0x88}},
+ "uuml": {Name: "uuml", CodePoints: []int{252}, Characters: []byte{0xc3, 0xbc}},
+ "uwangle": {Name: "uwangle", CodePoints: []int{10663}, Characters: []byte{0xe2, 0xa6, 0xa7}},
+ "vArr": {Name: "vArr", CodePoints: []int{8661}, Characters: []byte{0xe2, 0x87, 0x95}},
+ "vBar": {Name: "vBar", CodePoints: []int{10984}, Characters: []byte{0xe2, 0xab, 0xa8}},
+ "vBarv": {Name: "vBarv", CodePoints: []int{10985}, Characters: []byte{0xe2, 0xab, 0xa9}},
+ "vDash": {Name: "vDash", CodePoints: []int{8872}, Characters: []byte{0xe2, 0x8a, 0xa8}},
+ "vangrt": {Name: "vangrt", CodePoints: []int{10652}, Characters: []byte{0xe2, 0xa6, 0x9c}},
+ "varepsilon": {Name: "varepsilon", CodePoints: []int{1013}, Characters: []byte{0xcf, 0xb5}},
+ "varkappa": {Name: "varkappa", CodePoints: []int{1008}, Characters: []byte{0xcf, 0xb0}},
+ "varnothing": {Name: "varnothing", CodePoints: []int{8709}, Characters: []byte{0xe2, 0x88, 0x85}},
+ "varphi": {Name: "varphi", CodePoints: []int{981}, Characters: []byte{0xcf, 0x95}},
+ "varpi": {Name: "varpi", CodePoints: []int{982}, Characters: []byte{0xcf, 0x96}},
+ "varpropto": {Name: "varpropto", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
+ "varr": {Name: "varr", CodePoints: []int{8597}, Characters: []byte{0xe2, 0x86, 0x95}},
+ "varrho": {Name: "varrho", CodePoints: []int{1009}, Characters: []byte{0xcf, 0xb1}},
+ "varsigma": {Name: "varsigma", CodePoints: []int{962}, Characters: []byte{0xcf, 0x82}},
+ "varsubsetneq": {Name: "varsubsetneq", CodePoints: []int{8842, 65024}, Characters: []byte{0xe2, 0x8a, 0x8a, 0xef, 0xb8, 0x80}},
+ "varsubsetneqq": {Name: "varsubsetneqq", CodePoints: []int{10955, 65024}, Characters: []byte{0xe2, 0xab, 0x8b, 0xef, 0xb8, 0x80}},
+ "varsupsetneq": {Name: "varsupsetneq", CodePoints: []int{8843, 65024}, Characters: []byte{0xe2, 0x8a, 0x8b, 0xef, 0xb8, 0x80}},
+ "varsupsetneqq": {Name: "varsupsetneqq", CodePoints: []int{10956, 65024}, Characters: []byte{0xe2, 0xab, 0x8c, 0xef, 0xb8, 0x80}},
+ "vartheta": {Name: "vartheta", CodePoints: []int{977}, Characters: []byte{0xcf, 0x91}},
+ "vartriangleleft": {Name: "vartriangleleft", CodePoints: []int{8882}, Characters: []byte{0xe2, 0x8a, 0xb2}},
+ "vartriangleright": {Name: "vartriangleright", CodePoints: []int{8883}, Characters: []byte{0xe2, 0x8a, 0xb3}},
+ "vcy": {Name: "vcy", CodePoints: []int{1074}, Characters: []byte{0xd0, 0xb2}},
+ "vdash": {Name: "vdash", CodePoints: []int{8866}, Characters: []byte{0xe2, 0x8a, 0xa2}},
+ "vee": {Name: "vee", CodePoints: []int{8744}, Characters: []byte{0xe2, 0x88, 0xa8}},
+ "veebar": {Name: "veebar", CodePoints: []int{8891}, Characters: []byte{0xe2, 0x8a, 0xbb}},
+ "veeeq": {Name: "veeeq", CodePoints: []int{8794}, Characters: []byte{0xe2, 0x89, 0x9a}},
+ "vellip": {Name: "vellip", CodePoints: []int{8942}, Characters: []byte{0xe2, 0x8b, 0xae}},
+ "verbar": {Name: "verbar", CodePoints: []int{124}, Characters: []byte{0x7c}},
+ "vert": {Name: "vert", CodePoints: []int{124}, Characters: []byte{0x7c}},
+ "vfr": {Name: "vfr", CodePoints: []int{120115}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb3}},
+ "vltri": {Name: "vltri", CodePoints: []int{8882}, Characters: []byte{0xe2, 0x8a, 0xb2}},
+ "vnsub": {Name: "vnsub", CodePoints: []int{8834, 8402}, Characters: []byte{0xe2, 0x8a, 0x82, 0xe2, 0x83, 0x92}},
+ "vnsup": {Name: "vnsup", CodePoints: []int{8835, 8402}, Characters: []byte{0xe2, 0x8a, 0x83, 0xe2, 0x83, 0x92}},
+ "vopf": {Name: "vopf", CodePoints: []int{120167}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa7}},
+ "vprop": {Name: "vprop", CodePoints: []int{8733}, Characters: []byte{0xe2, 0x88, 0x9d}},
+ "vrtri": {Name: "vrtri", CodePoints: []int{8883}, Characters: []byte{0xe2, 0x8a, 0xb3}},
+ "vscr": {Name: "vscr", CodePoints: []int{120011}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8b}},
+ "vsubnE": {Name: "vsubnE", CodePoints: []int{10955, 65024}, Characters: []byte{0xe2, 0xab, 0x8b, 0xef, 0xb8, 0x80}},
+ "vsubne": {Name: "vsubne", CodePoints: []int{8842, 65024}, Characters: []byte{0xe2, 0x8a, 0x8a, 0xef, 0xb8, 0x80}},
+ "vsupnE": {Name: "vsupnE", CodePoints: []int{10956, 65024}, Characters: []byte{0xe2, 0xab, 0x8c, 0xef, 0xb8, 0x80}},
+ "vsupne": {Name: "vsupne", CodePoints: []int{8843, 65024}, Characters: []byte{0xe2, 0x8a, 0x8b, 0xef, 0xb8, 0x80}},
+ "vzigzag": {Name: "vzigzag", CodePoints: []int{10650}, Characters: []byte{0xe2, 0xa6, 0x9a}},
+ "wcirc": {Name: "wcirc", CodePoints: []int{373}, Characters: []byte{0xc5, 0xb5}},
+ "wedbar": {Name: "wedbar", CodePoints: []int{10847}, Characters: []byte{0xe2, 0xa9, 0x9f}},
+ "wedge": {Name: "wedge", CodePoints: []int{8743}, Characters: []byte{0xe2, 0x88, 0xa7}},
+ "wedgeq": {Name: "wedgeq", CodePoints: []int{8793}, Characters: []byte{0xe2, 0x89, 0x99}},
+ "weierp": {Name: "weierp", CodePoints: []int{8472}, Characters: []byte{0xe2, 0x84, 0x98}},
+ "wfr": {Name: "wfr", CodePoints: []int{120116}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb4}},
+ "wopf": {Name: "wopf", CodePoints: []int{120168}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa8}},
+ "wp": {Name: "wp", CodePoints: []int{8472}, Characters: []byte{0xe2, 0x84, 0x98}},
+ "wr": {Name: "wr", CodePoints: []int{8768}, Characters: []byte{0xe2, 0x89, 0x80}},
+ "wreath": {Name: "wreath", CodePoints: []int{8768}, Characters: []byte{0xe2, 0x89, 0x80}},
+ "wscr": {Name: "wscr", CodePoints: []int{120012}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8c}},
+ "xcap": {Name: "xcap", CodePoints: []int{8898}, Characters: []byte{0xe2, 0x8b, 0x82}},
+ "xcirc": {Name: "xcirc", CodePoints: []int{9711}, Characters: []byte{0xe2, 0x97, 0xaf}},
+ "xcup": {Name: "xcup", CodePoints: []int{8899}, Characters: []byte{0xe2, 0x8b, 0x83}},
+ "xdtri": {Name: "xdtri", CodePoints: []int{9661}, Characters: []byte{0xe2, 0x96, 0xbd}},
+ "xfr": {Name: "xfr", CodePoints: []int{120117}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb5}},
+ "xhArr": {Name: "xhArr", CodePoints: []int{10234}, Characters: []byte{0xe2, 0x9f, 0xba}},
+ "xharr": {Name: "xharr", CodePoints: []int{10231}, Characters: []byte{0xe2, 0x9f, 0xb7}},
+ "xi": {Name: "xi", CodePoints: []int{958}, Characters: []byte{0xce, 0xbe}},
+ "xlArr": {Name: "xlArr", CodePoints: []int{10232}, Characters: []byte{0xe2, 0x9f, 0xb8}},
+ "xlarr": {Name: "xlarr", CodePoints: []int{10229}, Characters: []byte{0xe2, 0x9f, 0xb5}},
+ "xmap": {Name: "xmap", CodePoints: []int{10236}, Characters: []byte{0xe2, 0x9f, 0xbc}},
+ "xnis": {Name: "xnis", CodePoints: []int{8955}, Characters: []byte{0xe2, 0x8b, 0xbb}},
+ "xodot": {Name: "xodot", CodePoints: []int{10752}, Characters: []byte{0xe2, 0xa8, 0x80}},
+ "xopf": {Name: "xopf", CodePoints: []int{120169}, Characters: []byte{0xf0, 0x9d, 0x95, 0xa9}},
+ "xoplus": {Name: "xoplus", CodePoints: []int{10753}, Characters: []byte{0xe2, 0xa8, 0x81}},
+ "xotime": {Name: "xotime", CodePoints: []int{10754}, Characters: []byte{0xe2, 0xa8, 0x82}},
+ "xrArr": {Name: "xrArr", CodePoints: []int{10233}, Characters: []byte{0xe2, 0x9f, 0xb9}},
+ "xrarr": {Name: "xrarr", CodePoints: []int{10230}, Characters: []byte{0xe2, 0x9f, 0xb6}},
+ "xscr": {Name: "xscr", CodePoints: []int{120013}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8d}},
+ "xsqcup": {Name: "xsqcup", CodePoints: []int{10758}, Characters: []byte{0xe2, 0xa8, 0x86}},
+ "xuplus": {Name: "xuplus", CodePoints: []int{10756}, Characters: []byte{0xe2, 0xa8, 0x84}},
+ "xutri": {Name: "xutri", CodePoints: []int{9651}, Characters: []byte{0xe2, 0x96, 0xb3}},
+ "xvee": {Name: "xvee", CodePoints: []int{8897}, Characters: []byte{0xe2, 0x8b, 0x81}},
+ "xwedge": {Name: "xwedge", CodePoints: []int{8896}, Characters: []byte{0xe2, 0x8b, 0x80}},
+ "yacute": {Name: "yacute", CodePoints: []int{253}, Characters: []byte{0xc3, 0xbd}},
+ "yacy": {Name: "yacy", CodePoints: []int{1103}, Characters: []byte{0xd1, 0x8f}},
+ "ycirc": {Name: "ycirc", CodePoints: []int{375}, Characters: []byte{0xc5, 0xb7}},
+ "ycy": {Name: "ycy", CodePoints: []int{1099}, Characters: []byte{0xd1, 0x8b}},
+ "yen": {Name: "yen", CodePoints: []int{165}, Characters: []byte{0xc2, 0xa5}},
+ "yfr": {Name: "yfr", CodePoints: []int{120118}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb6}},
+ "yicy": {Name: "yicy", CodePoints: []int{1111}, Characters: []byte{0xd1, 0x97}},
+ "yopf": {Name: "yopf", CodePoints: []int{120170}, Characters: []byte{0xf0, 0x9d, 0x95, 0xaa}},
+ "yscr": {Name: "yscr", CodePoints: []int{120014}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8e}},
+ "yucy": {Name: "yucy", CodePoints: []int{1102}, Characters: []byte{0xd1, 0x8e}},
+ "yuml": {Name: "yuml", CodePoints: []int{255}, Characters: []byte{0xc3, 0xbf}},
+ "zacute": {Name: "zacute", CodePoints: []int{378}, Characters: []byte{0xc5, 0xba}},
+ "zcaron": {Name: "zcaron", CodePoints: []int{382}, Characters: []byte{0xc5, 0xbe}},
+ "zcy": {Name: "zcy", CodePoints: []int{1079}, Characters: []byte{0xd0, 0xb7}},
+ "zdot": {Name: "zdot", CodePoints: []int{380}, Characters: []byte{0xc5, 0xbc}},
+ "zeetrf": {Name: "zeetrf", CodePoints: []int{8488}, Characters: []byte{0xe2, 0x84, 0xa8}},
+ "zeta": {Name: "zeta", CodePoints: []int{950}, Characters: []byte{0xce, 0xb6}},
+ "zfr": {Name: "zfr", CodePoints: []int{120119}, Characters: []byte{0xf0, 0x9d, 0x94, 0xb7}},
+ "zhcy": {Name: "zhcy", CodePoints: []int{1078}, Characters: []byte{0xd0, 0xb6}},
+ "zigrarr": {Name: "zigrarr", CodePoints: []int{8669}, Characters: []byte{0xe2, 0x87, 0x9d}},
+ "zopf": {Name: "zopf", CodePoints: []int{120171}, Characters: []byte{0xf0, 0x9d, 0x95, 0xab}},
+ "zscr": {Name: "zscr", CodePoints: []int{120015}, Characters: []byte{0xf0, 0x9d, 0x93, 0x8f}},
+ "zwj": {Name: "zwj", CodePoints: []int{8205}, Characters: []byte{0xe2, 0x80, 0x8d}},
+ "zwnj": {Name: "zwnj", CodePoints: []int{8204}, Characters: []byte{0xe2, 0x80, 0x8c}},
+}
diff --git a/vendor/github.com/yuin/goldmark/util/unicode_case_folding.go b/vendor/github.com/yuin/goldmark/util/unicode_case_folding.go
new file mode 100644
index 0000000..f0e6aa4
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/unicode_case_folding.go
@@ -0,0 +1,1534 @@
+package util
+
+var unicodeCaseFoldings = map[rune][]rune {
+ 0x41 : []int32{97},
+ 0x42 : []int32{98},
+ 0x43 : []int32{99},
+ 0x44 : []int32{100},
+ 0x45 : []int32{101},
+ 0x46 : []int32{102},
+ 0x47 : []int32{103},
+ 0x48 : []int32{104},
+ 0x49 : []int32{105},
+ 0x4a : []int32{106},
+ 0x4b : []int32{107},
+ 0x4c : []int32{108},
+ 0x4d : []int32{109},
+ 0x4e : []int32{110},
+ 0x4f : []int32{111},
+ 0x50 : []int32{112},
+ 0x51 : []int32{113},
+ 0x52 : []int32{114},
+ 0x53 : []int32{115},
+ 0x54 : []int32{116},
+ 0x55 : []int32{117},
+ 0x56 : []int32{118},
+ 0x57 : []int32{119},
+ 0x58 : []int32{120},
+ 0x59 : []int32{121},
+ 0x5a : []int32{122},
+ 0xb5 : []int32{956},
+ 0xc0 : []int32{224},
+ 0xc1 : []int32{225},
+ 0xc2 : []int32{226},
+ 0xc3 : []int32{227},
+ 0xc4 : []int32{228},
+ 0xc5 : []int32{229},
+ 0xc6 : []int32{230},
+ 0xc7 : []int32{231},
+ 0xc8 : []int32{232},
+ 0xc9 : []int32{233},
+ 0xca : []int32{234},
+ 0xcb : []int32{235},
+ 0xcc : []int32{236},
+ 0xcd : []int32{237},
+ 0xce : []int32{238},
+ 0xcf : []int32{239},
+ 0xd0 : []int32{240},
+ 0xd1 : []int32{241},
+ 0xd2 : []int32{242},
+ 0xd3 : []int32{243},
+ 0xd4 : []int32{244},
+ 0xd5 : []int32{245},
+ 0xd6 : []int32{246},
+ 0xd8 : []int32{248},
+ 0xd9 : []int32{249},
+ 0xda : []int32{250},
+ 0xdb : []int32{251},
+ 0xdc : []int32{252},
+ 0xdd : []int32{253},
+ 0xde : []int32{254},
+ 0xdf : []int32{115, 115},
+ 0x100 : []int32{257},
+ 0x102 : []int32{259},
+ 0x104 : []int32{261},
+ 0x106 : []int32{263},
+ 0x108 : []int32{265},
+ 0x10a : []int32{267},
+ 0x10c : []int32{269},
+ 0x10e : []int32{271},
+ 0x110 : []int32{273},
+ 0x112 : []int32{275},
+ 0x114 : []int32{277},
+ 0x116 : []int32{279},
+ 0x118 : []int32{281},
+ 0x11a : []int32{283},
+ 0x11c : []int32{285},
+ 0x11e : []int32{287},
+ 0x120 : []int32{289},
+ 0x122 : []int32{291},
+ 0x124 : []int32{293},
+ 0x126 : []int32{295},
+ 0x128 : []int32{297},
+ 0x12a : []int32{299},
+ 0x12c : []int32{301},
+ 0x12e : []int32{303},
+ 0x130 : []int32{105, 775},
+ 0x132 : []int32{307},
+ 0x134 : []int32{309},
+ 0x136 : []int32{311},
+ 0x139 : []int32{314},
+ 0x13b : []int32{316},
+ 0x13d : []int32{318},
+ 0x13f : []int32{320},
+ 0x141 : []int32{322},
+ 0x143 : []int32{324},
+ 0x145 : []int32{326},
+ 0x147 : []int32{328},
+ 0x149 : []int32{700, 110},
+ 0x14a : []int32{331},
+ 0x14c : []int32{333},
+ 0x14e : []int32{335},
+ 0x150 : []int32{337},
+ 0x152 : []int32{339},
+ 0x154 : []int32{341},
+ 0x156 : []int32{343},
+ 0x158 : []int32{345},
+ 0x15a : []int32{347},
+ 0x15c : []int32{349},
+ 0x15e : []int32{351},
+ 0x160 : []int32{353},
+ 0x162 : []int32{355},
+ 0x164 : []int32{357},
+ 0x166 : []int32{359},
+ 0x168 : []int32{361},
+ 0x16a : []int32{363},
+ 0x16c : []int32{365},
+ 0x16e : []int32{367},
+ 0x170 : []int32{369},
+ 0x172 : []int32{371},
+ 0x174 : []int32{373},
+ 0x176 : []int32{375},
+ 0x178 : []int32{255},
+ 0x179 : []int32{378},
+ 0x17b : []int32{380},
+ 0x17d : []int32{382},
+ 0x17f : []int32{115},
+ 0x181 : []int32{595},
+ 0x182 : []int32{387},
+ 0x184 : []int32{389},
+ 0x186 : []int32{596},
+ 0x187 : []int32{392},
+ 0x189 : []int32{598},
+ 0x18a : []int32{599},
+ 0x18b : []int32{396},
+ 0x18e : []int32{477},
+ 0x18f : []int32{601},
+ 0x190 : []int32{603},
+ 0x191 : []int32{402},
+ 0x193 : []int32{608},
+ 0x194 : []int32{611},
+ 0x196 : []int32{617},
+ 0x197 : []int32{616},
+ 0x198 : []int32{409},
+ 0x19c : []int32{623},
+ 0x19d : []int32{626},
+ 0x19f : []int32{629},
+ 0x1a0 : []int32{417},
+ 0x1a2 : []int32{419},
+ 0x1a4 : []int32{421},
+ 0x1a6 : []int32{640},
+ 0x1a7 : []int32{424},
+ 0x1a9 : []int32{643},
+ 0x1ac : []int32{429},
+ 0x1ae : []int32{648},
+ 0x1af : []int32{432},
+ 0x1b1 : []int32{650},
+ 0x1b2 : []int32{651},
+ 0x1b3 : []int32{436},
+ 0x1b5 : []int32{438},
+ 0x1b7 : []int32{658},
+ 0x1b8 : []int32{441},
+ 0x1bc : []int32{445},
+ 0x1c4 : []int32{454},
+ 0x1c5 : []int32{454},
+ 0x1c7 : []int32{457},
+ 0x1c8 : []int32{457},
+ 0x1ca : []int32{460},
+ 0x1cb : []int32{460},
+ 0x1cd : []int32{462},
+ 0x1cf : []int32{464},
+ 0x1d1 : []int32{466},
+ 0x1d3 : []int32{468},
+ 0x1d5 : []int32{470},
+ 0x1d7 : []int32{472},
+ 0x1d9 : []int32{474},
+ 0x1db : []int32{476},
+ 0x1de : []int32{479},
+ 0x1e0 : []int32{481},
+ 0x1e2 : []int32{483},
+ 0x1e4 : []int32{485},
+ 0x1e6 : []int32{487},
+ 0x1e8 : []int32{489},
+ 0x1ea : []int32{491},
+ 0x1ec : []int32{493},
+ 0x1ee : []int32{495},
+ 0x1f0 : []int32{106, 780},
+ 0x1f1 : []int32{499},
+ 0x1f2 : []int32{499},
+ 0x1f4 : []int32{501},
+ 0x1f6 : []int32{405},
+ 0x1f7 : []int32{447},
+ 0x1f8 : []int32{505},
+ 0x1fa : []int32{507},
+ 0x1fc : []int32{509},
+ 0x1fe : []int32{511},
+ 0x200 : []int32{513},
+ 0x202 : []int32{515},
+ 0x204 : []int32{517},
+ 0x206 : []int32{519},
+ 0x208 : []int32{521},
+ 0x20a : []int32{523},
+ 0x20c : []int32{525},
+ 0x20e : []int32{527},
+ 0x210 : []int32{529},
+ 0x212 : []int32{531},
+ 0x214 : []int32{533},
+ 0x216 : []int32{535},
+ 0x218 : []int32{537},
+ 0x21a : []int32{539},
+ 0x21c : []int32{541},
+ 0x21e : []int32{543},
+ 0x220 : []int32{414},
+ 0x222 : []int32{547},
+ 0x224 : []int32{549},
+ 0x226 : []int32{551},
+ 0x228 : []int32{553},
+ 0x22a : []int32{555},
+ 0x22c : []int32{557},
+ 0x22e : []int32{559},
+ 0x230 : []int32{561},
+ 0x232 : []int32{563},
+ 0x23a : []int32{11365},
+ 0x23b : []int32{572},
+ 0x23d : []int32{410},
+ 0x23e : []int32{11366},
+ 0x241 : []int32{578},
+ 0x243 : []int32{384},
+ 0x244 : []int32{649},
+ 0x245 : []int32{652},
+ 0x246 : []int32{583},
+ 0x248 : []int32{585},
+ 0x24a : []int32{587},
+ 0x24c : []int32{589},
+ 0x24e : []int32{591},
+ 0x345 : []int32{953},
+ 0x370 : []int32{881},
+ 0x372 : []int32{883},
+ 0x376 : []int32{887},
+ 0x37f : []int32{1011},
+ 0x386 : []int32{940},
+ 0x388 : []int32{941},
+ 0x389 : []int32{942},
+ 0x38a : []int32{943},
+ 0x38c : []int32{972},
+ 0x38e : []int32{973},
+ 0x38f : []int32{974},
+ 0x390 : []int32{953, 776, 769},
+ 0x391 : []int32{945},
+ 0x392 : []int32{946},
+ 0x393 : []int32{947},
+ 0x394 : []int32{948},
+ 0x395 : []int32{949},
+ 0x396 : []int32{950},
+ 0x397 : []int32{951},
+ 0x398 : []int32{952},
+ 0x399 : []int32{953},
+ 0x39a : []int32{954},
+ 0x39b : []int32{955},
+ 0x39c : []int32{956},
+ 0x39d : []int32{957},
+ 0x39e : []int32{958},
+ 0x39f : []int32{959},
+ 0x3a0 : []int32{960},
+ 0x3a1 : []int32{961},
+ 0x3a3 : []int32{963},
+ 0x3a4 : []int32{964},
+ 0x3a5 : []int32{965},
+ 0x3a6 : []int32{966},
+ 0x3a7 : []int32{967},
+ 0x3a8 : []int32{968},
+ 0x3a9 : []int32{969},
+ 0x3aa : []int32{970},
+ 0x3ab : []int32{971},
+ 0x3b0 : []int32{965, 776, 769},
+ 0x3c2 : []int32{963},
+ 0x3cf : []int32{983},
+ 0x3d0 : []int32{946},
+ 0x3d1 : []int32{952},
+ 0x3d5 : []int32{966},
+ 0x3d6 : []int32{960},
+ 0x3d8 : []int32{985},
+ 0x3da : []int32{987},
+ 0x3dc : []int32{989},
+ 0x3de : []int32{991},
+ 0x3e0 : []int32{993},
+ 0x3e2 : []int32{995},
+ 0x3e4 : []int32{997},
+ 0x3e6 : []int32{999},
+ 0x3e8 : []int32{1001},
+ 0x3ea : []int32{1003},
+ 0x3ec : []int32{1005},
+ 0x3ee : []int32{1007},
+ 0x3f0 : []int32{954},
+ 0x3f1 : []int32{961},
+ 0x3f4 : []int32{952},
+ 0x3f5 : []int32{949},
+ 0x3f7 : []int32{1016},
+ 0x3f9 : []int32{1010},
+ 0x3fa : []int32{1019},
+ 0x3fd : []int32{891},
+ 0x3fe : []int32{892},
+ 0x3ff : []int32{893},
+ 0x400 : []int32{1104},
+ 0x401 : []int32{1105},
+ 0x402 : []int32{1106},
+ 0x403 : []int32{1107},
+ 0x404 : []int32{1108},
+ 0x405 : []int32{1109},
+ 0x406 : []int32{1110},
+ 0x407 : []int32{1111},
+ 0x408 : []int32{1112},
+ 0x409 : []int32{1113},
+ 0x40a : []int32{1114},
+ 0x40b : []int32{1115},
+ 0x40c : []int32{1116},
+ 0x40d : []int32{1117},
+ 0x40e : []int32{1118},
+ 0x40f : []int32{1119},
+ 0x410 : []int32{1072},
+ 0x411 : []int32{1073},
+ 0x412 : []int32{1074},
+ 0x413 : []int32{1075},
+ 0x414 : []int32{1076},
+ 0x415 : []int32{1077},
+ 0x416 : []int32{1078},
+ 0x417 : []int32{1079},
+ 0x418 : []int32{1080},
+ 0x419 : []int32{1081},
+ 0x41a : []int32{1082},
+ 0x41b : []int32{1083},
+ 0x41c : []int32{1084},
+ 0x41d : []int32{1085},
+ 0x41e : []int32{1086},
+ 0x41f : []int32{1087},
+ 0x420 : []int32{1088},
+ 0x421 : []int32{1089},
+ 0x422 : []int32{1090},
+ 0x423 : []int32{1091},
+ 0x424 : []int32{1092},
+ 0x425 : []int32{1093},
+ 0x426 : []int32{1094},
+ 0x427 : []int32{1095},
+ 0x428 : []int32{1096},
+ 0x429 : []int32{1097},
+ 0x42a : []int32{1098},
+ 0x42b : []int32{1099},
+ 0x42c : []int32{1100},
+ 0x42d : []int32{1101},
+ 0x42e : []int32{1102},
+ 0x42f : []int32{1103},
+ 0x460 : []int32{1121},
+ 0x462 : []int32{1123},
+ 0x464 : []int32{1125},
+ 0x466 : []int32{1127},
+ 0x468 : []int32{1129},
+ 0x46a : []int32{1131},
+ 0x46c : []int32{1133},
+ 0x46e : []int32{1135},
+ 0x470 : []int32{1137},
+ 0x472 : []int32{1139},
+ 0x474 : []int32{1141},
+ 0x476 : []int32{1143},
+ 0x478 : []int32{1145},
+ 0x47a : []int32{1147},
+ 0x47c : []int32{1149},
+ 0x47e : []int32{1151},
+ 0x480 : []int32{1153},
+ 0x48a : []int32{1163},
+ 0x48c : []int32{1165},
+ 0x48e : []int32{1167},
+ 0x490 : []int32{1169},
+ 0x492 : []int32{1171},
+ 0x494 : []int32{1173},
+ 0x496 : []int32{1175},
+ 0x498 : []int32{1177},
+ 0x49a : []int32{1179},
+ 0x49c : []int32{1181},
+ 0x49e : []int32{1183},
+ 0x4a0 : []int32{1185},
+ 0x4a2 : []int32{1187},
+ 0x4a4 : []int32{1189},
+ 0x4a6 : []int32{1191},
+ 0x4a8 : []int32{1193},
+ 0x4aa : []int32{1195},
+ 0x4ac : []int32{1197},
+ 0x4ae : []int32{1199},
+ 0x4b0 : []int32{1201},
+ 0x4b2 : []int32{1203},
+ 0x4b4 : []int32{1205},
+ 0x4b6 : []int32{1207},
+ 0x4b8 : []int32{1209},
+ 0x4ba : []int32{1211},
+ 0x4bc : []int32{1213},
+ 0x4be : []int32{1215},
+ 0x4c0 : []int32{1231},
+ 0x4c1 : []int32{1218},
+ 0x4c3 : []int32{1220},
+ 0x4c5 : []int32{1222},
+ 0x4c7 : []int32{1224},
+ 0x4c9 : []int32{1226},
+ 0x4cb : []int32{1228},
+ 0x4cd : []int32{1230},
+ 0x4d0 : []int32{1233},
+ 0x4d2 : []int32{1235},
+ 0x4d4 : []int32{1237},
+ 0x4d6 : []int32{1239},
+ 0x4d8 : []int32{1241},
+ 0x4da : []int32{1243},
+ 0x4dc : []int32{1245},
+ 0x4de : []int32{1247},
+ 0x4e0 : []int32{1249},
+ 0x4e2 : []int32{1251},
+ 0x4e4 : []int32{1253},
+ 0x4e6 : []int32{1255},
+ 0x4e8 : []int32{1257},
+ 0x4ea : []int32{1259},
+ 0x4ec : []int32{1261},
+ 0x4ee : []int32{1263},
+ 0x4f0 : []int32{1265},
+ 0x4f2 : []int32{1267},
+ 0x4f4 : []int32{1269},
+ 0x4f6 : []int32{1271},
+ 0x4f8 : []int32{1273},
+ 0x4fa : []int32{1275},
+ 0x4fc : []int32{1277},
+ 0x4fe : []int32{1279},
+ 0x500 : []int32{1281},
+ 0x502 : []int32{1283},
+ 0x504 : []int32{1285},
+ 0x506 : []int32{1287},
+ 0x508 : []int32{1289},
+ 0x50a : []int32{1291},
+ 0x50c : []int32{1293},
+ 0x50e : []int32{1295},
+ 0x510 : []int32{1297},
+ 0x512 : []int32{1299},
+ 0x514 : []int32{1301},
+ 0x516 : []int32{1303},
+ 0x518 : []int32{1305},
+ 0x51a : []int32{1307},
+ 0x51c : []int32{1309},
+ 0x51e : []int32{1311},
+ 0x520 : []int32{1313},
+ 0x522 : []int32{1315},
+ 0x524 : []int32{1317},
+ 0x526 : []int32{1319},
+ 0x528 : []int32{1321},
+ 0x52a : []int32{1323},
+ 0x52c : []int32{1325},
+ 0x52e : []int32{1327},
+ 0x531 : []int32{1377},
+ 0x532 : []int32{1378},
+ 0x533 : []int32{1379},
+ 0x534 : []int32{1380},
+ 0x535 : []int32{1381},
+ 0x536 : []int32{1382},
+ 0x537 : []int32{1383},
+ 0x538 : []int32{1384},
+ 0x539 : []int32{1385},
+ 0x53a : []int32{1386},
+ 0x53b : []int32{1387},
+ 0x53c : []int32{1388},
+ 0x53d : []int32{1389},
+ 0x53e : []int32{1390},
+ 0x53f : []int32{1391},
+ 0x540 : []int32{1392},
+ 0x541 : []int32{1393},
+ 0x542 : []int32{1394},
+ 0x543 : []int32{1395},
+ 0x544 : []int32{1396},
+ 0x545 : []int32{1397},
+ 0x546 : []int32{1398},
+ 0x547 : []int32{1399},
+ 0x548 : []int32{1400},
+ 0x549 : []int32{1401},
+ 0x54a : []int32{1402},
+ 0x54b : []int32{1403},
+ 0x54c : []int32{1404},
+ 0x54d : []int32{1405},
+ 0x54e : []int32{1406},
+ 0x54f : []int32{1407},
+ 0x550 : []int32{1408},
+ 0x551 : []int32{1409},
+ 0x552 : []int32{1410},
+ 0x553 : []int32{1411},
+ 0x554 : []int32{1412},
+ 0x555 : []int32{1413},
+ 0x556 : []int32{1414},
+ 0x587 : []int32{1381, 1410},
+ 0x10a0 : []int32{11520},
+ 0x10a1 : []int32{11521},
+ 0x10a2 : []int32{11522},
+ 0x10a3 : []int32{11523},
+ 0x10a4 : []int32{11524},
+ 0x10a5 : []int32{11525},
+ 0x10a6 : []int32{11526},
+ 0x10a7 : []int32{11527},
+ 0x10a8 : []int32{11528},
+ 0x10a9 : []int32{11529},
+ 0x10aa : []int32{11530},
+ 0x10ab : []int32{11531},
+ 0x10ac : []int32{11532},
+ 0x10ad : []int32{11533},
+ 0x10ae : []int32{11534},
+ 0x10af : []int32{11535},
+ 0x10b0 : []int32{11536},
+ 0x10b1 : []int32{11537},
+ 0x10b2 : []int32{11538},
+ 0x10b3 : []int32{11539},
+ 0x10b4 : []int32{11540},
+ 0x10b5 : []int32{11541},
+ 0x10b6 : []int32{11542},
+ 0x10b7 : []int32{11543},
+ 0x10b8 : []int32{11544},
+ 0x10b9 : []int32{11545},
+ 0x10ba : []int32{11546},
+ 0x10bb : []int32{11547},
+ 0x10bc : []int32{11548},
+ 0x10bd : []int32{11549},
+ 0x10be : []int32{11550},
+ 0x10bf : []int32{11551},
+ 0x10c0 : []int32{11552},
+ 0x10c1 : []int32{11553},
+ 0x10c2 : []int32{11554},
+ 0x10c3 : []int32{11555},
+ 0x10c4 : []int32{11556},
+ 0x10c5 : []int32{11557},
+ 0x10c7 : []int32{11559},
+ 0x10cd : []int32{11565},
+ 0x13f8 : []int32{5104},
+ 0x13f9 : []int32{5105},
+ 0x13fa : []int32{5106},
+ 0x13fb : []int32{5107},
+ 0x13fc : []int32{5108},
+ 0x13fd : []int32{5109},
+ 0x1c80 : []int32{1074},
+ 0x1c81 : []int32{1076},
+ 0x1c82 : []int32{1086},
+ 0x1c83 : []int32{1089},
+ 0x1c84 : []int32{1090},
+ 0x1c85 : []int32{1090},
+ 0x1c86 : []int32{1098},
+ 0x1c87 : []int32{1123},
+ 0x1c88 : []int32{42571},
+ 0x1c90 : []int32{4304},
+ 0x1c91 : []int32{4305},
+ 0x1c92 : []int32{4306},
+ 0x1c93 : []int32{4307},
+ 0x1c94 : []int32{4308},
+ 0x1c95 : []int32{4309},
+ 0x1c96 : []int32{4310},
+ 0x1c97 : []int32{4311},
+ 0x1c98 : []int32{4312},
+ 0x1c99 : []int32{4313},
+ 0x1c9a : []int32{4314},
+ 0x1c9b : []int32{4315},
+ 0x1c9c : []int32{4316},
+ 0x1c9d : []int32{4317},
+ 0x1c9e : []int32{4318},
+ 0x1c9f : []int32{4319},
+ 0x1ca0 : []int32{4320},
+ 0x1ca1 : []int32{4321},
+ 0x1ca2 : []int32{4322},
+ 0x1ca3 : []int32{4323},
+ 0x1ca4 : []int32{4324},
+ 0x1ca5 : []int32{4325},
+ 0x1ca6 : []int32{4326},
+ 0x1ca7 : []int32{4327},
+ 0x1ca8 : []int32{4328},
+ 0x1ca9 : []int32{4329},
+ 0x1caa : []int32{4330},
+ 0x1cab : []int32{4331},
+ 0x1cac : []int32{4332},
+ 0x1cad : []int32{4333},
+ 0x1cae : []int32{4334},
+ 0x1caf : []int32{4335},
+ 0x1cb0 : []int32{4336},
+ 0x1cb1 : []int32{4337},
+ 0x1cb2 : []int32{4338},
+ 0x1cb3 : []int32{4339},
+ 0x1cb4 : []int32{4340},
+ 0x1cb5 : []int32{4341},
+ 0x1cb6 : []int32{4342},
+ 0x1cb7 : []int32{4343},
+ 0x1cb8 : []int32{4344},
+ 0x1cb9 : []int32{4345},
+ 0x1cba : []int32{4346},
+ 0x1cbd : []int32{4349},
+ 0x1cbe : []int32{4350},
+ 0x1cbf : []int32{4351},
+ 0x1e00 : []int32{7681},
+ 0x1e02 : []int32{7683},
+ 0x1e04 : []int32{7685},
+ 0x1e06 : []int32{7687},
+ 0x1e08 : []int32{7689},
+ 0x1e0a : []int32{7691},
+ 0x1e0c : []int32{7693},
+ 0x1e0e : []int32{7695},
+ 0x1e10 : []int32{7697},
+ 0x1e12 : []int32{7699},
+ 0x1e14 : []int32{7701},
+ 0x1e16 : []int32{7703},
+ 0x1e18 : []int32{7705},
+ 0x1e1a : []int32{7707},
+ 0x1e1c : []int32{7709},
+ 0x1e1e : []int32{7711},
+ 0x1e20 : []int32{7713},
+ 0x1e22 : []int32{7715},
+ 0x1e24 : []int32{7717},
+ 0x1e26 : []int32{7719},
+ 0x1e28 : []int32{7721},
+ 0x1e2a : []int32{7723},
+ 0x1e2c : []int32{7725},
+ 0x1e2e : []int32{7727},
+ 0x1e30 : []int32{7729},
+ 0x1e32 : []int32{7731},
+ 0x1e34 : []int32{7733},
+ 0x1e36 : []int32{7735},
+ 0x1e38 : []int32{7737},
+ 0x1e3a : []int32{7739},
+ 0x1e3c : []int32{7741},
+ 0x1e3e : []int32{7743},
+ 0x1e40 : []int32{7745},
+ 0x1e42 : []int32{7747},
+ 0x1e44 : []int32{7749},
+ 0x1e46 : []int32{7751},
+ 0x1e48 : []int32{7753},
+ 0x1e4a : []int32{7755},
+ 0x1e4c : []int32{7757},
+ 0x1e4e : []int32{7759},
+ 0x1e50 : []int32{7761},
+ 0x1e52 : []int32{7763},
+ 0x1e54 : []int32{7765},
+ 0x1e56 : []int32{7767},
+ 0x1e58 : []int32{7769},
+ 0x1e5a : []int32{7771},
+ 0x1e5c : []int32{7773},
+ 0x1e5e : []int32{7775},
+ 0x1e60 : []int32{7777},
+ 0x1e62 : []int32{7779},
+ 0x1e64 : []int32{7781},
+ 0x1e66 : []int32{7783},
+ 0x1e68 : []int32{7785},
+ 0x1e6a : []int32{7787},
+ 0x1e6c : []int32{7789},
+ 0x1e6e : []int32{7791},
+ 0x1e70 : []int32{7793},
+ 0x1e72 : []int32{7795},
+ 0x1e74 : []int32{7797},
+ 0x1e76 : []int32{7799},
+ 0x1e78 : []int32{7801},
+ 0x1e7a : []int32{7803},
+ 0x1e7c : []int32{7805},
+ 0x1e7e : []int32{7807},
+ 0x1e80 : []int32{7809},
+ 0x1e82 : []int32{7811},
+ 0x1e84 : []int32{7813},
+ 0x1e86 : []int32{7815},
+ 0x1e88 : []int32{7817},
+ 0x1e8a : []int32{7819},
+ 0x1e8c : []int32{7821},
+ 0x1e8e : []int32{7823},
+ 0x1e90 : []int32{7825},
+ 0x1e92 : []int32{7827},
+ 0x1e94 : []int32{7829},
+ 0x1e96 : []int32{104, 817},
+ 0x1e97 : []int32{116, 776},
+ 0x1e98 : []int32{119, 778},
+ 0x1e99 : []int32{121, 778},
+ 0x1e9a : []int32{97, 702},
+ 0x1e9b : []int32{7777},
+ 0x1e9e : []int32{115, 115},
+ 0x1ea0 : []int32{7841},
+ 0x1ea2 : []int32{7843},
+ 0x1ea4 : []int32{7845},
+ 0x1ea6 : []int32{7847},
+ 0x1ea8 : []int32{7849},
+ 0x1eaa : []int32{7851},
+ 0x1eac : []int32{7853},
+ 0x1eae : []int32{7855},
+ 0x1eb0 : []int32{7857},
+ 0x1eb2 : []int32{7859},
+ 0x1eb4 : []int32{7861},
+ 0x1eb6 : []int32{7863},
+ 0x1eb8 : []int32{7865},
+ 0x1eba : []int32{7867},
+ 0x1ebc : []int32{7869},
+ 0x1ebe : []int32{7871},
+ 0x1ec0 : []int32{7873},
+ 0x1ec2 : []int32{7875},
+ 0x1ec4 : []int32{7877},
+ 0x1ec6 : []int32{7879},
+ 0x1ec8 : []int32{7881},
+ 0x1eca : []int32{7883},
+ 0x1ecc : []int32{7885},
+ 0x1ece : []int32{7887},
+ 0x1ed0 : []int32{7889},
+ 0x1ed2 : []int32{7891},
+ 0x1ed4 : []int32{7893},
+ 0x1ed6 : []int32{7895},
+ 0x1ed8 : []int32{7897},
+ 0x1eda : []int32{7899},
+ 0x1edc : []int32{7901},
+ 0x1ede : []int32{7903},
+ 0x1ee0 : []int32{7905},
+ 0x1ee2 : []int32{7907},
+ 0x1ee4 : []int32{7909},
+ 0x1ee6 : []int32{7911},
+ 0x1ee8 : []int32{7913},
+ 0x1eea : []int32{7915},
+ 0x1eec : []int32{7917},
+ 0x1eee : []int32{7919},
+ 0x1ef0 : []int32{7921},
+ 0x1ef2 : []int32{7923},
+ 0x1ef4 : []int32{7925},
+ 0x1ef6 : []int32{7927},
+ 0x1ef8 : []int32{7929},
+ 0x1efa : []int32{7931},
+ 0x1efc : []int32{7933},
+ 0x1efe : []int32{7935},
+ 0x1f08 : []int32{7936},
+ 0x1f09 : []int32{7937},
+ 0x1f0a : []int32{7938},
+ 0x1f0b : []int32{7939},
+ 0x1f0c : []int32{7940},
+ 0x1f0d : []int32{7941},
+ 0x1f0e : []int32{7942},
+ 0x1f0f : []int32{7943},
+ 0x1f18 : []int32{7952},
+ 0x1f19 : []int32{7953},
+ 0x1f1a : []int32{7954},
+ 0x1f1b : []int32{7955},
+ 0x1f1c : []int32{7956},
+ 0x1f1d : []int32{7957},
+ 0x1f28 : []int32{7968},
+ 0x1f29 : []int32{7969},
+ 0x1f2a : []int32{7970},
+ 0x1f2b : []int32{7971},
+ 0x1f2c : []int32{7972},
+ 0x1f2d : []int32{7973},
+ 0x1f2e : []int32{7974},
+ 0x1f2f : []int32{7975},
+ 0x1f38 : []int32{7984},
+ 0x1f39 : []int32{7985},
+ 0x1f3a : []int32{7986},
+ 0x1f3b : []int32{7987},
+ 0x1f3c : []int32{7988},
+ 0x1f3d : []int32{7989},
+ 0x1f3e : []int32{7990},
+ 0x1f3f : []int32{7991},
+ 0x1f48 : []int32{8000},
+ 0x1f49 : []int32{8001},
+ 0x1f4a : []int32{8002},
+ 0x1f4b : []int32{8003},
+ 0x1f4c : []int32{8004},
+ 0x1f4d : []int32{8005},
+ 0x1f50 : []int32{965, 787},
+ 0x1f52 : []int32{965, 787, 768},
+ 0x1f54 : []int32{965, 787, 769},
+ 0x1f56 : []int32{965, 787, 834},
+ 0x1f59 : []int32{8017},
+ 0x1f5b : []int32{8019},
+ 0x1f5d : []int32{8021},
+ 0x1f5f : []int32{8023},
+ 0x1f68 : []int32{8032},
+ 0x1f69 : []int32{8033},
+ 0x1f6a : []int32{8034},
+ 0x1f6b : []int32{8035},
+ 0x1f6c : []int32{8036},
+ 0x1f6d : []int32{8037},
+ 0x1f6e : []int32{8038},
+ 0x1f6f : []int32{8039},
+ 0x1f80 : []int32{7936, 953},
+ 0x1f81 : []int32{7937, 953},
+ 0x1f82 : []int32{7938, 953},
+ 0x1f83 : []int32{7939, 953},
+ 0x1f84 : []int32{7940, 953},
+ 0x1f85 : []int32{7941, 953},
+ 0x1f86 : []int32{7942, 953},
+ 0x1f87 : []int32{7943, 953},
+ 0x1f88 : []int32{7936, 953},
+ 0x1f89 : []int32{7937, 953},
+ 0x1f8a : []int32{7938, 953},
+ 0x1f8b : []int32{7939, 953},
+ 0x1f8c : []int32{7940, 953},
+ 0x1f8d : []int32{7941, 953},
+ 0x1f8e : []int32{7942, 953},
+ 0x1f8f : []int32{7943, 953},
+ 0x1f90 : []int32{7968, 953},
+ 0x1f91 : []int32{7969, 953},
+ 0x1f92 : []int32{7970, 953},
+ 0x1f93 : []int32{7971, 953},
+ 0x1f94 : []int32{7972, 953},
+ 0x1f95 : []int32{7973, 953},
+ 0x1f96 : []int32{7974, 953},
+ 0x1f97 : []int32{7975, 953},
+ 0x1f98 : []int32{7968, 953},
+ 0x1f99 : []int32{7969, 953},
+ 0x1f9a : []int32{7970, 953},
+ 0x1f9b : []int32{7971, 953},
+ 0x1f9c : []int32{7972, 953},
+ 0x1f9d : []int32{7973, 953},
+ 0x1f9e : []int32{7974, 953},
+ 0x1f9f : []int32{7975, 953},
+ 0x1fa0 : []int32{8032, 953},
+ 0x1fa1 : []int32{8033, 953},
+ 0x1fa2 : []int32{8034, 953},
+ 0x1fa3 : []int32{8035, 953},
+ 0x1fa4 : []int32{8036, 953},
+ 0x1fa5 : []int32{8037, 953},
+ 0x1fa6 : []int32{8038, 953},
+ 0x1fa7 : []int32{8039, 953},
+ 0x1fa8 : []int32{8032, 953},
+ 0x1fa9 : []int32{8033, 953},
+ 0x1faa : []int32{8034, 953},
+ 0x1fab : []int32{8035, 953},
+ 0x1fac : []int32{8036, 953},
+ 0x1fad : []int32{8037, 953},
+ 0x1fae : []int32{8038, 953},
+ 0x1faf : []int32{8039, 953},
+ 0x1fb2 : []int32{8048, 953},
+ 0x1fb3 : []int32{945, 953},
+ 0x1fb4 : []int32{940, 953},
+ 0x1fb6 : []int32{945, 834},
+ 0x1fb7 : []int32{945, 834, 953},
+ 0x1fb8 : []int32{8112},
+ 0x1fb9 : []int32{8113},
+ 0x1fba : []int32{8048},
+ 0x1fbb : []int32{8049},
+ 0x1fbc : []int32{945, 953},
+ 0x1fbe : []int32{953},
+ 0x1fc2 : []int32{8052, 953},
+ 0x1fc3 : []int32{951, 953},
+ 0x1fc4 : []int32{942, 953},
+ 0x1fc6 : []int32{951, 834},
+ 0x1fc7 : []int32{951, 834, 953},
+ 0x1fc8 : []int32{8050},
+ 0x1fc9 : []int32{8051},
+ 0x1fca : []int32{8052},
+ 0x1fcb : []int32{8053},
+ 0x1fcc : []int32{951, 953},
+ 0x1fd2 : []int32{953, 776, 768},
+ 0x1fd3 : []int32{953, 776, 769},
+ 0x1fd6 : []int32{953, 834},
+ 0x1fd7 : []int32{953, 776, 834},
+ 0x1fd8 : []int32{8144},
+ 0x1fd9 : []int32{8145},
+ 0x1fda : []int32{8054},
+ 0x1fdb : []int32{8055},
+ 0x1fe2 : []int32{965, 776, 768},
+ 0x1fe3 : []int32{965, 776, 769},
+ 0x1fe4 : []int32{961, 787},
+ 0x1fe6 : []int32{965, 834},
+ 0x1fe7 : []int32{965, 776, 834},
+ 0x1fe8 : []int32{8160},
+ 0x1fe9 : []int32{8161},
+ 0x1fea : []int32{8058},
+ 0x1feb : []int32{8059},
+ 0x1fec : []int32{8165},
+ 0x1ff2 : []int32{8060, 953},
+ 0x1ff3 : []int32{969, 953},
+ 0x1ff4 : []int32{974, 953},
+ 0x1ff6 : []int32{969, 834},
+ 0x1ff7 : []int32{969, 834, 953},
+ 0x1ff8 : []int32{8056},
+ 0x1ff9 : []int32{8057},
+ 0x1ffa : []int32{8060},
+ 0x1ffb : []int32{8061},
+ 0x1ffc : []int32{969, 953},
+ 0x2126 : []int32{969},
+ 0x212a : []int32{107},
+ 0x212b : []int32{229},
+ 0x2132 : []int32{8526},
+ 0x2160 : []int32{8560},
+ 0x2161 : []int32{8561},
+ 0x2162 : []int32{8562},
+ 0x2163 : []int32{8563},
+ 0x2164 : []int32{8564},
+ 0x2165 : []int32{8565},
+ 0x2166 : []int32{8566},
+ 0x2167 : []int32{8567},
+ 0x2168 : []int32{8568},
+ 0x2169 : []int32{8569},
+ 0x216a : []int32{8570},
+ 0x216b : []int32{8571},
+ 0x216c : []int32{8572},
+ 0x216d : []int32{8573},
+ 0x216e : []int32{8574},
+ 0x216f : []int32{8575},
+ 0x2183 : []int32{8580},
+ 0x24b6 : []int32{9424},
+ 0x24b7 : []int32{9425},
+ 0x24b8 : []int32{9426},
+ 0x24b9 : []int32{9427},
+ 0x24ba : []int32{9428},
+ 0x24bb : []int32{9429},
+ 0x24bc : []int32{9430},
+ 0x24bd : []int32{9431},
+ 0x24be : []int32{9432},
+ 0x24bf : []int32{9433},
+ 0x24c0 : []int32{9434},
+ 0x24c1 : []int32{9435},
+ 0x24c2 : []int32{9436},
+ 0x24c3 : []int32{9437},
+ 0x24c4 : []int32{9438},
+ 0x24c5 : []int32{9439},
+ 0x24c6 : []int32{9440},
+ 0x24c7 : []int32{9441},
+ 0x24c8 : []int32{9442},
+ 0x24c9 : []int32{9443},
+ 0x24ca : []int32{9444},
+ 0x24cb : []int32{9445},
+ 0x24cc : []int32{9446},
+ 0x24cd : []int32{9447},
+ 0x24ce : []int32{9448},
+ 0x24cf : []int32{9449},
+ 0x2c00 : []int32{11312},
+ 0x2c01 : []int32{11313},
+ 0x2c02 : []int32{11314},
+ 0x2c03 : []int32{11315},
+ 0x2c04 : []int32{11316},
+ 0x2c05 : []int32{11317},
+ 0x2c06 : []int32{11318},
+ 0x2c07 : []int32{11319},
+ 0x2c08 : []int32{11320},
+ 0x2c09 : []int32{11321},
+ 0x2c0a : []int32{11322},
+ 0x2c0b : []int32{11323},
+ 0x2c0c : []int32{11324},
+ 0x2c0d : []int32{11325},
+ 0x2c0e : []int32{11326},
+ 0x2c0f : []int32{11327},
+ 0x2c10 : []int32{11328},
+ 0x2c11 : []int32{11329},
+ 0x2c12 : []int32{11330},
+ 0x2c13 : []int32{11331},
+ 0x2c14 : []int32{11332},
+ 0x2c15 : []int32{11333},
+ 0x2c16 : []int32{11334},
+ 0x2c17 : []int32{11335},
+ 0x2c18 : []int32{11336},
+ 0x2c19 : []int32{11337},
+ 0x2c1a : []int32{11338},
+ 0x2c1b : []int32{11339},
+ 0x2c1c : []int32{11340},
+ 0x2c1d : []int32{11341},
+ 0x2c1e : []int32{11342},
+ 0x2c1f : []int32{11343},
+ 0x2c20 : []int32{11344},
+ 0x2c21 : []int32{11345},
+ 0x2c22 : []int32{11346},
+ 0x2c23 : []int32{11347},
+ 0x2c24 : []int32{11348},
+ 0x2c25 : []int32{11349},
+ 0x2c26 : []int32{11350},
+ 0x2c27 : []int32{11351},
+ 0x2c28 : []int32{11352},
+ 0x2c29 : []int32{11353},
+ 0x2c2a : []int32{11354},
+ 0x2c2b : []int32{11355},
+ 0x2c2c : []int32{11356},
+ 0x2c2d : []int32{11357},
+ 0x2c2e : []int32{11358},
+ 0x2c2f : []int32{11359},
+ 0x2c60 : []int32{11361},
+ 0x2c62 : []int32{619},
+ 0x2c63 : []int32{7549},
+ 0x2c64 : []int32{637},
+ 0x2c67 : []int32{11368},
+ 0x2c69 : []int32{11370},
+ 0x2c6b : []int32{11372},
+ 0x2c6d : []int32{593},
+ 0x2c6e : []int32{625},
+ 0x2c6f : []int32{592},
+ 0x2c70 : []int32{594},
+ 0x2c72 : []int32{11379},
+ 0x2c75 : []int32{11382},
+ 0x2c7e : []int32{575},
+ 0x2c7f : []int32{576},
+ 0x2c80 : []int32{11393},
+ 0x2c82 : []int32{11395},
+ 0x2c84 : []int32{11397},
+ 0x2c86 : []int32{11399},
+ 0x2c88 : []int32{11401},
+ 0x2c8a : []int32{11403},
+ 0x2c8c : []int32{11405},
+ 0x2c8e : []int32{11407},
+ 0x2c90 : []int32{11409},
+ 0x2c92 : []int32{11411},
+ 0x2c94 : []int32{11413},
+ 0x2c96 : []int32{11415},
+ 0x2c98 : []int32{11417},
+ 0x2c9a : []int32{11419},
+ 0x2c9c : []int32{11421},
+ 0x2c9e : []int32{11423},
+ 0x2ca0 : []int32{11425},
+ 0x2ca2 : []int32{11427},
+ 0x2ca4 : []int32{11429},
+ 0x2ca6 : []int32{11431},
+ 0x2ca8 : []int32{11433},
+ 0x2caa : []int32{11435},
+ 0x2cac : []int32{11437},
+ 0x2cae : []int32{11439},
+ 0x2cb0 : []int32{11441},
+ 0x2cb2 : []int32{11443},
+ 0x2cb4 : []int32{11445},
+ 0x2cb6 : []int32{11447},
+ 0x2cb8 : []int32{11449},
+ 0x2cba : []int32{11451},
+ 0x2cbc : []int32{11453},
+ 0x2cbe : []int32{11455},
+ 0x2cc0 : []int32{11457},
+ 0x2cc2 : []int32{11459},
+ 0x2cc4 : []int32{11461},
+ 0x2cc6 : []int32{11463},
+ 0x2cc8 : []int32{11465},
+ 0x2cca : []int32{11467},
+ 0x2ccc : []int32{11469},
+ 0x2cce : []int32{11471},
+ 0x2cd0 : []int32{11473},
+ 0x2cd2 : []int32{11475},
+ 0x2cd4 : []int32{11477},
+ 0x2cd6 : []int32{11479},
+ 0x2cd8 : []int32{11481},
+ 0x2cda : []int32{11483},
+ 0x2cdc : []int32{11485},
+ 0x2cde : []int32{11487},
+ 0x2ce0 : []int32{11489},
+ 0x2ce2 : []int32{11491},
+ 0x2ceb : []int32{11500},
+ 0x2ced : []int32{11502},
+ 0x2cf2 : []int32{11507},
+ 0xa640 : []int32{42561},
+ 0xa642 : []int32{42563},
+ 0xa644 : []int32{42565},
+ 0xa646 : []int32{42567},
+ 0xa648 : []int32{42569},
+ 0xa64a : []int32{42571},
+ 0xa64c : []int32{42573},
+ 0xa64e : []int32{42575},
+ 0xa650 : []int32{42577},
+ 0xa652 : []int32{42579},
+ 0xa654 : []int32{42581},
+ 0xa656 : []int32{42583},
+ 0xa658 : []int32{42585},
+ 0xa65a : []int32{42587},
+ 0xa65c : []int32{42589},
+ 0xa65e : []int32{42591},
+ 0xa660 : []int32{42593},
+ 0xa662 : []int32{42595},
+ 0xa664 : []int32{42597},
+ 0xa666 : []int32{42599},
+ 0xa668 : []int32{42601},
+ 0xa66a : []int32{42603},
+ 0xa66c : []int32{42605},
+ 0xa680 : []int32{42625},
+ 0xa682 : []int32{42627},
+ 0xa684 : []int32{42629},
+ 0xa686 : []int32{42631},
+ 0xa688 : []int32{42633},
+ 0xa68a : []int32{42635},
+ 0xa68c : []int32{42637},
+ 0xa68e : []int32{42639},
+ 0xa690 : []int32{42641},
+ 0xa692 : []int32{42643},
+ 0xa694 : []int32{42645},
+ 0xa696 : []int32{42647},
+ 0xa698 : []int32{42649},
+ 0xa69a : []int32{42651},
+ 0xa722 : []int32{42787},
+ 0xa724 : []int32{42789},
+ 0xa726 : []int32{42791},
+ 0xa728 : []int32{42793},
+ 0xa72a : []int32{42795},
+ 0xa72c : []int32{42797},
+ 0xa72e : []int32{42799},
+ 0xa732 : []int32{42803},
+ 0xa734 : []int32{42805},
+ 0xa736 : []int32{42807},
+ 0xa738 : []int32{42809},
+ 0xa73a : []int32{42811},
+ 0xa73c : []int32{42813},
+ 0xa73e : []int32{42815},
+ 0xa740 : []int32{42817},
+ 0xa742 : []int32{42819},
+ 0xa744 : []int32{42821},
+ 0xa746 : []int32{42823},
+ 0xa748 : []int32{42825},
+ 0xa74a : []int32{42827},
+ 0xa74c : []int32{42829},
+ 0xa74e : []int32{42831},
+ 0xa750 : []int32{42833},
+ 0xa752 : []int32{42835},
+ 0xa754 : []int32{42837},
+ 0xa756 : []int32{42839},
+ 0xa758 : []int32{42841},
+ 0xa75a : []int32{42843},
+ 0xa75c : []int32{42845},
+ 0xa75e : []int32{42847},
+ 0xa760 : []int32{42849},
+ 0xa762 : []int32{42851},
+ 0xa764 : []int32{42853},
+ 0xa766 : []int32{42855},
+ 0xa768 : []int32{42857},
+ 0xa76a : []int32{42859},
+ 0xa76c : []int32{42861},
+ 0xa76e : []int32{42863},
+ 0xa779 : []int32{42874},
+ 0xa77b : []int32{42876},
+ 0xa77d : []int32{7545},
+ 0xa77e : []int32{42879},
+ 0xa780 : []int32{42881},
+ 0xa782 : []int32{42883},
+ 0xa784 : []int32{42885},
+ 0xa786 : []int32{42887},
+ 0xa78b : []int32{42892},
+ 0xa78d : []int32{613},
+ 0xa790 : []int32{42897},
+ 0xa792 : []int32{42899},
+ 0xa796 : []int32{42903},
+ 0xa798 : []int32{42905},
+ 0xa79a : []int32{42907},
+ 0xa79c : []int32{42909},
+ 0xa79e : []int32{42911},
+ 0xa7a0 : []int32{42913},
+ 0xa7a2 : []int32{42915},
+ 0xa7a4 : []int32{42917},
+ 0xa7a6 : []int32{42919},
+ 0xa7a8 : []int32{42921},
+ 0xa7aa : []int32{614},
+ 0xa7ab : []int32{604},
+ 0xa7ac : []int32{609},
+ 0xa7ad : []int32{620},
+ 0xa7ae : []int32{618},
+ 0xa7b0 : []int32{670},
+ 0xa7b1 : []int32{647},
+ 0xa7b2 : []int32{669},
+ 0xa7b3 : []int32{43859},
+ 0xa7b4 : []int32{42933},
+ 0xa7b6 : []int32{42935},
+ 0xa7b8 : []int32{42937},
+ 0xa7ba : []int32{42939},
+ 0xa7bc : []int32{42941},
+ 0xa7be : []int32{42943},
+ 0xa7c0 : []int32{42945},
+ 0xa7c2 : []int32{42947},
+ 0xa7c4 : []int32{42900},
+ 0xa7c5 : []int32{642},
+ 0xa7c6 : []int32{7566},
+ 0xa7c7 : []int32{42952},
+ 0xa7c9 : []int32{42954},
+ 0xa7d0 : []int32{42961},
+ 0xa7d6 : []int32{42967},
+ 0xa7d8 : []int32{42969},
+ 0xa7f5 : []int32{42998},
+ 0xab70 : []int32{5024},
+ 0xab71 : []int32{5025},
+ 0xab72 : []int32{5026},
+ 0xab73 : []int32{5027},
+ 0xab74 : []int32{5028},
+ 0xab75 : []int32{5029},
+ 0xab76 : []int32{5030},
+ 0xab77 : []int32{5031},
+ 0xab78 : []int32{5032},
+ 0xab79 : []int32{5033},
+ 0xab7a : []int32{5034},
+ 0xab7b : []int32{5035},
+ 0xab7c : []int32{5036},
+ 0xab7d : []int32{5037},
+ 0xab7e : []int32{5038},
+ 0xab7f : []int32{5039},
+ 0xab80 : []int32{5040},
+ 0xab81 : []int32{5041},
+ 0xab82 : []int32{5042},
+ 0xab83 : []int32{5043},
+ 0xab84 : []int32{5044},
+ 0xab85 : []int32{5045},
+ 0xab86 : []int32{5046},
+ 0xab87 : []int32{5047},
+ 0xab88 : []int32{5048},
+ 0xab89 : []int32{5049},
+ 0xab8a : []int32{5050},
+ 0xab8b : []int32{5051},
+ 0xab8c : []int32{5052},
+ 0xab8d : []int32{5053},
+ 0xab8e : []int32{5054},
+ 0xab8f : []int32{5055},
+ 0xab90 : []int32{5056},
+ 0xab91 : []int32{5057},
+ 0xab92 : []int32{5058},
+ 0xab93 : []int32{5059},
+ 0xab94 : []int32{5060},
+ 0xab95 : []int32{5061},
+ 0xab96 : []int32{5062},
+ 0xab97 : []int32{5063},
+ 0xab98 : []int32{5064},
+ 0xab99 : []int32{5065},
+ 0xab9a : []int32{5066},
+ 0xab9b : []int32{5067},
+ 0xab9c : []int32{5068},
+ 0xab9d : []int32{5069},
+ 0xab9e : []int32{5070},
+ 0xab9f : []int32{5071},
+ 0xaba0 : []int32{5072},
+ 0xaba1 : []int32{5073},
+ 0xaba2 : []int32{5074},
+ 0xaba3 : []int32{5075},
+ 0xaba4 : []int32{5076},
+ 0xaba5 : []int32{5077},
+ 0xaba6 : []int32{5078},
+ 0xaba7 : []int32{5079},
+ 0xaba8 : []int32{5080},
+ 0xaba9 : []int32{5081},
+ 0xabaa : []int32{5082},
+ 0xabab : []int32{5083},
+ 0xabac : []int32{5084},
+ 0xabad : []int32{5085},
+ 0xabae : []int32{5086},
+ 0xabaf : []int32{5087},
+ 0xabb0 : []int32{5088},
+ 0xabb1 : []int32{5089},
+ 0xabb2 : []int32{5090},
+ 0xabb3 : []int32{5091},
+ 0xabb4 : []int32{5092},
+ 0xabb5 : []int32{5093},
+ 0xabb6 : []int32{5094},
+ 0xabb7 : []int32{5095},
+ 0xabb8 : []int32{5096},
+ 0xabb9 : []int32{5097},
+ 0xabba : []int32{5098},
+ 0xabbb : []int32{5099},
+ 0xabbc : []int32{5100},
+ 0xabbd : []int32{5101},
+ 0xabbe : []int32{5102},
+ 0xabbf : []int32{5103},
+ 0xfb00 : []int32{102, 102},
+ 0xfb01 : []int32{102, 105},
+ 0xfb02 : []int32{102, 108},
+ 0xfb03 : []int32{102, 102, 105},
+ 0xfb04 : []int32{102, 102, 108},
+ 0xfb05 : []int32{115, 116},
+ 0xfb06 : []int32{115, 116},
+ 0xfb13 : []int32{1396, 1398},
+ 0xfb14 : []int32{1396, 1381},
+ 0xfb15 : []int32{1396, 1387},
+ 0xfb16 : []int32{1406, 1398},
+ 0xfb17 : []int32{1396, 1389},
+ 0xff21 : []int32{65345},
+ 0xff22 : []int32{65346},
+ 0xff23 : []int32{65347},
+ 0xff24 : []int32{65348},
+ 0xff25 : []int32{65349},
+ 0xff26 : []int32{65350},
+ 0xff27 : []int32{65351},
+ 0xff28 : []int32{65352},
+ 0xff29 : []int32{65353},
+ 0xff2a : []int32{65354},
+ 0xff2b : []int32{65355},
+ 0xff2c : []int32{65356},
+ 0xff2d : []int32{65357},
+ 0xff2e : []int32{65358},
+ 0xff2f : []int32{65359},
+ 0xff30 : []int32{65360},
+ 0xff31 : []int32{65361},
+ 0xff32 : []int32{65362},
+ 0xff33 : []int32{65363},
+ 0xff34 : []int32{65364},
+ 0xff35 : []int32{65365},
+ 0xff36 : []int32{65366},
+ 0xff37 : []int32{65367},
+ 0xff38 : []int32{65368},
+ 0xff39 : []int32{65369},
+ 0xff3a : []int32{65370},
+ 0x10400 : []int32{66600},
+ 0x10401 : []int32{66601},
+ 0x10402 : []int32{66602},
+ 0x10403 : []int32{66603},
+ 0x10404 : []int32{66604},
+ 0x10405 : []int32{66605},
+ 0x10406 : []int32{66606},
+ 0x10407 : []int32{66607},
+ 0x10408 : []int32{66608},
+ 0x10409 : []int32{66609},
+ 0x1040a : []int32{66610},
+ 0x1040b : []int32{66611},
+ 0x1040c : []int32{66612},
+ 0x1040d : []int32{66613},
+ 0x1040e : []int32{66614},
+ 0x1040f : []int32{66615},
+ 0x10410 : []int32{66616},
+ 0x10411 : []int32{66617},
+ 0x10412 : []int32{66618},
+ 0x10413 : []int32{66619},
+ 0x10414 : []int32{66620},
+ 0x10415 : []int32{66621},
+ 0x10416 : []int32{66622},
+ 0x10417 : []int32{66623},
+ 0x10418 : []int32{66624},
+ 0x10419 : []int32{66625},
+ 0x1041a : []int32{66626},
+ 0x1041b : []int32{66627},
+ 0x1041c : []int32{66628},
+ 0x1041d : []int32{66629},
+ 0x1041e : []int32{66630},
+ 0x1041f : []int32{66631},
+ 0x10420 : []int32{66632},
+ 0x10421 : []int32{66633},
+ 0x10422 : []int32{66634},
+ 0x10423 : []int32{66635},
+ 0x10424 : []int32{66636},
+ 0x10425 : []int32{66637},
+ 0x10426 : []int32{66638},
+ 0x10427 : []int32{66639},
+ 0x104b0 : []int32{66776},
+ 0x104b1 : []int32{66777},
+ 0x104b2 : []int32{66778},
+ 0x104b3 : []int32{66779},
+ 0x104b4 : []int32{66780},
+ 0x104b5 : []int32{66781},
+ 0x104b6 : []int32{66782},
+ 0x104b7 : []int32{66783},
+ 0x104b8 : []int32{66784},
+ 0x104b9 : []int32{66785},
+ 0x104ba : []int32{66786},
+ 0x104bb : []int32{66787},
+ 0x104bc : []int32{66788},
+ 0x104bd : []int32{66789},
+ 0x104be : []int32{66790},
+ 0x104bf : []int32{66791},
+ 0x104c0 : []int32{66792},
+ 0x104c1 : []int32{66793},
+ 0x104c2 : []int32{66794},
+ 0x104c3 : []int32{66795},
+ 0x104c4 : []int32{66796},
+ 0x104c5 : []int32{66797},
+ 0x104c6 : []int32{66798},
+ 0x104c7 : []int32{66799},
+ 0x104c8 : []int32{66800},
+ 0x104c9 : []int32{66801},
+ 0x104ca : []int32{66802},
+ 0x104cb : []int32{66803},
+ 0x104cc : []int32{66804},
+ 0x104cd : []int32{66805},
+ 0x104ce : []int32{66806},
+ 0x104cf : []int32{66807},
+ 0x104d0 : []int32{66808},
+ 0x104d1 : []int32{66809},
+ 0x104d2 : []int32{66810},
+ 0x104d3 : []int32{66811},
+ 0x10570 : []int32{66967},
+ 0x10571 : []int32{66968},
+ 0x10572 : []int32{66969},
+ 0x10573 : []int32{66970},
+ 0x10574 : []int32{66971},
+ 0x10575 : []int32{66972},
+ 0x10576 : []int32{66973},
+ 0x10577 : []int32{66974},
+ 0x10578 : []int32{66975},
+ 0x10579 : []int32{66976},
+ 0x1057a : []int32{66977},
+ 0x1057c : []int32{66979},
+ 0x1057d : []int32{66980},
+ 0x1057e : []int32{66981},
+ 0x1057f : []int32{66982},
+ 0x10580 : []int32{66983},
+ 0x10581 : []int32{66984},
+ 0x10582 : []int32{66985},
+ 0x10583 : []int32{66986},
+ 0x10584 : []int32{66987},
+ 0x10585 : []int32{66988},
+ 0x10586 : []int32{66989},
+ 0x10587 : []int32{66990},
+ 0x10588 : []int32{66991},
+ 0x10589 : []int32{66992},
+ 0x1058a : []int32{66993},
+ 0x1058c : []int32{66995},
+ 0x1058d : []int32{66996},
+ 0x1058e : []int32{66997},
+ 0x1058f : []int32{66998},
+ 0x10590 : []int32{66999},
+ 0x10591 : []int32{67000},
+ 0x10592 : []int32{67001},
+ 0x10594 : []int32{67003},
+ 0x10595 : []int32{67004},
+ 0x10c80 : []int32{68800},
+ 0x10c81 : []int32{68801},
+ 0x10c82 : []int32{68802},
+ 0x10c83 : []int32{68803},
+ 0x10c84 : []int32{68804},
+ 0x10c85 : []int32{68805},
+ 0x10c86 : []int32{68806},
+ 0x10c87 : []int32{68807},
+ 0x10c88 : []int32{68808},
+ 0x10c89 : []int32{68809},
+ 0x10c8a : []int32{68810},
+ 0x10c8b : []int32{68811},
+ 0x10c8c : []int32{68812},
+ 0x10c8d : []int32{68813},
+ 0x10c8e : []int32{68814},
+ 0x10c8f : []int32{68815},
+ 0x10c90 : []int32{68816},
+ 0x10c91 : []int32{68817},
+ 0x10c92 : []int32{68818},
+ 0x10c93 : []int32{68819},
+ 0x10c94 : []int32{68820},
+ 0x10c95 : []int32{68821},
+ 0x10c96 : []int32{68822},
+ 0x10c97 : []int32{68823},
+ 0x10c98 : []int32{68824},
+ 0x10c99 : []int32{68825},
+ 0x10c9a : []int32{68826},
+ 0x10c9b : []int32{68827},
+ 0x10c9c : []int32{68828},
+ 0x10c9d : []int32{68829},
+ 0x10c9e : []int32{68830},
+ 0x10c9f : []int32{68831},
+ 0x10ca0 : []int32{68832},
+ 0x10ca1 : []int32{68833},
+ 0x10ca2 : []int32{68834},
+ 0x10ca3 : []int32{68835},
+ 0x10ca4 : []int32{68836},
+ 0x10ca5 : []int32{68837},
+ 0x10ca6 : []int32{68838},
+ 0x10ca7 : []int32{68839},
+ 0x10ca8 : []int32{68840},
+ 0x10ca9 : []int32{68841},
+ 0x10caa : []int32{68842},
+ 0x10cab : []int32{68843},
+ 0x10cac : []int32{68844},
+ 0x10cad : []int32{68845},
+ 0x10cae : []int32{68846},
+ 0x10caf : []int32{68847},
+ 0x10cb0 : []int32{68848},
+ 0x10cb1 : []int32{68849},
+ 0x10cb2 : []int32{68850},
+ 0x118a0 : []int32{71872},
+ 0x118a1 : []int32{71873},
+ 0x118a2 : []int32{71874},
+ 0x118a3 : []int32{71875},
+ 0x118a4 : []int32{71876},
+ 0x118a5 : []int32{71877},
+ 0x118a6 : []int32{71878},
+ 0x118a7 : []int32{71879},
+ 0x118a8 : []int32{71880},
+ 0x118a9 : []int32{71881},
+ 0x118aa : []int32{71882},
+ 0x118ab : []int32{71883},
+ 0x118ac : []int32{71884},
+ 0x118ad : []int32{71885},
+ 0x118ae : []int32{71886},
+ 0x118af : []int32{71887},
+ 0x118b0 : []int32{71888},
+ 0x118b1 : []int32{71889},
+ 0x118b2 : []int32{71890},
+ 0x118b3 : []int32{71891},
+ 0x118b4 : []int32{71892},
+ 0x118b5 : []int32{71893},
+ 0x118b6 : []int32{71894},
+ 0x118b7 : []int32{71895},
+ 0x118b8 : []int32{71896},
+ 0x118b9 : []int32{71897},
+ 0x118ba : []int32{71898},
+ 0x118bb : []int32{71899},
+ 0x118bc : []int32{71900},
+ 0x118bd : []int32{71901},
+ 0x118be : []int32{71902},
+ 0x118bf : []int32{71903},
+ 0x16e40 : []int32{93792},
+ 0x16e41 : []int32{93793},
+ 0x16e42 : []int32{93794},
+ 0x16e43 : []int32{93795},
+ 0x16e44 : []int32{93796},
+ 0x16e45 : []int32{93797},
+ 0x16e46 : []int32{93798},
+ 0x16e47 : []int32{93799},
+ 0x16e48 : []int32{93800},
+ 0x16e49 : []int32{93801},
+ 0x16e4a : []int32{93802},
+ 0x16e4b : []int32{93803},
+ 0x16e4c : []int32{93804},
+ 0x16e4d : []int32{93805},
+ 0x16e4e : []int32{93806},
+ 0x16e4f : []int32{93807},
+ 0x16e50 : []int32{93808},
+ 0x16e51 : []int32{93809},
+ 0x16e52 : []int32{93810},
+ 0x16e53 : []int32{93811},
+ 0x16e54 : []int32{93812},
+ 0x16e55 : []int32{93813},
+ 0x16e56 : []int32{93814},
+ 0x16e57 : []int32{93815},
+ 0x16e58 : []int32{93816},
+ 0x16e59 : []int32{93817},
+ 0x16e5a : []int32{93818},
+ 0x16e5b : []int32{93819},
+ 0x16e5c : []int32{93820},
+ 0x16e5d : []int32{93821},
+ 0x16e5e : []int32{93822},
+ 0x16e5f : []int32{93823},
+ 0x1e900 : []int32{125218},
+ 0x1e901 : []int32{125219},
+ 0x1e902 : []int32{125220},
+ 0x1e903 : []int32{125221},
+ 0x1e904 : []int32{125222},
+ 0x1e905 : []int32{125223},
+ 0x1e906 : []int32{125224},
+ 0x1e907 : []int32{125225},
+ 0x1e908 : []int32{125226},
+ 0x1e909 : []int32{125227},
+ 0x1e90a : []int32{125228},
+ 0x1e90b : []int32{125229},
+ 0x1e90c : []int32{125230},
+ 0x1e90d : []int32{125231},
+ 0x1e90e : []int32{125232},
+ 0x1e90f : []int32{125233},
+ 0x1e910 : []int32{125234},
+ 0x1e911 : []int32{125235},
+ 0x1e912 : []int32{125236},
+ 0x1e913 : []int32{125237},
+ 0x1e914 : []int32{125238},
+ 0x1e915 : []int32{125239},
+ 0x1e916 : []int32{125240},
+ 0x1e917 : []int32{125241},
+ 0x1e918 : []int32{125242},
+ 0x1e919 : []int32{125243},
+ 0x1e91a : []int32{125244},
+ 0x1e91b : []int32{125245},
+ 0x1e91c : []int32{125246},
+ 0x1e91d : []int32{125247},
+ 0x1e91e : []int32{125248},
+ 0x1e91f : []int32{125249},
+ 0x1e920 : []int32{125250},
+ 0x1e921 : []int32{125251},
+}
diff --git a/vendor/github.com/yuin/goldmark/util/util.go b/vendor/github.com/yuin/goldmark/util/util.go
new file mode 100644
index 0000000..a817ec6
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/util.go
@@ -0,0 +1,980 @@
+// Package util provides utility functions for the goldmark.
+package util
+
+import (
+ "bytes"
+ "io"
+ "net/url"
+ "regexp"
+ "sort"
+ "strconv"
+ "unicode"
+ "unicode/utf8"
+)
+
+// A CopyOnWriteBuffer is a byte buffer that copies buffer when
+// it need to be changed.
+type CopyOnWriteBuffer struct {
+ buffer []byte
+ copied bool
+}
+
+// NewCopyOnWriteBuffer returns a new CopyOnWriteBuffer.
+func NewCopyOnWriteBuffer(buffer []byte) CopyOnWriteBuffer {
+ return CopyOnWriteBuffer{
+ buffer: buffer,
+ copied: false,
+ }
+}
+
+// Write writes given bytes to the buffer.
+// Write allocate new buffer and clears it at the first time.
+func (b *CopyOnWriteBuffer) Write(value []byte) {
+ if !b.copied {
+ b.buffer = make([]byte, 0, len(b.buffer)+20)
+ b.copied = true
+ }
+ b.buffer = append(b.buffer, value...)
+}
+
+// WriteString writes given string to the buffer.
+// WriteString allocate new buffer and clears it at the first time.
+func (b *CopyOnWriteBuffer) WriteString(value string) {
+ b.Write(StringToReadOnlyBytes(value))
+}
+
+// Append appends given bytes to the buffer.
+// Append copy buffer at the first time.
+func (b *CopyOnWriteBuffer) Append(value []byte) {
+ if !b.copied {
+ tmp := make([]byte, len(b.buffer), len(b.buffer)+20)
+ copy(tmp, b.buffer)
+ b.buffer = tmp
+ b.copied = true
+ }
+ b.buffer = append(b.buffer, value...)
+}
+
+// AppendString appends given string to the buffer.
+// AppendString copy buffer at the first time.
+func (b *CopyOnWriteBuffer) AppendString(value string) {
+ b.Append(StringToReadOnlyBytes(value))
+}
+
+// WriteByte writes the given byte to the buffer.
+// WriteByte allocate new buffer and clears it at the first time.
+func (b *CopyOnWriteBuffer) WriteByte(c byte) {
+ if !b.copied {
+ b.buffer = make([]byte, 0, len(b.buffer)+20)
+ b.copied = true
+ }
+ b.buffer = append(b.buffer, c)
+}
+
+// AppendByte appends given bytes to the buffer.
+// AppendByte copy buffer at the first time.
+func (b *CopyOnWriteBuffer) AppendByte(c byte) {
+ if !b.copied {
+ tmp := make([]byte, len(b.buffer), len(b.buffer)+20)
+ copy(tmp, b.buffer)
+ b.buffer = tmp
+ b.copied = true
+ }
+ b.buffer = append(b.buffer, c)
+}
+
+// Bytes returns bytes of this buffer.
+func (b *CopyOnWriteBuffer) Bytes() []byte {
+ return b.buffer
+}
+
+// IsCopied returns true if buffer has been copied, otherwise false.
+func (b *CopyOnWriteBuffer) IsCopied() bool {
+ return b.copied
+}
+
+// IsEscapedPunctuation returns true if character at a given index i
+// is an escaped punctuation, otherwise false.
+func IsEscapedPunctuation(source []byte, i int) bool {
+ return source[i] == '\\' && i < len(source)-1 && IsPunct(source[i+1])
+}
+
+// ReadWhile read the given source while pred is true.
+func ReadWhile(source []byte, index [2]int, pred func(byte) bool) (int, bool) {
+ j := index[0]
+ ok := false
+ for ; j < index[1]; j++ {
+ c1 := source[j]
+ if pred(c1) {
+ ok = true
+ continue
+ }
+ break
+ }
+ return j, ok
+}
+
+// IsBlank returns true if the given string is all space characters.
+func IsBlank(bs []byte) bool {
+ for _, b := range bs {
+ if !IsSpace(b) {
+ return false
+ }
+ }
+ return true
+}
+
+// VisualizeSpaces visualize invisible space characters.
+func VisualizeSpaces(bs []byte) []byte {
+ bs = bytes.Replace(bs, []byte(" "), []byte("[SPACE]"), -1)
+ bs = bytes.Replace(bs, []byte("\t"), []byte("[TAB]"), -1)
+ bs = bytes.Replace(bs, []byte("\n"), []byte("[NEWLINE]\n"), -1)
+ bs = bytes.Replace(bs, []byte("\r"), []byte("[CR]"), -1)
+ bs = bytes.Replace(bs, []byte("\v"), []byte("[VTAB]"), -1)
+ bs = bytes.Replace(bs, []byte("\x00"), []byte("[NUL]"), -1)
+ bs = bytes.Replace(bs, []byte("\ufffd"), []byte("[U+FFFD]"), -1)
+ return bs
+}
+
+// TabWidth calculates actual width of a tab at the given position.
+func TabWidth(currentPos int) int {
+ return 4 - currentPos%4
+}
+
+// IndentPosition searches an indent position with the given width for the given line.
+// If the line contains tab characters, paddings may be not zero.
+// currentPos==0 and width==2:
+//
+// position: 0 1
+// [TAB]aaaa
+// width: 1234 5678
+//
+// width=2 is in the tab character. In this case, IndentPosition returns
+// (pos=1, padding=2)
+func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
+ return IndentPositionPadding(bs, currentPos, 0, width)
+}
+
+// IndentPositionPadding searches an indent position with the given width for the given line.
+// This function is mostly same as IndentPosition except this function
+// takes account into additional paddings.
+func IndentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
+ if width == 0 {
+ return 0, paddingv
+ }
+ w := 0
+ i := 0
+ l := len(bs)
+ for ; i < l; i++ {
+ if bs[i] == '\t' && w < width {
+ w += TabWidth(currentPos + w)
+ } else if bs[i] == ' ' && w < width {
+ w++
+ } else {
+ break
+ }
+ }
+ if w >= width {
+ return i - paddingv, w - width
+ }
+ return -1, -1
+}
+
+// DedentPosition dedents lines by the given width.
+//
+// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
+func DedentPosition(bs []byte, currentPos, width int) (pos, padding int) {
+ if width == 0 {
+ return 0, 0
+ }
+ w := 0
+ l := len(bs)
+ i := 0
+ for ; i < l; i++ {
+ if bs[i] == '\t' {
+ w += TabWidth(currentPos + w)
+ } else if bs[i] == ' ' {
+ w++
+ } else {
+ break
+ }
+ }
+ if w >= width {
+ return i, w - width
+ }
+ return i, 0
+}
+
+// DedentPositionPadding dedents lines by the given width.
+// This function is mostly same as DedentPosition except this function
+// takes account into additional paddings.
+//
+// Deprecated: This function has bugs. Use util.IndentPositionPadding and util.FirstNonSpacePosition.
+func DedentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
+ if width == 0 {
+ return 0, paddingv
+ }
+
+ w := 0
+ i := 0
+ l := len(bs)
+ for ; i < l; i++ {
+ if bs[i] == '\t' {
+ w += TabWidth(currentPos + w)
+ } else if bs[i] == ' ' {
+ w++
+ } else {
+ break
+ }
+ }
+ if w >= width {
+ return i - paddingv, w - width
+ }
+ return i - paddingv, 0
+}
+
+// IndentWidth calculate an indent width for the given line.
+func IndentWidth(bs []byte, currentPos int) (width, pos int) {
+ l := len(bs)
+ for i := 0; i < l; i++ {
+ b := bs[i]
+ if b == ' ' {
+ width++
+ pos++
+ } else if b == '\t' {
+ width += TabWidth(currentPos + width)
+ pos++
+ } else {
+ break
+ }
+ }
+ return
+}
+
+// FirstNonSpacePosition returns a position line that is a first nonspace
+// character.
+func FirstNonSpacePosition(bs []byte) int {
+ i := 0
+ for ; i < len(bs); i++ {
+ c := bs[i]
+ if c == ' ' || c == '\t' {
+ continue
+ }
+ if c == '\n' {
+ return -1
+ }
+ return i
+ }
+ return -1
+}
+
+// FindClosure returns a position that closes the given opener.
+// If codeSpan is set true, it ignores characters in code spans.
+// If allowNesting is set true, closures correspond to nested opener will be
+// ignored.
+//
+// Deprecated: This function can not handle newlines. Many elements
+// can be existed over multiple lines(e.g. link labels).
+// Use text.Reader.FindClosure.
+func FindClosure(bs []byte, opener, closure byte, codeSpan, allowNesting bool) int {
+ i := 0
+ opened := 1
+ codeSpanOpener := 0
+ for i < len(bs) {
+ c := bs[i]
+ if codeSpan && codeSpanOpener != 0 && c == '`' {
+ codeSpanCloser := 0
+ for ; i < len(bs); i++ {
+ if bs[i] == '`' {
+ codeSpanCloser++
+ } else {
+ i--
+ break
+ }
+ }
+ if codeSpanCloser == codeSpanOpener {
+ codeSpanOpener = 0
+ }
+ } else if codeSpanOpener == 0 && c == '\\' && i < len(bs)-1 && IsPunct(bs[i+1]) {
+ i += 2
+ continue
+ } else if codeSpan && codeSpanOpener == 0 && c == '`' {
+ for ; i < len(bs); i++ {
+ if bs[i] == '`' {
+ codeSpanOpener++
+ } else {
+ i--
+ break
+ }
+ }
+ } else if (codeSpan && codeSpanOpener == 0) || !codeSpan {
+ if c == closure {
+ opened--
+ if opened == 0 {
+ return i
+ }
+ } else if c == opener {
+ if !allowNesting {
+ return -1
+ }
+ opened++
+ }
+ }
+ i++
+ }
+ return -1
+}
+
+// TrimLeft trims characters in the given s from head of the source.
+// bytes.TrimLeft offers same functionalities, but bytes.TrimLeft
+// allocates new buffer for the result.
+func TrimLeft(source, b []byte) []byte {
+ i := 0
+ for ; i < len(source); i++ {
+ c := source[i]
+ found := false
+ for j := 0; j < len(b); j++ {
+ if c == b[j] {
+ found = true
+ break
+ }
+ }
+ if !found {
+ break
+ }
+ }
+ return source[i:]
+}
+
+// TrimRight trims characters in the given s from tail of the source.
+func TrimRight(source, b []byte) []byte {
+ i := len(source) - 1
+ for ; i >= 0; i-- {
+ c := source[i]
+ found := false
+ for j := 0; j < len(b); j++ {
+ if c == b[j] {
+ found = true
+ break
+ }
+ }
+ if !found {
+ break
+ }
+ }
+ return source[:i+1]
+}
+
+// TrimLeftLength returns a length of leading specified characters.
+func TrimLeftLength(source, s []byte) int {
+ return len(source) - len(TrimLeft(source, s))
+}
+
+// TrimRightLength returns a length of trailing specified characters.
+func TrimRightLength(source, s []byte) int {
+ return len(source) - len(TrimRight(source, s))
+}
+
+// TrimLeftSpaceLength returns a length of leading space characters.
+func TrimLeftSpaceLength(source []byte) int {
+ i := 0
+ for ; i < len(source); i++ {
+ if !IsSpace(source[i]) {
+ break
+ }
+ }
+ return i
+}
+
+// TrimRightSpaceLength returns a length of trailing space characters.
+func TrimRightSpaceLength(source []byte) int {
+ l := len(source)
+ i := l - 1
+ for ; i >= 0; i-- {
+ if !IsSpace(source[i]) {
+ break
+ }
+ }
+ if i < 0 {
+ return l
+ }
+ return l - 1 - i
+}
+
+// TrimLeftSpace returns a subslice of the given string by slicing off all leading
+// space characters.
+func TrimLeftSpace(source []byte) []byte {
+ return TrimLeft(source, spaces)
+}
+
+// TrimRightSpace returns a subslice of the given string by slicing off all trailing
+// space characters.
+func TrimRightSpace(source []byte) []byte {
+ return TrimRight(source, spaces)
+}
+
+// DoFullUnicodeCaseFolding performs full unicode case folding to given bytes.
+func DoFullUnicodeCaseFolding(v []byte) []byte {
+ var rbuf []byte
+ cob := NewCopyOnWriteBuffer(v)
+ n := 0
+ for i := 0; i < len(v); i++ {
+ c := v[i]
+ if c < 0xb5 {
+ if c >= 0x41 && c <= 0x5a {
+ // A-Z to a-z
+ cob.Write(v[n:i])
+ cob.WriteByte(c + 32)
+ n = i + 1
+ }
+ continue
+ }
+
+ if !utf8.RuneStart(c) {
+ continue
+ }
+ r, length := utf8.DecodeRune(v[i:])
+ if r == utf8.RuneError {
+ continue
+ }
+ folded, ok := unicodeCaseFoldings[r]
+ if !ok {
+ continue
+ }
+
+ cob.Write(v[n:i])
+ if rbuf == nil {
+ rbuf = make([]byte, 4)
+ }
+ for _, f := range folded {
+ l := utf8.EncodeRune(rbuf, f)
+ cob.Write(rbuf[:l])
+ }
+ i += length - 1
+ n = i + 1
+ }
+ if cob.IsCopied() {
+ cob.Write(v[n:])
+ }
+ return cob.Bytes()
+}
+
+// ReplaceSpaces replaces sequence of spaces with the given repl.
+func ReplaceSpaces(source []byte, repl byte) []byte {
+ var ret []byte
+ start := -1
+ for i, c := range source {
+ iss := IsSpace(c)
+ if start < 0 && iss {
+ start = i
+ continue
+ } else if start >= 0 && iss {
+ continue
+ } else if start >= 0 {
+ if ret == nil {
+ ret = make([]byte, 0, len(source))
+ ret = append(ret, source[:start]...)
+ }
+ ret = append(ret, repl)
+ start = -1
+ }
+ if ret != nil {
+ ret = append(ret, c)
+ }
+ }
+ if start >= 0 && ret != nil {
+ ret = append(ret, repl)
+ }
+ if ret == nil {
+ return source
+ }
+ return ret
+}
+
+// ToRune decode given bytes start at pos and returns a rune.
+func ToRune(source []byte, pos int) rune {
+ i := pos
+ for ; i >= 0; i-- {
+ if utf8.RuneStart(source[i]) {
+ break
+ }
+ }
+ r, _ := utf8.DecodeRune(source[i:])
+ return r
+}
+
+// ToValidRune returns 0xFFFD if the given rune is invalid, otherwise v.
+func ToValidRune(v rune) rune {
+ if v == 0 || !utf8.ValidRune(v) {
+ return rune(0xFFFD)
+ }
+ return v
+}
+
+// ToLinkReference converts given bytes into a valid link reference string.
+// ToLinkReference performs unicode case folding, trims leading and trailing spaces, converts into lower
+// case and replace spaces with a single space character.
+func ToLinkReference(v []byte) string {
+ v = TrimLeftSpace(v)
+ v = TrimRightSpace(v)
+ v = DoFullUnicodeCaseFolding(v)
+ return string(ReplaceSpaces(v, ' '))
+}
+
+var htmlEscapeTable = [256][]byte{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []byte("""), nil, nil, nil, []byte("&"), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, []byte("<"), nil, []byte(">"), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}
+
+// EscapeHTMLByte returns HTML escaped bytes if the given byte should be escaped,
+// otherwise nil.
+func EscapeHTMLByte(b byte) []byte {
+ return htmlEscapeTable[b]
+}
+
+// EscapeHTML escapes characters that should be escaped in HTML text.
+func EscapeHTML(v []byte) []byte {
+ cob := NewCopyOnWriteBuffer(v)
+ n := 0
+ for i := 0; i < len(v); i++ {
+ c := v[i]
+ escaped := htmlEscapeTable[c]
+ if escaped != nil {
+ cob.Write(v[n:i])
+ cob.Write(escaped)
+ n = i + 1
+ }
+ }
+ if cob.IsCopied() {
+ cob.Write(v[n:])
+ }
+ return cob.Bytes()
+}
+
+// UnescapePunctuations unescapes blackslash escaped punctuations.
+func UnescapePunctuations(source []byte) []byte {
+ cob := NewCopyOnWriteBuffer(source)
+ limit := len(source)
+ n := 0
+ for i := 0; i < limit; {
+ c := source[i]
+ if i < limit-1 && c == '\\' && IsPunct(source[i+1]) {
+ cob.Write(source[n:i])
+ cob.WriteByte(source[i+1])
+ i += 2
+ n = i
+ continue
+ }
+ i++
+ }
+ if cob.IsCopied() {
+ cob.Write(source[n:])
+ }
+ return cob.Bytes()
+}
+
+// ResolveNumericReferences resolve numeric references like 'Ӓ" .
+func ResolveNumericReferences(source []byte) []byte {
+ cob := NewCopyOnWriteBuffer(source)
+ buf := make([]byte, 6, 6)
+ limit := len(source)
+ ok := false
+ n := 0
+ for i := 0; i < limit; i++ {
+ if source[i] == '&' {
+ pos := i
+ next := i + 1
+ if next < limit && source[next] == '#' {
+ nnext := next + 1
+ if nnext < limit {
+ nc := source[nnext]
+ // code point like #x22;
+ if nnext < limit && nc == 'x' || nc == 'X' {
+ start := nnext + 1
+ i, ok = ReadWhile(source, [2]int{start, limit}, IsHexDecimal)
+ if ok && i < limit && source[i] == ';' {
+ v, _ := strconv.ParseUint(BytesToReadOnlyString(source[start:i]), 16, 32)
+ cob.Write(source[n:pos])
+ n = i + 1
+ runeSize := utf8.EncodeRune(buf, ToValidRune(rune(v)))
+ cob.Write(buf[:runeSize])
+ continue
+ }
+ // code point like #1234;
+ } else if nc >= '0' && nc <= '9' {
+ start := nnext
+ i, ok = ReadWhile(source, [2]int{start, limit}, IsNumeric)
+ if ok && i < limit && i-start < 8 && source[i] == ';' {
+ v, _ := strconv.ParseUint(BytesToReadOnlyString(source[start:i]), 0, 32)
+ cob.Write(source[n:pos])
+ n = i + 1
+ runeSize := utf8.EncodeRune(buf, ToValidRune(rune(v)))
+ cob.Write(buf[:runeSize])
+ continue
+ }
+ }
+ }
+ }
+ i = next - 1
+ }
+ }
+ if cob.IsCopied() {
+ cob.Write(source[n:])
+ }
+ return cob.Bytes()
+}
+
+// ResolveEntityNames resolve entity references like 'ö" .
+func ResolveEntityNames(source []byte) []byte {
+ cob := NewCopyOnWriteBuffer(source)
+ limit := len(source)
+ ok := false
+ n := 0
+ for i := 0; i < limit; i++ {
+ if source[i] == '&' {
+ pos := i
+ next := i + 1
+ if !(next < limit && source[next] == '#') {
+ start := next
+ i, ok = ReadWhile(source, [2]int{start, limit}, IsAlphaNumeric)
+ if ok && i < limit && source[i] == ';' {
+ name := BytesToReadOnlyString(source[start:i])
+ entity, ok := LookUpHTML5EntityByName(name)
+ if ok {
+ cob.Write(source[n:pos])
+ n = i + 1
+ cob.Write(entity.Characters)
+ continue
+ }
+ }
+ }
+ i = next - 1
+ }
+ }
+ if cob.IsCopied() {
+ cob.Write(source[n:])
+ }
+ return cob.Bytes()
+}
+
+var htmlSpace = []byte("%20")
+
+// URLEscape escape the given URL.
+// If resolveReference is set true:
+// 1. unescape punctuations
+// 2. resolve numeric references
+// 3. resolve entity references
+//
+// URL encoded values (%xx) are kept as is.
+func URLEscape(v []byte, resolveReference bool) []byte {
+ if resolveReference {
+ v = UnescapePunctuations(v)
+ v = ResolveNumericReferences(v)
+ v = ResolveEntityNames(v)
+ }
+ cob := NewCopyOnWriteBuffer(v)
+ limit := len(v)
+ n := 0
+
+ for i := 0; i < limit; {
+ c := v[i]
+ if urlEscapeTable[c] == 1 {
+ i++
+ continue
+ }
+ if c == '%' && i+2 < limit && IsHexDecimal(v[i+1]) && IsHexDecimal(v[i+1]) {
+ i += 3
+ continue
+ }
+ u8len := utf8lenTable[c]
+ if u8len == 99 { // invalid utf8 leading byte, skip it
+ i++
+ continue
+ }
+ if c == ' ' {
+ cob.Write(v[n:i])
+ cob.Write(htmlSpace)
+ i++
+ n = i
+ continue
+ }
+ if int(u8len) > len(v) {
+ u8len = int8(len(v) - 1)
+ }
+ if u8len == 0 {
+ i++
+ n = i
+ continue
+ }
+ cob.Write(v[n:i])
+ stop := i + int(u8len)
+ if stop > len(v) {
+ i++
+ n = i
+ continue
+ }
+ cob.Write(StringToReadOnlyBytes(url.QueryEscape(string(v[i:stop]))))
+ i += int(u8len)
+ n = i
+ }
+ if cob.IsCopied() && n < limit {
+ cob.Write(v[n:])
+ }
+ return cob.Bytes()
+}
+
+// FindURLIndex returns a stop index value if the given bytes seem an URL.
+// This function is equivalent to [A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]* .
+func FindURLIndex(b []byte) int {
+ i := 0
+ if !(len(b) > 0 && urlTable[b[i]]&7 == 7) {
+ return -1
+ }
+ i++
+ for ; i < len(b); i++ {
+ c := b[i]
+ if urlTable[c]&4 != 4 {
+ break
+ }
+ }
+ if i == 1 || i > 33 || i >= len(b) {
+ return -1
+ }
+ if b[i] != ':' {
+ return -1
+ }
+ i++
+ for ; i < len(b); i++ {
+ c := b[i]
+ if urlTable[c]&1 != 1 {
+ break
+ }
+ }
+ return i
+}
+
+var emailDomainRegexp = regexp.MustCompile(`^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*`)
+
+// FindEmailIndex returns a stop index value if the given bytes seem an email address.
+func FindEmailIndex(b []byte) int {
+ // TODO: eliminate regexps
+ i := 0
+ for ; i < len(b); i++ {
+ c := b[i]
+ if emailTable[c]&1 != 1 {
+ break
+ }
+ }
+ if i == 0 {
+ return -1
+ }
+ if i >= len(b) || b[i] != '@' {
+ return -1
+ }
+ i++
+ if i >= len(b) {
+ return -1
+ }
+ match := emailDomainRegexp.FindSubmatchIndex(b[i:])
+ if match == nil {
+ return -1
+ }
+ return i + match[1]
+}
+
+var spaces = []byte(" \t\n\x0b\x0c\x0d")
+
+var spaceTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+var punctTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+// a-zA-Z0-9, ;/?:@&=+$,-_.!~*'()#
+var urlEscapeTable = [256]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+var utf8lenTable = [256]int8{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 99, 99, 99, 99, 99, 99, 99, 99}
+
+var urlTable = [256]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 5, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 0, 1, 0, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+
+var emailTable = [256]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+// UTF8Len returns a byte length of the utf-8 character.
+func UTF8Len(b byte) int8 {
+ return utf8lenTable[b]
+}
+
+// IsPunct returns true if the given character is a punctuation, otherwise false.
+func IsPunct(c byte) bool {
+ return punctTable[c] == 1
+}
+
+// IsPunctRune returns true if the given rune is a punctuation, otherwise false.
+func IsPunctRune(r rune) bool {
+ return int32(r) <= 256 && IsPunct(byte(r)) || unicode.IsPunct(r)
+}
+
+// IsSpace returns true if the given character is a space, otherwise false.
+func IsSpace(c byte) bool {
+ return spaceTable[c] == 1
+}
+
+// IsSpaceRune returns true if the given rune is a space, otherwise false.
+func IsSpaceRune(r rune) bool {
+ return int32(r) <= 256 && IsSpace(byte(r)) || unicode.IsSpace(r)
+}
+
+// IsNumeric returns true if the given character is a numeric, otherwise false.
+func IsNumeric(c byte) bool {
+ return c >= '0' && c <= '9'
+}
+
+// IsHexDecimal returns true if the given character is a hexdecimal, otherwise false.
+func IsHexDecimal(c byte) bool {
+ return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F'
+}
+
+// IsAlphaNumeric returns true if the given character is a alphabet or a numeric, otherwise false.
+func IsAlphaNumeric(c byte) bool {
+ return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'
+}
+
+// A BufWriter is a subset of the bufio.Writer .
+type BufWriter interface {
+ io.Writer
+ Available() int
+ Buffered() int
+ Flush() error
+ WriteByte(c byte) error
+ WriteRune(r rune) (size int, err error)
+ WriteString(s string) (int, error)
+}
+
+// A PrioritizedValue struct holds pair of an arbitrary value and a priority.
+type PrioritizedValue struct {
+ // Value is an arbitrary value that you want to prioritize.
+ Value interface{}
+ // Priority is a priority of the value.
+ Priority int
+}
+
+// PrioritizedSlice is a slice of the PrioritizedValues
+type PrioritizedSlice []PrioritizedValue
+
+// Sort sorts the PrioritizedSlice in ascending order.
+func (s PrioritizedSlice) Sort() {
+ sort.Slice(s, func(i, j int) bool {
+ return s[i].Priority < s[j].Priority
+ })
+}
+
+// Remove removes the given value from this slice.
+func (s PrioritizedSlice) Remove(v interface{}) PrioritizedSlice {
+ i := 0
+ found := false
+ for ; i < len(s); i++ {
+ if s[i].Value == v {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return s
+ }
+ return append(s[:i], s[i+1:]...)
+}
+
+// Prioritized returns a new PrioritizedValue.
+func Prioritized(v interface{}, priority int) PrioritizedValue {
+ return PrioritizedValue{v, priority}
+}
+
+func bytesHash(b []byte) uint64 {
+ var hash uint64 = 5381
+ for _, c := range b {
+ hash = ((hash << 5) + hash) + uint64(c)
+ }
+ return hash
+}
+
+// BytesFilter is a efficient data structure for checking whether bytes exist or not.
+// BytesFilter is thread-safe.
+type BytesFilter interface {
+ // Add adds given bytes to this set.
+ Add([]byte)
+
+ // Contains return true if this set contains given bytes, otherwise false.
+ Contains([]byte) bool
+
+ // Extend copies this filter and adds given bytes to new filter.
+ Extend(...[]byte) BytesFilter
+}
+
+type bytesFilter struct {
+ chars [256]uint8
+ threshold int
+ slots [][][]byte
+}
+
+// NewBytesFilter returns a new BytesFilter.
+func NewBytesFilter(elements ...[]byte) BytesFilter {
+ s := &bytesFilter{
+ threshold: 3,
+ slots: make([][][]byte, 64),
+ }
+ for _, element := range elements {
+ s.Add(element)
+ }
+ return s
+}
+
+func (s *bytesFilter) Add(b []byte) {
+ l := len(b)
+ m := s.threshold
+ if l < s.threshold {
+ m = l
+ }
+ for i := 0; i < m; i++ {
+ s.chars[b[i]] |= 1 << uint8(i)
+ }
+ h := bytesHash(b) % uint64(len(s.slots))
+ slot := s.slots[h]
+ if slot == nil {
+ slot = [][]byte{}
+ }
+ s.slots[h] = append(slot, b)
+}
+
+func (s *bytesFilter) Extend(bs ...[]byte) BytesFilter {
+ newFilter := NewBytesFilter().(*bytesFilter)
+ newFilter.chars = s.chars
+ newFilter.threshold = s.threshold
+ for k, v := range s.slots {
+ newSlot := make([][]byte, len(v))
+ copy(newSlot, v)
+ newFilter.slots[k] = v
+ }
+ for _, b := range bs {
+ newFilter.Add(b)
+ }
+ return newFilter
+}
+
+func (s *bytesFilter) Contains(b []byte) bool {
+ l := len(b)
+ m := s.threshold
+ if l < s.threshold {
+ m = l
+ }
+ for i := 0; i < m; i++ {
+ if (s.chars[b[i]] & (1 << uint8(i))) == 0 {
+ return false
+ }
+ }
+ h := bytesHash(b) % uint64(len(s.slots))
+ slot := s.slots[h]
+ if slot == nil || len(slot) == 0 {
+ return false
+ }
+ for _, element := range slot {
+ if bytes.Equal(element, b) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/yuin/goldmark/util/util_safe.go b/vendor/github.com/yuin/goldmark/util/util_safe.go
new file mode 100644
index 0000000..507a9d0
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/util_safe.go
@@ -0,0 +1,13 @@
+// +build appengine js
+
+package util
+
+// BytesToReadOnlyString returns a string converted from given bytes.
+func BytesToReadOnlyString(b []byte) string {
+ return string(b)
+}
+
+// StringToReadOnlyBytes returns bytes converted from given string.
+func StringToReadOnlyBytes(s string) []byte {
+ return []byte(s)
+}
diff --git a/vendor/github.com/yuin/goldmark/util/util_unsafe.go b/vendor/github.com/yuin/goldmark/util/util_unsafe.go
new file mode 100644
index 0000000..d098811
--- /dev/null
+++ b/vendor/github.com/yuin/goldmark/util/util_unsafe.go
@@ -0,0 +1,23 @@
+// +build !appengine,!js
+
+package util
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// BytesToReadOnlyString returns a string converted from given bytes.
+func BytesToReadOnlyString(b []byte) string {
+ return *(*string)(unsafe.Pointer(&b))
+}
+
+// StringToReadOnlyBytes returns bytes converted from given string.
+func StringToReadOnlyBytes(s string) (bs []byte) {
+ sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
+ bh := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
+ bh.Data = sh.Data
+ bh.Cap = sh.Len
+ bh.Len = sh.Len
+ return
+}
diff --git a/vendor/gopkg.in/yaml.v2/.travis.yml b/vendor/gopkg.in/yaml.v2/.travis.yml
new file mode 100644
index 0000000..055480b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/.travis.yml
@@ -0,0 +1,16 @@
+language: go
+
+go:
+ - "1.4.x"
+ - "1.5.x"
+ - "1.6.x"
+ - "1.7.x"
+ - "1.8.x"
+ - "1.9.x"
+ - "1.10.x"
+ - "1.11.x"
+ - "1.12.x"
+ - "1.13.x"
+ - "tip"
+
+go_import_path: gopkg.in/yaml.v2
diff --git a/vendor/gopkg.in/yaml.v2/LICENSE b/vendor/gopkg.in/yaml.v2/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v2/LICENSE.libyaml b/vendor/gopkg.in/yaml.v2/LICENSE.libyaml
new file mode 100644
index 0000000..8da58fb
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/LICENSE.libyaml
@@ -0,0 +1,31 @@
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original copyright and license:
+
+ apic.go
+ emitterc.go
+ parserc.go
+ readerc.go
+ scannerc.go
+ writerc.go
+ yamlh.go
+ yamlprivateh.go
+
+Copyright (c) 2006 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/gopkg.in/yaml.v2/NOTICE b/vendor/gopkg.in/yaml.v2/NOTICE
new file mode 100644
index 0000000..866d74a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/NOTICE
@@ -0,0 +1,13 @@
+Copyright 2011-2016 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v2/README.md b/vendor/gopkg.in/yaml.v2/README.md
new file mode 100644
index 0000000..b50c6e8
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/README.md
@@ -0,0 +1,133 @@
+# YAML support for the Go language
+
+Introduction
+------------
+
+The yaml package enables Go programs to comfortably encode and decode YAML
+values. It was developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a
+pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
+C library to parse and generate YAML data quickly and reliably.
+
+Compatibility
+-------------
+
+The yaml package supports most of YAML 1.1 and 1.2, including support for
+anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
+implemented, and base-60 floats from YAML 1.1 are purposefully not
+supported since they're a poor design and are gone in YAML 1.2.
+
+Installation and usage
+----------------------
+
+The import path for the package is *gopkg.in/yaml.v2*.
+
+To install it, run:
+
+ go get gopkg.in/yaml.v2
+
+API documentation
+-----------------
+
+If opened in a browser, the import path itself leads to the API documentation:
+
+ * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
+
+API stability
+-------------
+
+The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
+
+
+License
+-------
+
+The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
+
+
+Example
+-------
+
+```Go
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "gopkg.in/yaml.v2"
+)
+
+var data = `
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+ A string
+ B struct {
+ RenamedC int `yaml:"c"`
+ D []int `yaml:",flow"`
+ }
+}
+
+func main() {
+ t := T{}
+
+ err := yaml.Unmarshal([]byte(data), &t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t:\n%v\n\n", t)
+
+ d, err := yaml.Marshal(&t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+ m := make(map[interface{}]interface{})
+
+ err = yaml.Unmarshal([]byte(data), &m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m:\n%v\n\n", m)
+
+ d, err = yaml.Marshal(&m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+ c: 2
+ d:
+ - 3
+ - 4
+```
+
diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v2/apic.go
new file mode 100644
index 0000000..d2c2308
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/apic.go
@@ -0,0 +1,740 @@
+package yaml
+
+import (
+ "io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+ // Check if we can move the queue at the beginning of the buffer.
+ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+ if parser.tokens_head != len(parser.tokens) {
+ copy(parser.tokens, parser.tokens[parser.tokens_head:])
+ }
+ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+ parser.tokens_head = 0
+ }
+ parser.tokens = append(parser.tokens, *token)
+ if pos < 0 {
+ return
+ }
+ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+ parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+ *parser = yaml_parser_t{
+ raw_buffer: make([]byte, 0, input_raw_buffer_size),
+ buffer: make([]byte, 0, input_buffer_size),
+ }
+ return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+ *parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ if parser.input_pos == len(parser.input) {
+ return 0, io.EOF
+ }
+ n = copy(buffer, parser.input[parser.input_pos:])
+ parser.input_pos += n
+ return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_string_read_handler
+ parser.input = input
+ parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_reader_read_handler
+ parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+ if parser.encoding != yaml_ANY_ENCODING {
+ panic("must set the encoding only once")
+ }
+ parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{
+ buffer: make([]byte, output_buffer_size),
+ raw_buffer: make([]byte, 0, output_raw_buffer_size),
+ states: make([]yaml_emitter_state_t, 0, initial_stack_size),
+ events: make([]yaml_event_t, 0, initial_queue_size),
+ best_width: -1,
+ }
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+ return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ _, err := emitter.output_writer.Write(buffer)
+ return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_string_write_handler
+ emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_writer_write_handler
+ emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+ if emitter.encoding != yaml_ANY_ENCODING {
+ panic("must set the output encoding only once")
+ }
+ emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+ emitter.canonical = canonical
+}
+
+//// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+ if indent < 2 || indent > 9 {
+ indent = 2
+ }
+ emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+ if width < 0 {
+ width = -1
+ }
+ emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+ emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+ emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+// assert(token); // Non-NULL token object expected.
+//
+// switch (token.type)
+// {
+// case YAML_TAG_DIRECTIVE_TOKEN:
+// yaml_free(token.data.tag_directive.handle);
+// yaml_free(token.data.tag_directive.prefix);
+// break;
+//
+// case YAML_ALIAS_TOKEN:
+// yaml_free(token.data.alias.value);
+// break;
+//
+// case YAML_ANCHOR_TOKEN:
+// yaml_free(token.data.anchor.value);
+// break;
+//
+// case YAML_TAG_TOKEN:
+// yaml_free(token.data.tag.handle);
+// yaml_free(token.data.tag.suffix);
+// break;
+//
+// case YAML_SCALAR_TOKEN:
+// yaml_free(token.data.scalar.value);
+// break;
+//
+// default:
+// break;
+// }
+//
+// memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+// yaml_char_t *end = start+length;
+// yaml_char_t *pointer = start;
+//
+// while (pointer < end) {
+// unsigned char octet;
+// unsigned int width;
+// unsigned int value;
+// size_t k;
+//
+// octet = pointer[0];
+// width = (octet & 0x80) == 0x00 ? 1 :
+// (octet & 0xE0) == 0xC0 ? 2 :
+// (octet & 0xF0) == 0xE0 ? 3 :
+// (octet & 0xF8) == 0xF0 ? 4 : 0;
+// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+// if (!width) return 0;
+// if (pointer+width > end) return 0;
+// for (k = 1; k < width; k ++) {
+// octet = pointer[k];
+// if ((octet & 0xC0) != 0x80) return 0;
+// value = (value << 6) + (octet & 0x3F);
+// }
+// if (!((width == 1) ||
+// (width == 2 && value >= 0x80) ||
+// (width == 3 && value >= 0x800) ||
+// (width == 4 && value >= 0x10000))) return 0;
+//
+// pointer += width;
+// }
+//
+// return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ encoding: encoding,
+ }
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ }
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+ event *yaml_event_t,
+ version_directive *yaml_version_directive_t,
+ tag_directives []yaml_tag_directive_t,
+ implicit bool,
+) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: implicit,
+ }
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ implicit: implicit,
+ }
+}
+
+///*
+// * Create ALIAS.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
+//{
+// mark yaml_mark_t = { 0, 0, 0 }
+// anchor_copy *yaml_char_t = NULL
+//
+// assert(event) // Non-NULL event object is expected.
+// assert(anchor) // Non-NULL anchor is expected.
+//
+// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
+//
+// anchor_copy = yaml_strdup(anchor)
+// if (!anchor_copy)
+// return 0
+//
+// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
+//
+// return 1
+//}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ anchor: anchor,
+ tag: tag,
+ value: value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ }
+ return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ }
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+ *event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+// version_directive *yaml_version_directive_t,
+// tag_directives_start *yaml_tag_directive_t,
+// tag_directives_end *yaml_tag_directive_t,
+// start_implicit int, end_implicit int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// struct {
+// start *yaml_node_t
+// end *yaml_node_t
+// top *yaml_node_t
+// } nodes = { NULL, NULL, NULL }
+// version_directive_copy *yaml_version_directive_t = NULL
+// struct {
+// start *yaml_tag_directive_t
+// end *yaml_tag_directive_t
+// top *yaml_tag_directive_t
+// } tag_directives_copy = { NULL, NULL, NULL }
+// value yaml_tag_directive_t = { NULL, NULL }
+// mark yaml_mark_t = { 0, 0, 0 }
+//
+// assert(document) // Non-NULL document object is expected.
+// assert((tag_directives_start && tag_directives_end) ||
+// (tag_directives_start == tag_directives_end))
+// // Valid tag directives are expected.
+//
+// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+// if (version_directive) {
+// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+// if (!version_directive_copy) goto error
+// version_directive_copy.major = version_directive.major
+// version_directive_copy.minor = version_directive.minor
+// }
+//
+// if (tag_directives_start != tag_directives_end) {
+// tag_directive *yaml_tag_directive_t
+// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+// goto error
+// for (tag_directive = tag_directives_start
+// tag_directive != tag_directives_end; tag_directive ++) {
+// assert(tag_directive.handle)
+// assert(tag_directive.prefix)
+// if (!yaml_check_utf8(tag_directive.handle,
+// strlen((char *)tag_directive.handle)))
+// goto error
+// if (!yaml_check_utf8(tag_directive.prefix,
+// strlen((char *)tag_directive.prefix)))
+// goto error
+// value.handle = yaml_strdup(tag_directive.handle)
+// value.prefix = yaml_strdup(tag_directive.prefix)
+// if (!value.handle || !value.prefix) goto error
+// if (!PUSH(&context, tag_directives_copy, value))
+// goto error
+// value.handle = NULL
+// value.prefix = NULL
+// }
+// }
+//
+// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+// tag_directives_copy.start, tag_directives_copy.top,
+// start_implicit, end_implicit, mark, mark)
+//
+// return 1
+//
+//error:
+// STACK_DEL(&context, nodes)
+// yaml_free(version_directive_copy)
+// while (!STACK_EMPTY(&context, tag_directives_copy)) {
+// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+// }
+// STACK_DEL(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+//
+// return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// tag_directive *yaml_tag_directive_t
+//
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// while (!STACK_EMPTY(&context, document.nodes)) {
+// node yaml_node_t = POP(&context, document.nodes)
+// yaml_free(node.tag)
+// switch (node.type) {
+// case YAML_SCALAR_NODE:
+// yaml_free(node.data.scalar.value)
+// break
+// case YAML_SEQUENCE_NODE:
+// STACK_DEL(&context, node.data.sequence.items)
+// break
+// case YAML_MAPPING_NODE:
+// STACK_DEL(&context, node.data.mapping.pairs)
+// break
+// default:
+// assert(0) // Should not happen.
+// }
+// }
+// STACK_DEL(&context, document.nodes)
+//
+// yaml_free(document.version_directive)
+// for (tag_directive = document.tag_directives.start
+// tag_directive != document.tag_directives.end
+// tag_directive++) {
+// yaml_free(tag_directive.handle)
+// yaml_free(tag_directive.prefix)
+// }
+// yaml_free(document.tag_directives.start)
+//
+// memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+// return document.nodes.start + index - 1
+// }
+// return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (document.nodes.top != document.nodes.start) {
+// return document.nodes.start
+// }
+// return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+// tag *yaml_char_t, value *yaml_char_t, length int,
+// style yaml_scalar_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// value_copy *yaml_char_t = NULL
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+// assert(value) // Non-NULL value is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (length < 0) {
+// length = strlen((char *)value)
+// }
+//
+// if (!yaml_check_utf8(value, length)) goto error
+// value_copy = yaml_malloc(length+1)
+// if (!value_copy) goto error
+// memcpy(value_copy, value, length)
+// value_copy[length] = '\0'
+//
+// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// yaml_free(tag_copy)
+// yaml_free(value_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_item_t
+// end *yaml_node_item_t
+// top *yaml_node_item_t
+// } items = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, items)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_pair_t
+// end *yaml_node_pair_t
+// top *yaml_node_pair_t
+// } pairs = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, pairs)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+// sequence int, item int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// assert(document) // Non-NULL document is required.
+// assert(sequence > 0
+// && document.nodes.start + sequence <= document.nodes.top)
+// // Valid sequence id is required.
+// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+// // A sequence node is required.
+// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+// // Valid item id is required.
+//
+// if (!PUSH(&context,
+// document.nodes.start[sequence-1].data.sequence.items, item))
+// return 0
+//
+// return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+// mapping int, key int, value int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// pair yaml_node_pair_t
+//
+// assert(document) // Non-NULL document is required.
+// assert(mapping > 0
+// && document.nodes.start + mapping <= document.nodes.top)
+// // Valid mapping id is required.
+// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+// // A mapping node is required.
+// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+// // Valid key id is required.
+// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+// // Valid value id is required.
+//
+// pair.key = key
+// pair.value = value
+//
+// if (!PUSH(&context,
+// document.nodes.start[mapping-1].data.mapping.pairs, pair))
+// return 0
+//
+// return 1
+//}
+//
+//
diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v2/decode.go
new file mode 100644
index 0000000..129bc2a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/decode.go
@@ -0,0 +1,815 @@
+package yaml
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+const (
+ documentNode = 1 << iota
+ mappingNode
+ sequenceNode
+ scalarNode
+ aliasNode
+)
+
+type node struct {
+ kind int
+ line, column int
+ tag string
+ // For an alias node, alias holds the resolved alias.
+ alias *node
+ value string
+ implicit bool
+ children []*node
+ anchors map[string]*node
+}
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+ parser yaml_parser_t
+ event yaml_event_t
+ doc *node
+ doneInit bool
+}
+
+func newParser(b []byte) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ if len(b) == 0 {
+ b = []byte{'\n'}
+ }
+ yaml_parser_set_input_string(&p.parser, b)
+ return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ yaml_parser_set_input_reader(&p.parser, r)
+ return &p
+}
+
+func (p *parser) init() {
+ if p.doneInit {
+ return
+ }
+ p.expect(yaml_STREAM_START_EVENT)
+ p.doneInit = true
+}
+
+func (p *parser) destroy() {
+ if p.event.typ != yaml_NO_EVENT {
+ yaml_event_delete(&p.event)
+ }
+ yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+ if p.event.typ == yaml_NO_EVENT {
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ }
+ if p.event.typ == yaml_STREAM_END_EVENT {
+ failf("attempted to go past the end of stream; corrupted value?")
+ }
+ if p.event.typ != e {
+ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+ p.fail()
+ }
+ yaml_event_delete(&p.event)
+ p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+ if p.event.typ != yaml_NO_EVENT {
+ return p.event.typ
+ }
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ return p.event.typ
+}
+
+func (p *parser) fail() {
+ var where string
+ var line int
+ if p.parser.problem_mark.line != 0 {
+ line = p.parser.problem_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ } else if p.parser.context_mark.line != 0 {
+ line = p.parser.context_mark.line
+ }
+ if line != 0 {
+ where = "line " + strconv.Itoa(line) + ": "
+ }
+ var msg string
+ if len(p.parser.problem) > 0 {
+ msg = p.parser.problem
+ } else {
+ msg = "unknown problem parsing YAML content"
+ }
+ failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *node, anchor []byte) {
+ if anchor != nil {
+ p.doc.anchors[string(anchor)] = n
+ }
+}
+
+func (p *parser) parse() *node {
+ p.init()
+ switch p.peek() {
+ case yaml_SCALAR_EVENT:
+ return p.scalar()
+ case yaml_ALIAS_EVENT:
+ return p.alias()
+ case yaml_MAPPING_START_EVENT:
+ return p.mapping()
+ case yaml_SEQUENCE_START_EVENT:
+ return p.sequence()
+ case yaml_DOCUMENT_START_EVENT:
+ return p.document()
+ case yaml_STREAM_END_EVENT:
+ // Happens when attempting to decode an empty buffer.
+ return nil
+ default:
+ panic("attempted to parse unknown event: " + p.event.typ.String())
+ }
+}
+
+func (p *parser) node(kind int) *node {
+ return &node{
+ kind: kind,
+ line: p.event.start_mark.line,
+ column: p.event.start_mark.column,
+ }
+}
+
+func (p *parser) document() *node {
+ n := p.node(documentNode)
+ n.anchors = make(map[string]*node)
+ p.doc = n
+ p.expect(yaml_DOCUMENT_START_EVENT)
+ n.children = append(n.children, p.parse())
+ p.expect(yaml_DOCUMENT_END_EVENT)
+ return n
+}
+
+func (p *parser) alias() *node {
+ n := p.node(aliasNode)
+ n.value = string(p.event.anchor)
+ n.alias = p.doc.anchors[n.value]
+ if n.alias == nil {
+ failf("unknown anchor '%s' referenced", n.value)
+ }
+ p.expect(yaml_ALIAS_EVENT)
+ return n
+}
+
+func (p *parser) scalar() *node {
+ n := p.node(scalarNode)
+ n.value = string(p.event.value)
+ n.tag = string(p.event.tag)
+ n.implicit = p.event.implicit
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SCALAR_EVENT)
+ return n
+}
+
+func (p *parser) sequence() *node {
+ n := p.node(sequenceNode)
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SEQUENCE_START_EVENT)
+ for p.peek() != yaml_SEQUENCE_END_EVENT {
+ n.children = append(n.children, p.parse())
+ }
+ p.expect(yaml_SEQUENCE_END_EVENT)
+ return n
+}
+
+func (p *parser) mapping() *node {
+ n := p.node(mappingNode)
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_MAPPING_START_EVENT)
+ for p.peek() != yaml_MAPPING_END_EVENT {
+ n.children = append(n.children, p.parse(), p.parse())
+ }
+ p.expect(yaml_MAPPING_END_EVENT)
+ return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+ doc *node
+ aliases map[*node]bool
+ mapType reflect.Type
+ terrors []string
+ strict bool
+
+ decodeCount int
+ aliasCount int
+ aliasDepth int
+}
+
+var (
+ mapItemType = reflect.TypeOf(MapItem{})
+ durationType = reflect.TypeOf(time.Duration(0))
+ defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
+ ifaceType = defaultMapType.Elem()
+ timeType = reflect.TypeOf(time.Time{})
+ ptrTimeType = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder(strict bool) *decoder {
+ d := &decoder{mapType: defaultMapType, strict: strict}
+ d.aliases = make(map[*node]bool)
+ return d
+}
+
+func (d *decoder) terror(n *node, tag string, out reflect.Value) {
+ if n.tag != "" {
+ tag = n.tag
+ }
+ value := n.value
+ if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
+ if len(value) > 10 {
+ value = " `" + value[:7] + "...`"
+ } else {
+ value = " `" + value + "`"
+ }
+ }
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
+ terrlen := len(d.terrors)
+ err := u.UnmarshalYAML(func(v interface{}) (err error) {
+ defer handleErr(&err)
+ d.unmarshal(n, reflect.ValueOf(v))
+ if len(d.terrors) > terrlen {
+ issues := d.terrors[terrlen:]
+ d.terrors = d.terrors[:terrlen]
+ return &TypeError{issues}
+ }
+ return nil
+ })
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+ if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
+ return out, false, false
+ }
+ again := true
+ for again {
+ again = false
+ if out.Kind() == reflect.Ptr {
+ if out.IsNil() {
+ out.Set(reflect.New(out.Type().Elem()))
+ }
+ out = out.Elem()
+ again = true
+ }
+ if out.CanAddr() {
+ if u, ok := out.Addr().Interface().(Unmarshaler); ok {
+ good = d.callUnmarshaler(n, u)
+ return out, true, good
+ }
+ }
+ }
+ return out, false, false
+}
+
+const (
+ // 400,000 decode operations is ~500kb of dense object declarations, or
+ // ~5kb of dense object declarations with 10000% alias expansion
+ alias_ratio_range_low = 400000
+
+ // 4,000,000 decode operations is ~5MB of dense object declarations, or
+ // ~4.5MB of dense object declarations with 10% alias expansion
+ alias_ratio_range_high = 4000000
+
+ // alias_ratio_range is the range over which we scale allowed alias ratios
+ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(decodeCount int) float64 {
+ switch {
+ case decodeCount <= alias_ratio_range_low:
+ // allow 99% to come from alias expansion for small-to-medium documents
+ return 0.99
+ case decodeCount >= alias_ratio_range_high:
+ // allow 10% to come from alias expansion for very large documents
+ return 0.10
+ default:
+ // scale smoothly from 99% down to 10% over the range.
+ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+ return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
+ }
+}
+
+func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
+ d.decodeCount++
+ if d.aliasDepth > 0 {
+ d.aliasCount++
+ }
+ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
+ failf("document contains excessive aliasing")
+ }
+ switch n.kind {
+ case documentNode:
+ return d.document(n, out)
+ case aliasNode:
+ return d.alias(n, out)
+ }
+ out, unmarshaled, good := d.prepare(n, out)
+ if unmarshaled {
+ return good
+ }
+ switch n.kind {
+ case scalarNode:
+ good = d.scalar(n, out)
+ case mappingNode:
+ good = d.mapping(n, out)
+ case sequenceNode:
+ good = d.sequence(n, out)
+ default:
+ panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
+ }
+ return good
+}
+
+func (d *decoder) document(n *node, out reflect.Value) (good bool) {
+ if len(n.children) == 1 {
+ d.doc = n
+ d.unmarshal(n.children[0], out)
+ return true
+ }
+ return false
+}
+
+func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
+ if d.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
+ failf("anchor '%s' value contains itself", n.value)
+ }
+ d.aliases[n] = true
+ d.aliasDepth++
+ good = d.unmarshal(n.alias, out)
+ d.aliasDepth--
+ delete(d.aliases, n)
+ return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+ for _, k := range out.MapKeys() {
+ out.SetMapIndex(k, zeroValue)
+ }
+}
+
+func (d *decoder) scalar(n *node, out reflect.Value) bool {
+ var tag string
+ var resolved interface{}
+ if n.tag == "" && !n.implicit {
+ tag = yaml_STR_TAG
+ resolved = n.value
+ } else {
+ tag, resolved = resolve(n.tag, n.value)
+ if tag == yaml_BINARY_TAG {
+ data, err := base64.StdEncoding.DecodeString(resolved.(string))
+ if err != nil {
+ failf("!!binary value contains invalid base64 data")
+ }
+ resolved = string(data)
+ }
+ }
+ if resolved == nil {
+ if out.Kind() == reflect.Map && !out.CanAddr() {
+ resetMap(out)
+ } else {
+ out.Set(reflect.Zero(out.Type()))
+ }
+ return true
+ }
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ // We've resolved to exactly the type we want, so use that.
+ out.Set(resolvedv)
+ return true
+ }
+ // Perhaps we can use the value as a TextUnmarshaler to
+ // set its value.
+ if out.CanAddr() {
+ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ if ok {
+ var text []byte
+ if tag == yaml_BINARY_TAG {
+ text = []byte(resolved.(string))
+ } else {
+ // We let any value be unmarshaled into TextUnmarshaler.
+ // That might be more lax than we'd like, but the
+ // TextUnmarshaler itself should bowl out any dubious values.
+ text = []byte(n.value)
+ }
+ err := u.UnmarshalText(text)
+ if err != nil {
+ fail(err)
+ }
+ return true
+ }
+ }
+ switch out.Kind() {
+ case reflect.String:
+ if tag == yaml_BINARY_TAG {
+ out.SetString(resolved.(string))
+ return true
+ }
+ if resolved != nil {
+ out.SetString(n.value)
+ return true
+ }
+ case reflect.Interface:
+ if resolved == nil {
+ out.Set(reflect.Zero(out.Type()))
+ } else if tag == yaml_TIMESTAMP_TAG {
+ // It looks like a timestamp but for backward compatibility
+ // reasons we set it as a string, so that code that unmarshals
+ // timestamp-like values into interface{} will continue to
+ // see a string and not a time.Time.
+ // TODO(v3) Drop this.
+ out.Set(reflect.ValueOf(n.value))
+ } else {
+ out.Set(reflect.ValueOf(resolved))
+ }
+ return true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ switch resolved := resolved.(type) {
+ case int:
+ if !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case int64:
+ if !out.OverflowInt(resolved) {
+ out.SetInt(resolved)
+ return true
+ }
+ case uint64:
+ if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case string:
+ if out.Type() == durationType {
+ d, err := time.ParseDuration(resolved)
+ if err == nil {
+ out.SetInt(int64(d))
+ return true
+ }
+ }
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch resolved := resolved.(type) {
+ case int:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case int64:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case uint64:
+ if !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ }
+ case reflect.Bool:
+ switch resolved := resolved.(type) {
+ case bool:
+ out.SetBool(resolved)
+ return true
+ }
+ case reflect.Float32, reflect.Float64:
+ switch resolved := resolved.(type) {
+ case int:
+ out.SetFloat(float64(resolved))
+ return true
+ case int64:
+ out.SetFloat(float64(resolved))
+ return true
+ case uint64:
+ out.SetFloat(float64(resolved))
+ return true
+ case float64:
+ out.SetFloat(resolved)
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
+ }
+ case reflect.Ptr:
+ if out.Type().Elem() == reflect.TypeOf(resolved) {
+ // TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
+ elem := reflect.New(out.Type().Elem())
+ elem.Elem().Set(reflect.ValueOf(resolved))
+ out.Set(elem)
+ return true
+ }
+ }
+ d.terror(n, tag, out)
+ return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+ v := reflect.ValueOf(i)
+ sv := reflect.New(v.Type()).Elem()
+ sv.Set(v)
+ return sv
+}
+
+func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
+ l := len(n.children)
+
+ var iface reflect.Value
+ switch out.Kind() {
+ case reflect.Slice:
+ out.Set(reflect.MakeSlice(out.Type(), l, l))
+ case reflect.Array:
+ if l != out.Len() {
+ failf("invalid array: want %d elements but got %d", out.Len(), l)
+ }
+ case reflect.Interface:
+ // No type hints. Will have to use a generic sequence.
+ iface = out
+ out = settableValueOf(make([]interface{}, l))
+ default:
+ d.terror(n, yaml_SEQ_TAG, out)
+ return false
+ }
+ et := out.Type().Elem()
+
+ j := 0
+ for i := 0; i < l; i++ {
+ e := reflect.New(et).Elem()
+ if ok := d.unmarshal(n.children[i], e); ok {
+ out.Index(j).Set(e)
+ j++
+ }
+ }
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
+ if iface.IsValid() {
+ iface.Set(out)
+ }
+ return true
+}
+
+func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
+ switch out.Kind() {
+ case reflect.Struct:
+ return d.mappingStruct(n, out)
+ case reflect.Slice:
+ return d.mappingSlice(n, out)
+ case reflect.Map:
+ // okay
+ case reflect.Interface:
+ if d.mapType.Kind() == reflect.Map {
+ iface := out
+ out = reflect.MakeMap(d.mapType)
+ iface.Set(out)
+ } else {
+ slicev := reflect.New(d.mapType).Elem()
+ if !d.mappingSlice(n, slicev) {
+ return false
+ }
+ out.Set(slicev)
+ return true
+ }
+ default:
+ d.terror(n, yaml_MAP_TAG, out)
+ return false
+ }
+ outt := out.Type()
+ kt := outt.Key()
+ et := outt.Elem()
+
+ mapType := d.mapType
+ if outt.Key() == ifaceType && outt.Elem() == ifaceType {
+ d.mapType = outt
+ }
+
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(outt))
+ }
+ l := len(n.children)
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.children[i]) {
+ d.merge(n.children[i+1], out)
+ continue
+ }
+ k := reflect.New(kt).Elem()
+ if d.unmarshal(n.children[i], k) {
+ kkind := k.Kind()
+ if kkind == reflect.Interface {
+ kkind = k.Elem().Kind()
+ }
+ if kkind == reflect.Map || kkind == reflect.Slice {
+ failf("invalid map key: %#v", k.Interface())
+ }
+ e := reflect.New(et).Elem()
+ if d.unmarshal(n.children[i+1], e) {
+ d.setMapIndex(n.children[i+1], out, k, e)
+ }
+ }
+ }
+ d.mapType = mapType
+ return true
+}
+
+func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
+ if d.strict && out.MapIndex(k) != zeroValue {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
+ return
+ }
+ out.SetMapIndex(k, v)
+}
+
+func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
+ outt := out.Type()
+ if outt.Elem() != mapItemType {
+ d.terror(n, yaml_MAP_TAG, out)
+ return false
+ }
+
+ mapType := d.mapType
+ d.mapType = outt
+
+ var slice []MapItem
+ var l = len(n.children)
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.children[i]) {
+ d.merge(n.children[i+1], out)
+ continue
+ }
+ item := MapItem{}
+ k := reflect.ValueOf(&item.Key).Elem()
+ if d.unmarshal(n.children[i], k) {
+ v := reflect.ValueOf(&item.Value).Elem()
+ if d.unmarshal(n.children[i+1], v) {
+ slice = append(slice, item)
+ }
+ }
+ }
+ out.Set(reflect.ValueOf(slice))
+ d.mapType = mapType
+ return true
+}
+
+func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
+ sinfo, err := getStructInfo(out.Type())
+ if err != nil {
+ panic(err)
+ }
+ name := settableValueOf("")
+ l := len(n.children)
+
+ var inlineMap reflect.Value
+ var elemType reflect.Type
+ if sinfo.InlineMap != -1 {
+ inlineMap = out.Field(sinfo.InlineMap)
+ inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
+ elemType = inlineMap.Type().Elem()
+ }
+
+ var doneFields []bool
+ if d.strict {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
+ for i := 0; i < l; i += 2 {
+ ni := n.children[i]
+ if isMerge(ni) {
+ d.merge(n.children[i+1], out)
+ continue
+ }
+ if !d.unmarshal(ni, name) {
+ continue
+ }
+ if info, ok := sinfo.FieldsMap[name.String()]; ok {
+ if d.strict {
+ if doneFields[info.Id] {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
+ continue
+ }
+ doneFields[info.Id] = true
+ }
+ var field reflect.Value
+ if info.Inline == nil {
+ field = out.Field(info.Num)
+ } else {
+ field = out.FieldByIndex(info.Inline)
+ }
+ d.unmarshal(n.children[i+1], field)
+ } else if sinfo.InlineMap != -1 {
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+ value := reflect.New(elemType).Elem()
+ d.unmarshal(n.children[i+1], value)
+ d.setMapIndex(n.children[i+1], inlineMap, name, value)
+ } else if d.strict {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
+ }
+ }
+ return true
+}
+
+func failWantMap() {
+ failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) merge(n *node, out reflect.Value) {
+ switch n.kind {
+ case mappingNode:
+ d.unmarshal(n, out)
+ case aliasNode:
+ if n.alias != nil && n.alias.kind != mappingNode {
+ failWantMap()
+ }
+ d.unmarshal(n, out)
+ case sequenceNode:
+ // Step backwards as earlier nodes take precedence.
+ for i := len(n.children) - 1; i >= 0; i-- {
+ ni := n.children[i]
+ if ni.kind == aliasNode {
+ if ni.alias != nil && ni.alias.kind != mappingNode {
+ failWantMap()
+ }
+ } else if ni.kind != mappingNode {
+ failWantMap()
+ }
+ d.unmarshal(ni, out)
+ }
+ default:
+ failWantMap()
+ }
+}
+
+func isMerge(n *node) bool {
+ return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
+}
diff --git a/vendor/gopkg.in/yaml.v2/emitterc.go b/vendor/gopkg.in/yaml.v2/emitterc.go
new file mode 100644
index 0000000..a1c2cc5
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/emitterc.go
@@ -0,0 +1,1685 @@
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ return yaml_emitter_flush(emitter)
+ }
+ return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.buffer[emitter.buffer_pos] = value
+ emitter.buffer_pos++
+ emitter.column++
+ return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ switch emitter.line_break {
+ case yaml_CR_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\r'
+ emitter.buffer_pos += 1
+ case yaml_LN_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\n'
+ emitter.buffer_pos += 1
+ case yaml_CRLN_BREAK:
+ emitter.buffer[emitter.buffer_pos+0] = '\r'
+ emitter.buffer[emitter.buffer_pos+1] = '\n'
+ emitter.buffer_pos += 2
+ default:
+ panic("unknown line break setting")
+ }
+ emitter.column = 0
+ emitter.line++
+ return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ p := emitter.buffer_pos
+ w := width(s[*i])
+ switch w {
+ case 4:
+ emitter.buffer[p+3] = s[*i+3]
+ fallthrough
+ case 3:
+ emitter.buffer[p+2] = s[*i+2]
+ fallthrough
+ case 2:
+ emitter.buffer[p+1] = s[*i+1]
+ fallthrough
+ case 1:
+ emitter.buffer[p+0] = s[*i+0]
+ default:
+ panic("unknown character width")
+ }
+ emitter.column++
+ emitter.buffer_pos += w
+ *i += w
+ return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+ for i := 0; i < len(s); {
+ if !write(emitter, s, &i) {
+ return false
+ }
+ }
+ return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if s[*i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ *i++
+ } else {
+ if !write(emitter, s, i) {
+ return false
+ }
+ emitter.column = 0
+ emitter.line++
+ }
+ return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_EMITTER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.events = append(emitter.events, *event)
+ for !yaml_emitter_need_more_events(emitter) {
+ event := &emitter.events[emitter.events_head]
+ if !yaml_emitter_analyze_event(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_state_machine(emitter, event) {
+ return false
+ }
+ yaml_event_delete(event)
+ emitter.events_head++
+ }
+ return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+// - 1 event for DOCUMENT-START
+// - 2 events for SEQUENCE-START
+// - 3 events for MAPPING-START
+//
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+ if emitter.events_head == len(emitter.events) {
+ return true
+ }
+ var accumulate int
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_DOCUMENT_START_EVENT:
+ accumulate = 1
+ break
+ case yaml_SEQUENCE_START_EVENT:
+ accumulate = 2
+ break
+ case yaml_MAPPING_START_EVENT:
+ accumulate = 3
+ break
+ default:
+ return false
+ }
+ if len(emitter.events)-emitter.events_head > accumulate {
+ return false
+ }
+ var level int
+ for i := emitter.events_head; i < len(emitter.events); i++ {
+ switch emitter.events[i].typ {
+ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+ level++
+ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+ level--
+ }
+ if level == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+ }
+ }
+
+ // [Go] Do we actually need to copy this given garbage collection
+ // and the lack of deallocating destructors?
+ tag_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(tag_copy.handle, value.handle)
+ copy(tag_copy.prefix, value.prefix)
+ emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+ return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+ emitter.indents = append(emitter.indents, emitter.indent)
+ if emitter.indent < 0 {
+ if flow {
+ emitter.indent = emitter.best_indent
+ } else {
+ emitter.indent = 0
+ }
+ } else if !indentless {
+ emitter.indent += emitter.best_indent
+ }
+ return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ switch emitter.state {
+ default:
+ case yaml_EMIT_STREAM_START_STATE:
+ return yaml_emitter_emit_stream_start(emitter, event)
+
+ case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, true)
+
+ case yaml_EMIT_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, false)
+
+ case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+ return yaml_emitter_emit_document_content(emitter, event)
+
+ case yaml_EMIT_DOCUMENT_END_STATE:
+ return yaml_emitter_emit_document_end(emitter, event)
+
+ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_END_STATE:
+ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+ }
+ panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_STREAM_START_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+ }
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = event.encoding
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = yaml_UTF8_ENCODING
+ }
+ }
+ if emitter.best_indent < 2 || emitter.best_indent > 9 {
+ emitter.best_indent = 2
+ }
+ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+ emitter.best_width = 80
+ }
+ if emitter.best_width < 0 {
+ emitter.best_width = 1<<31 - 1
+ }
+ if emitter.line_break == yaml_ANY_BREAK {
+ emitter.line_break = yaml_LN_BREAK
+ }
+
+ emitter.indent = -1
+ emitter.line = 0
+ emitter.column = 0
+ emitter.whitespace = true
+ emitter.indention = true
+
+ if emitter.encoding != yaml_UTF8_ENCODING {
+ if !yaml_emitter_write_bom(emitter) {
+ return false
+ }
+ }
+ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+ return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+ if event.typ == yaml_DOCUMENT_START_EVENT {
+
+ if event.version_directive != nil {
+ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+ return false
+ }
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(default_tag_directives); i++ {
+ tag_directive := &default_tag_directives[i]
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+ return false
+ }
+ }
+
+ implicit := event.implicit
+ if !first || emitter.canonical {
+ implicit = false
+ }
+
+ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if event.version_directive != nil {
+ implicit = false
+ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if len(event.tag_directives) > 0 {
+ implicit = false
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if yaml_emitter_check_empty_document(emitter) {
+ implicit = false
+ }
+ if !implicit {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+ return false
+ }
+ if emitter.canonical {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+ return true
+ }
+
+ if event.typ == yaml_STREAM_END_EVENT {
+ if emitter.open_ended {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_END_STATE
+ return true
+ }
+
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+ return yaml_emitter_emit_node(emitter, event, true, false, false, false)
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_DOCUMENT_END_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !event.implicit {
+ // [Go] Allocate the slice elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+ emitter.tag_directives = emitter.tag_directives[:0]
+ return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+
+ return true
+ }
+
+ if !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, true, false, false)
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+
+ if !first {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+ return false
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) {
+ return false
+ }
+ }
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, true, false, false)
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ return false
+ }
+ }
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+ return false
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+ root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+ emitter.root_context = root
+ emitter.sequence_context = sequence
+ emitter.mapping_context = mapping
+ emitter.simple_key_context = simple_key
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ return yaml_emitter_emit_alias(emitter, event)
+ case yaml_SCALAR_EVENT:
+ return yaml_emitter_emit_scalar(emitter, event)
+ case yaml_SEQUENCE_START_EVENT:
+ return yaml_emitter_emit_sequence_start(emitter, event)
+ case yaml_MAPPING_START_EVENT:
+ return yaml_emitter_emit_mapping_start(emitter, event)
+ default:
+ return yaml_emitter_set_emitter_error(emitter,
+ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+ }
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_select_scalar_style(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_scalar(emitter) {
+ return false
+ }
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+ yaml_emitter_check_empty_sequence(emitter) {
+ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+ }
+ return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+ yaml_emitter_check_empty_mapping(emitter) {
+ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+ }
+ return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+ return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+ length := 0
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_ALIAS_EVENT:
+ length += len(emitter.anchor_data.anchor)
+ case yaml_SCALAR_EVENT:
+ if emitter.scalar_data.multiline {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix) +
+ len(emitter.scalar_data.value)
+ case yaml_SEQUENCE_START_EVENT:
+ if !yaml_emitter_check_empty_sequence(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ case yaml_MAPPING_START_EVENT:
+ if !yaml_emitter_check_empty_mapping(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ default:
+ return false
+ }
+ return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+ if no_tag && !event.implicit && !event.quoted_implicit {
+ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+ }
+
+ style := event.scalar_style()
+ if style == yaml_ANY_SCALAR_STYLE {
+ style = yaml_PLAIN_SCALAR_STYLE
+ }
+ if emitter.canonical {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ if emitter.simple_key_context && emitter.scalar_data.multiline {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ if style == yaml_PLAIN_SCALAR_STYLE {
+ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if no_tag && !event.implicit {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+ if !emitter.scalar_data.single_quoted_allowed {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+
+ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+ emitter.tag_data.handle = []byte{'!'}
+ }
+ emitter.scalar_data.style = style
+ return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+ if emitter.anchor_data.anchor == nil {
+ return true
+ }
+ c := []byte{'&'}
+ if emitter.anchor_data.alias {
+ c[0] = '*'
+ }
+ if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+ return false
+ }
+ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+ return true
+ }
+ if len(emitter.tag_data.handle) > 0 {
+ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+ return false
+ }
+ if len(emitter.tag_data.suffix) > 0 {
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ }
+ } else {
+ // [Go] Allocate these slices elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+ switch emitter.scalar_data.style {
+ case yaml_PLAIN_SCALAR_STYLE:
+ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_LITERAL_SCALAR_STYLE:
+ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+ case yaml_FOLDED_SCALAR_STYLE:
+ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+ }
+ panic("unknown scalar style")
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+ if version_directive.major != 1 || version_directive.minor != 1 {
+ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+ }
+ return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+ handle := tag_directive.handle
+ prefix := tag_directive.prefix
+ if len(handle) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+ }
+ if handle[0] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+ }
+ if handle[len(handle)-1] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+ }
+ for i := 1; i < len(handle)-1; i += width(handle[i]) {
+ if !is_alpha(handle, i) {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+ }
+ }
+ if len(prefix) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+ }
+ return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+ if len(anchor) == 0 {
+ problem := "anchor value must not be empty"
+ if alias {
+ problem = "alias value must not be empty"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ for i := 0; i < len(anchor); i += width(anchor[i]) {
+ if !is_alpha(anchor, i) {
+ problem := "anchor value must contain alphanumerical characters only"
+ if alias {
+ problem = "alias value must contain alphanumerical characters only"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ }
+ emitter.anchor_data.anchor = anchor
+ emitter.anchor_data.alias = alias
+ return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+ if len(tag) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+ }
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ tag_directive := &emitter.tag_directives[i]
+ if bytes.HasPrefix(tag, tag_directive.prefix) {
+ emitter.tag_data.handle = tag_directive.handle
+ emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+ return true
+ }
+ }
+ emitter.tag_data.suffix = tag
+ return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ var (
+ block_indicators = false
+ flow_indicators = false
+ line_breaks = false
+ special_characters = false
+
+ leading_space = false
+ leading_break = false
+ trailing_space = false
+ trailing_break = false
+ break_space = false
+ space_break = false
+
+ preceded_by_whitespace = false
+ followed_by_whitespace = false
+ previous_space = false
+ previous_break = false
+ )
+
+ emitter.scalar_data.value = value
+
+ if len(value) == 0 {
+ emitter.scalar_data.multiline = false
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = false
+ return true
+ }
+
+ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+ block_indicators = true
+ flow_indicators = true
+ }
+
+ preceded_by_whitespace = true
+ for i, w := 0, 0; i < len(value); i += w {
+ w = width(value[i])
+ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+ if i == 0 {
+ switch value[i] {
+ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+ flow_indicators = true
+ block_indicators = true
+ case '?', ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '-':
+ if followed_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ } else {
+ switch value[i] {
+ case ',', '?', '[', ']', '{', '}':
+ flow_indicators = true
+ case ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '#':
+ if preceded_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ }
+
+ if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+ special_characters = true
+ }
+ if is_space(value, i) {
+ if i == 0 {
+ leading_space = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_space = true
+ }
+ if previous_break {
+ break_space = true
+ }
+ previous_space = true
+ previous_break = false
+ } else if is_break(value, i) {
+ line_breaks = true
+ if i == 0 {
+ leading_break = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_break = true
+ }
+ if previous_space {
+ space_break = true
+ }
+ previous_space = false
+ previous_break = true
+ } else {
+ previous_space = false
+ previous_break = false
+ }
+
+ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+ preceded_by_whitespace = is_blankz(value, i)
+ }
+
+ emitter.scalar_data.multiline = line_breaks
+ emitter.scalar_data.flow_plain_allowed = true
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = true
+
+ if leading_space || leading_break || trailing_space || trailing_break {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if trailing_space {
+ emitter.scalar_data.block_allowed = false
+ }
+ if break_space {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ emitter.scalar_data.block_allowed = false
+ }
+ if line_breaks {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if flow_indicators {
+ emitter.scalar_data.flow_plain_allowed = false
+ }
+ if block_indicators {
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ emitter.anchor_data.anchor = nil
+ emitter.tag_data.handle = nil
+ emitter.tag_data.suffix = nil
+ emitter.scalar_data.value = nil
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+ return false
+ }
+
+ case yaml_SCALAR_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ if !yaml_emitter_analyze_scalar(emitter, event.value) {
+ return false
+ }
+
+ case yaml_SEQUENCE_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+
+ case yaml_MAPPING_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+ if !flush(emitter) {
+ return false
+ }
+ pos := emitter.buffer_pos
+ emitter.buffer[pos+0] = '\xEF'
+ emitter.buffer[pos+1] = '\xBB'
+ emitter.buffer[pos+2] = '\xBF'
+ emitter.buffer_pos += 3
+ return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+ indent := emitter.indent
+ if indent < 0 {
+ indent = 0
+ }
+ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ for emitter.column < indent {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ emitter.whitespace = true
+ emitter.indention = true
+ return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, indicator) {
+ return false
+ }
+ emitter.whitespace = is_whitespace
+ emitter.indention = (emitter.indention && is_indention)
+ emitter.open_ended = false
+ return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ for i := 0; i < len(value); {
+ var must_write bool
+ switch value[i] {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+ must_write = true
+ default:
+ must_write = is_alpha(value, i)
+ }
+ if must_write {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ } else {
+ w := width(value[i])
+ for k := 0; k < w; k++ {
+ octet := value[i]
+ i++
+ if !put(emitter, '%') {
+ return false
+ }
+
+ c := octet >> 4
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+
+ c = octet & 0x0f
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+ }
+ }
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+
+ emitter.whitespace = false
+ emitter.indention = false
+ if emitter.root_context {
+ emitter.open_ended = true
+ }
+
+ return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+ return false
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if value[i] == '\'' {
+ if !put(emitter, '\'') {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ spaces := false
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+ return false
+ }
+
+ for i := 0; i < len(value); {
+ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+ is_bom(value, i) || is_break(value, i) ||
+ value[i] == '"' || value[i] == '\\' {
+
+ octet := value[i]
+
+ var w int
+ var v rune
+ switch {
+ case octet&0x80 == 0x00:
+ w, v = 1, rune(octet&0x7F)
+ case octet&0xE0 == 0xC0:
+ w, v = 2, rune(octet&0x1F)
+ case octet&0xF0 == 0xE0:
+ w, v = 3, rune(octet&0x0F)
+ case octet&0xF8 == 0xF0:
+ w, v = 4, rune(octet&0x07)
+ }
+ for k := 1; k < w; k++ {
+ octet = value[i+k]
+ v = (v << 6) + (rune(octet) & 0x3F)
+ }
+ i += w
+
+ if !put(emitter, '\\') {
+ return false
+ }
+
+ var ok bool
+ switch v {
+ case 0x00:
+ ok = put(emitter, '0')
+ case 0x07:
+ ok = put(emitter, 'a')
+ case 0x08:
+ ok = put(emitter, 'b')
+ case 0x09:
+ ok = put(emitter, 't')
+ case 0x0A:
+ ok = put(emitter, 'n')
+ case 0x0b:
+ ok = put(emitter, 'v')
+ case 0x0c:
+ ok = put(emitter, 'f')
+ case 0x0d:
+ ok = put(emitter, 'r')
+ case 0x1b:
+ ok = put(emitter, 'e')
+ case 0x22:
+ ok = put(emitter, '"')
+ case 0x5c:
+ ok = put(emitter, '\\')
+ case 0x85:
+ ok = put(emitter, 'N')
+ case 0xA0:
+ ok = put(emitter, '_')
+ case 0x2028:
+ ok = put(emitter, 'L')
+ case 0x2029:
+ ok = put(emitter, 'P')
+ default:
+ if v <= 0xFF {
+ ok = put(emitter, 'x')
+ w = 2
+ } else if v <= 0xFFFF {
+ ok = put(emitter, 'u')
+ w = 4
+ } else {
+ ok = put(emitter, 'U')
+ w = 8
+ }
+ for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+ digit := byte((v >> uint(k)) & 0x0F)
+ if digit < 10 {
+ ok = put(emitter, digit+'0')
+ } else {
+ ok = put(emitter, digit+'A'-10)
+ }
+ }
+ }
+ if !ok {
+ return false
+ }
+ spaces = false
+ } else if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if is_space(value, i+1) {
+ if !put(emitter, '\\') {
+ return false
+ }
+ }
+ i += width(value[i])
+ } else if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = true
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+ if is_space(value, 0) || is_break(value, 0) {
+ indent_hint := []byte{'0' + byte(emitter.best_indent)}
+ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+ return false
+ }
+ }
+
+ emitter.open_ended = false
+
+ var chomp_hint [1]byte
+ if len(value) == 0 {
+ chomp_hint[0] = '-'
+ } else {
+ i := len(value) - 1
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if !is_break(value, i) {
+ chomp_hint[0] = '-'
+ } else if i == 0 {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ } else {
+ i--
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if is_break(value, i) {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ }
+ }
+ }
+ if chomp_hint[0] != 0 {
+ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !put_break(emitter) {
+ return false
+ }
+ emitter.indention = true
+ emitter.whitespace = true
+ breaks := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+
+ return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+
+ if !put_break(emitter) {
+ return false
+ }
+ emitter.indention = true
+ emitter.whitespace = true
+
+ breaks := true
+ leading_spaces := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !breaks && !leading_spaces && value[i] == '\n' {
+ k := 0
+ for is_break(value, k) {
+ k += width(value[k])
+ }
+ if !is_blankz(value, k) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ leading_spaces = is_blank(value, i)
+ }
+ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/encode.go b/vendor/gopkg.in/yaml.v2/encode.go
new file mode 100644
index 0000000..0ee738e
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/encode.go
@@ -0,0 +1,390 @@
+package yaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+// jsonNumber is the interface of the encoding/json.Number datatype.
+// Repeating the interface here avoids a dependency on encoding/json, and also
+// supports other libraries like jsoniter, which use a similar datatype with
+// the same interface. Detecting this interface is useful when dealing with
+// structures containing json.Number, which is a string under the hood. The
+// encoder should prefer the use of Int64(), Float64() and string(), in that
+// order, when encoding this type.
+type jsonNumber interface {
+ Float64() (float64, error)
+ Int64() (int64, error)
+ String() string
+}
+
+type encoder struct {
+ emitter yaml_emitter_t
+ event yaml_event_t
+ out []byte
+ flow bool
+ // doneInit holds whether the initial stream_start_event has been
+ // emitted.
+ doneInit bool
+}
+
+func newEncoder() *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_string(&e.emitter, &e.out)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_writer(&e.emitter, w)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func (e *encoder) init() {
+ if e.doneInit {
+ return
+ }
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+ e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
+ e.emitter.open_ended = false
+ yaml_stream_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) destroy() {
+ yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+ // This will internally delete the e.event value.
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+ if !ok {
+ msg := e.emitter.problem
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.emit()
+ e.marshal(tag, in)
+ yaml_document_end_event_initialize(&e.event, true)
+ e.emit()
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+ e.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch m := iface.(type) {
+ case jsonNumber:
+ integer, err := m.Int64()
+ if err == nil {
+ // In this case the json.Number is a valid int64
+ in = reflect.ValueOf(integer)
+ break
+ }
+ float, err := m.Float64()
+ if err == nil {
+ // In this case the json.Number is a valid float64
+ in = reflect.ValueOf(float)
+ break
+ }
+ // fallback case - no number could be obtained
+ in = reflect.ValueOf(m.String())
+ case time.Time, *time.Time:
+ // Although time.Time implements TextMarshaler,
+ // we don't want to treat it as a string for YAML
+ // purposes because YAML has special support for
+ // timestamps.
+ case Marshaler:
+ v, err := m.MarshalYAML()
+ if err != nil {
+ fail(err)
+ }
+ if v == nil {
+ e.nilv()
+ return
+ }
+ in = reflect.ValueOf(v)
+ case encoding.TextMarshaler:
+ text, err := m.MarshalText()
+ if err != nil {
+ fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ e.marshal(tag, in.Elem())
+ case reflect.Map:
+ e.mapv(tag, in)
+ case reflect.Ptr:
+ if in.Type() == ptrTimeType {
+ e.timev(tag, in.Elem())
+ } else {
+ e.marshal(tag, in.Elem())
+ }
+ case reflect.Struct:
+ if in.Type() == timeType {
+ e.timev(tag, in)
+ } else {
+ e.structv(tag, in)
+ }
+ case reflect.Slice, reflect.Array:
+ if in.Type().Elem() == mapItemType {
+ e.itemsv(tag, in)
+ } else {
+ e.slicev(tag, in)
+ }
+ case reflect.String:
+ e.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if in.Type() == durationType {
+ e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
+ } else {
+ e.intv(tag, in)
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ e.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ e.floatv(tag, in)
+ case reflect.Bool:
+ e.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ e.marshal("", k)
+ e.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (e *encoder) itemsv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
+ for _, item := range slice {
+ e.marshal("", reflect.ValueOf(item.Key))
+ e.marshal("", reflect.ValueOf(item.Value))
+ }
+ })
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ e.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = in.FieldByIndex(info.Inline)
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ e.marshal("", reflect.ValueOf(info.Key))
+ e.flow = info.Flow
+ e.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ e.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
+ }
+ e.marshal("", k)
+ e.flow = false
+ e.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := yaml_BLOCK_MAPPING_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+ e.emit()
+ f()
+ yaml_mapping_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ e.emit()
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ e.marshal("", in.Index(i))
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+ var style yaml_scalar_style_t
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == yaml_BINARY_TAG {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = yaml_BINARY_TAG
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when encoded unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ style = yaml_LITERAL_SCALAR_STYLE
+ case canUsePlain:
+ style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ e.emitScalar(s, "", tag, style)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) nilv() {
+ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
+ implicit := tag == ""
+ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+ e.emit()
+}
diff --git a/vendor/gopkg.in/yaml.v2/parserc.go b/vendor/gopkg.in/yaml.v2/parserc.go
new file mode 100644
index 0000000..81d05df
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/parserc.go
@@ -0,0 +1,1095 @@
+package yaml
+
+import (
+ "bytes"
+)
+
+// The parser implements the following grammar:
+//
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document ::= block_node DOCUMENT-END*
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// | properties (block_content | indentless_block_sequence)?
+// | block_content
+// | indentless_block_sequence
+// block_node ::= ALIAS
+// | properties block_content?
+// | block_content
+// flow_node ::= ALIAS
+// | properties flow_content?
+// | flow_content
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content ::= block_collection | flow_collection | SCALAR
+// flow_content ::= flow_collection | SCALAR
+// block_collection ::= block_sequence | block_mapping
+// flow_collection ::= flow_sequence | flow_mapping
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// block_mapping ::= BLOCK-MAPPING_START
+// ((KEY block_node_or_indentless_sequence?)?
+// (VALUE block_node_or_indentless_sequence?)?)*
+// BLOCK-END
+// flow_sequence ::= FLOW-SEQUENCE-START
+// (flow_sequence_entry FLOW-ENTRY)*
+// flow_sequence_entry?
+// FLOW-SEQUENCE-END
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping ::= FLOW-MAPPING-START
+// (flow_mapping_entry FLOW-ENTRY)*
+// flow_mapping_entry?
+// FLOW-MAPPING-END
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+// Peek the next token in the token queue.
+func peek_token(parser *yaml_parser_t) *yaml_token_t {
+ if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
+ return &parser.tokens[parser.tokens_head]
+ }
+ return nil
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func skip_token(parser *yaml_parser_t) {
+ parser.token_available = false
+ parser.tokens_parsed++
+ parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
+ parser.tokens_head++
+}
+
+// Get the next event.
+func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
+ // Erase the event object.
+ *event = yaml_event_t{}
+
+ // No events after the end of the stream or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
+ return true
+ }
+
+ // Generate the next event.
+ return yaml_parser_state_machine(parser, event)
+}
+
+// Set parser error.
+func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+// State dispatcher.
+func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
+ //trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+ switch parser.state {
+ case yaml_PARSE_STREAM_START_STATE:
+ return yaml_parser_parse_stream_start(parser, event)
+
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, true)
+
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, false)
+
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return yaml_parser_parse_document_content(parser, event)
+
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return yaml_parser_parse_document_end(parser, event)
+
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, true, false)
+
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return yaml_parser_parse_node(parser, event, true, true)
+
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, false, false)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_indentless_sequence_entry(parser, event)
+
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, true)
+
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, false)
+
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_block_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, true)
+
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, true)
+
+ default:
+ panic("invalid parser state")
+ }
+}
+
+// Parse the production:
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// ************
+func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_STREAM_START_TOKEN {
+ return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark)
+ }
+ parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ encoding: token.encoding,
+ }
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// *************************
+func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ // Parse extra document end indicators.
+ if !implicit {
+ for token.typ == yaml_DOCUMENT_END_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
+ token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
+ token.typ != yaml_DOCUMENT_START_TOKEN &&
+ token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an implicit document.
+ if !yaml_parser_process_directives(parser, nil, nil) {
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_BLOCK_NODE_STATE
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ } else if token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an explicit document.
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+ start_mark := token.start_mark
+ if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
+ return false
+ }
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_DOCUMENT_START_TOKEN {
+ yaml_parser_set_parser_error(parser,
+ "did not find expected ", token.start_mark)
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
+ end_mark := token.end_mark
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: false,
+ }
+ skip_token(parser)
+
+ } else {
+ // Parse the stream end.
+ parser.state = yaml_PARSE_END_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ }
+
+ return true
+}
+
+// Parse the productions:
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// ***********
+//
+func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
+ token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
+ token.typ == yaml_DOCUMENT_START_TOKEN ||
+ token.typ == yaml_DOCUMENT_END_TOKEN ||
+ token.typ == yaml_STREAM_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ return yaml_parser_process_empty_scalar(parser, event,
+ token.start_mark)
+ }
+ return yaml_parser_parse_node(parser, event, true, false)
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *************
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ implicit := true
+ if token.typ == yaml_DOCUMENT_END_TOKEN {
+ end_mark = token.end_mark
+ skip_token(parser)
+ implicit = false
+ }
+
+ parser.tag_directives = parser.tag_directives[:0]
+
+ parser.state = yaml_PARSE_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ implicit: implicit,
+ }
+ return true
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// *****
+// | properties (block_content | indentless_block_sequence)?
+// ********** *
+// | block_content | indentless_block_sequence
+// *
+// block_node ::= ALIAS
+// *****
+// | properties block_content?
+// ********** *
+// | block_content
+// *
+// flow_node ::= ALIAS
+// *****
+// | properties flow_content?
+// ********** *
+// | flow_content
+// *
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// *************************
+// block_content ::= block_collection | flow_collection | SCALAR
+// ******
+// flow_content ::= flow_collection | SCALAR
+// ******
+func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
+ //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_ALIAS_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ anchor: token.value,
+ }
+ skip_token(parser)
+ return true
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ var tag_token bool
+ var tag_handle, tag_suffix, anchor []byte
+ var tag_mark yaml_mark_t
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ start_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ } else if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ start_mark = token.start_mark
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ var tag []byte
+ if tag_token {
+ if len(tag_handle) == 0 {
+ tag = tag_suffix
+ tag_suffix = nil
+ } else {
+ for i := range parser.tag_directives {
+ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+ tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+ tag = append(tag, tag_suffix...)
+ break
+ }
+ }
+ if len(tag) == 0 {
+ yaml_parser_set_parser_error_context(parser,
+ "while parsing a node", start_mark,
+ "found undefined tag handle", tag_mark)
+ return false
+ }
+ }
+ }
+
+ implicit := len(tag) == 0
+ if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if token.typ == yaml_SCALAR_TOKEN {
+ var plain_implicit, quoted_implicit bool
+ end_mark = token.end_mark
+ if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+ plain_implicit = true
+ } else if len(tag) == 0 {
+ quoted_implicit = true
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ value: token.value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(token.style),
+ }
+ skip_token(parser)
+ return true
+ }
+ if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
+ // [Go] Some of the events below can be merged as they differ only on style.
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
+ }
+ return true
+ }
+ if len(anchor) > 0 || len(tag) > 0 {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ quoted_implicit: false,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+ }
+
+ context := "while parsing a flow node"
+ if block {
+ context = "while parsing a block node"
+ }
+ yaml_parser_set_parser_error_context(parser, context, start_mark,
+ "did not find expected node content", token.start_mark)
+ return false
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// ******************** *********** * *********
+//
+func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ }
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block collection", context_mark,
+ "did not find expected '-' indicator", token.start_mark)
+}
+
+// Parse the productions:
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// *********** *
+func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
+ token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ }
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark?
+ }
+ return true
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+// *******************
+// ((KEY block_node_or_indentless_sequence?)?
+// *** *
+// (VALUE block_node_or_indentless_sequence?)?)*
+//
+// BLOCK-END
+// *********
+//
+func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ } else if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block mapping", context_mark,
+ "did not find expected key", token.start_mark)
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// ((KEY block_node_or_indentless_sequence?)?
+//
+// (VALUE block_node_or_indentless_sequence?)?)*
+// ***** *
+// BLOCK-END
+//
+//
+func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence ::= FLOW-SEQUENCE-START
+// *******************
+// (flow_sequence_entry FLOW-ENTRY)*
+// * **********
+// flow_sequence_entry?
+// *
+// FLOW-SEQUENCE-END
+// *****************
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow sequence", context_mark,
+ "did not find expected ',' or ']'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ implicit: true,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ skip_token(parser)
+ return true
+ } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ skip_token(parser)
+ return true
+}
+
+//
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ mark := token.end_mark
+ skip_token(parser)
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// ***** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be end_mark?
+ }
+ return true
+}
+
+// Parse the productions:
+// flow_mapping ::= FLOW-MAPPING-START
+// ******************
+// (flow_mapping_entry FLOW-ENTRY)*
+// * **********
+// flow_mapping_entry?
+// ******************
+// FLOW-MAPPING-END
+// ****************
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * *** *
+//
+func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow mapping", context_mark,
+ "did not find expected ',' or '}'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ } else {
+ parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * ***** *
+//
+func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if empty {
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Generate an empty scalar event.
+func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: mark,
+ end_mark: mark,
+ value: nil, // Empty
+ implicit: true,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+}
+
+var default_tag_directives = []yaml_tag_directive_t{
+ {[]byte("!"), []byte("!")},
+ {[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func yaml_parser_process_directives(parser *yaml_parser_t,
+ version_directive_ref **yaml_version_directive_t,
+ tag_directives_ref *[]yaml_tag_directive_t) bool {
+
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
+ if version_directive != nil {
+ yaml_parser_set_parser_error(parser,
+ "found duplicate %YAML directive", token.start_mark)
+ return false
+ }
+ if token.major != 1 || token.minor != 1 {
+ yaml_parser_set_parser_error(parser,
+ "found incompatible YAML document", token.start_mark)
+ return false
+ }
+ version_directive = &yaml_version_directive_t{
+ major: token.major,
+ minor: token.minor,
+ }
+ } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ value := yaml_tag_directive_t{
+ handle: token.value,
+ prefix: token.prefix,
+ }
+ if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
+ return false
+ }
+ tag_directives = append(tag_directives, value)
+ }
+
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+
+ for i := range default_tag_directives {
+ if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
+ return false
+ }
+ }
+
+ if version_directive_ref != nil {
+ *version_directive_ref = version_directive
+ }
+ if tag_directives_ref != nil {
+ *tag_directives_ref = tag_directives
+ }
+ return true
+}
+
+// Append a tag directive to the directives stack.
+func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
+ for i := range parser.tag_directives {
+ if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
+ }
+ }
+
+ // [Go] I suspect the copy is unnecessary. This was likely done
+ // because there was no way to track ownership of the data.
+ value_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(value_copy.handle, value.handle)
+ copy(value_copy.prefix, value.prefix)
+ parser.tag_directives = append(parser.tag_directives, value_copy)
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/readerc.go b/vendor/gopkg.in/yaml.v2/readerc.go
new file mode 100644
index 0000000..7c1f5fa
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/readerc.go
@@ -0,0 +1,412 @@
+package yaml
+
+import (
+ "io"
+)
+
+// Set the reader error and return 0.
+func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
+ parser.error = yaml_READER_ERROR
+ parser.problem = problem
+ parser.problem_offset = offset
+ parser.problem_value = value
+ return false
+}
+
+// Byte order marks.
+const (
+ bom_UTF8 = "\xef\xbb\xbf"
+ bom_UTF16LE = "\xff\xfe"
+ bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
+ // Ensure that we had enough bytes in the raw buffer.
+ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+ if !yaml_parser_update_raw_buffer(parser) {
+ return false
+ }
+ }
+
+ // Determine the encoding.
+ buf := parser.raw_buffer
+ pos := parser.raw_buffer_pos
+ avail := len(buf) - pos
+ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+ parser.encoding = yaml_UTF16LE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+ parser.encoding = yaml_UTF16BE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+ parser.encoding = yaml_UTF8_ENCODING
+ parser.raw_buffer_pos += 3
+ parser.offset += 3
+ } else {
+ parser.encoding = yaml_UTF8_ENCODING
+ }
+ return true
+}
+
+// Update the raw buffer.
+func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
+ size_read := 0
+
+ // Return if the raw buffer is full.
+ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+ return true
+ }
+
+ // Return on EOF.
+ if parser.eof {
+ return true
+ }
+
+ // Move the remaining bytes in the raw buffer to the beginning.
+ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+ }
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+ parser.raw_buffer_pos = 0
+
+ // Call the read handler to fill the buffer.
+ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+ if err == io.EOF {
+ parser.eof = true
+ } else if err != nil {
+ return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
+ }
+ return true
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
+ if parser.read_handler == nil {
+ panic("read handler must be set")
+ }
+
+ // [Go] This function was changed to guarantee the requested length size at EOF.
+ // The fact we need to do this is pretty awful, but the description above implies
+ // for that to be the case, and there are tests
+
+ // If the EOF flag is set and the raw buffer is empty, do nothing.
+ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+ // [Go] ACTUALLY! Read the documentation of this function above.
+ // This is just broken. To return true, we need to have the
+ // given length in the buffer. Not doing that means every single
+ // check that calls this function to make sure the buffer has a
+ // given length is Go) panicking; or C) accessing invalid memory.
+ //return true
+ }
+
+ // Return if the buffer contains enough characters.
+ if parser.unread >= length {
+ return true
+ }
+
+ // Determine the input encoding if it is not known yet.
+ if parser.encoding == yaml_ANY_ENCODING {
+ if !yaml_parser_determine_encoding(parser) {
+ return false
+ }
+ }
+
+ // Move the unread characters to the beginning of the buffer.
+ buffer_len := len(parser.buffer)
+ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+ copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+ buffer_len -= parser.buffer_pos
+ parser.buffer_pos = 0
+ } else if parser.buffer_pos == buffer_len {
+ buffer_len = 0
+ parser.buffer_pos = 0
+ }
+
+ // Open the whole buffer for writing, and cut it before returning.
+ parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+ // Fill the buffer until it has enough characters.
+ first := true
+ for parser.unread < length {
+
+ // Fill the raw buffer if necessary.
+ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+ if !yaml_parser_update_raw_buffer(parser) {
+ parser.buffer = parser.buffer[:buffer_len]
+ return false
+ }
+ }
+ first = false
+
+ // Decode the raw buffer.
+ inner:
+ for parser.raw_buffer_pos != len(parser.raw_buffer) {
+ var value rune
+ var width int
+
+ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+ // Decode the next character.
+ switch parser.encoding {
+ case yaml_UTF8_ENCODING:
+ // Decode a UTF-8 character. Check RFC 3629
+ // (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+ //
+ // The following table (taken from the RFC) is used for
+ // decoding.
+ //
+ // Char. number range | UTF-8 octet sequence
+ // (hexadecimal) | (binary)
+ // --------------------+------------------------------------
+ // 0000 0000-0000 007F | 0xxxxxxx
+ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ //
+ // Additionally, the characters in the range 0xD800-0xDFFF
+ // are prohibited as they are reserved for use with UTF-16
+ // surrogate pairs.
+
+ // Determine the length of the UTF-8 sequence.
+ octet := parser.raw_buffer[parser.raw_buffer_pos]
+ switch {
+ case octet&0x80 == 0x00:
+ width = 1
+ case octet&0xE0 == 0xC0:
+ width = 2
+ case octet&0xF0 == 0xE0:
+ width = 3
+ case octet&0xF8 == 0xF0:
+ width = 4
+ default:
+ // The leading octet is invalid.
+ return yaml_parser_set_reader_error(parser,
+ "invalid leading UTF-8 octet",
+ parser.offset, int(octet))
+ }
+
+ // Check if the raw buffer contains an incomplete character.
+ if width > raw_unread {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-8 octet sequence",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Decode the leading octet.
+ switch {
+ case octet&0x80 == 0x00:
+ value = rune(octet & 0x7F)
+ case octet&0xE0 == 0xC0:
+ value = rune(octet & 0x1F)
+ case octet&0xF0 == 0xE0:
+ value = rune(octet & 0x0F)
+ case octet&0xF8 == 0xF0:
+ value = rune(octet & 0x07)
+ default:
+ value = 0
+ }
+
+ // Check and decode the trailing octets.
+ for k := 1; k < width; k++ {
+ octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+ // Check if the octet is valid.
+ if (octet & 0xC0) != 0x80 {
+ return yaml_parser_set_reader_error(parser,
+ "invalid trailing UTF-8 octet",
+ parser.offset+k, int(octet))
+ }
+
+ // Decode the octet.
+ value = (value << 6) + rune(octet&0x3F)
+ }
+
+ // Check the length of the sequence against the value.
+ switch {
+ case width == 1:
+ case width == 2 && value >= 0x80:
+ case width == 3 && value >= 0x800:
+ case width == 4 && value >= 0x10000:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "invalid length of a UTF-8 sequence",
+ parser.offset, -1)
+ }
+
+ // Check the range of the value.
+ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+ return yaml_parser_set_reader_error(parser,
+ "invalid Unicode character",
+ parser.offset, int(value))
+ }
+
+ case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
+ var low, high int
+ if parser.encoding == yaml_UTF16LE_ENCODING {
+ low, high = 0, 1
+ } else {
+ low, high = 1, 0
+ }
+
+ // The UTF-16 encoding is not as simple as one might
+ // naively think. Check RFC 2781
+ // (http://www.ietf.org/rfc/rfc2781.txt).
+ //
+ // Normally, two subsequent bytes describe a Unicode
+ // character. However a special technique (called a
+ // surrogate pair) is used for specifying character
+ // values larger than 0xFFFF.
+ //
+ // A surrogate pair consists of two pseudo-characters:
+ // high surrogate area (0xD800-0xDBFF)
+ // low surrogate area (0xDC00-0xDFFF)
+ //
+ // The following formulas are used for decoding
+ // and encoding characters using surrogate pairs:
+ //
+ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
+ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
+ // W1 = 110110yyyyyyyyyy
+ // W2 = 110111xxxxxxxxxx
+ //
+ // where U is the character value, W1 is the high surrogate
+ // area, W2 is the low surrogate area.
+
+ // Check for incomplete UTF-16 character.
+ if raw_unread < 2 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 character",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the character.
+ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+ // Check for unexpected low surrogate area.
+ if value&0xFC00 == 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "unexpected low surrogate area",
+ parser.offset, int(value))
+ }
+
+ // Check for a high surrogate area.
+ if value&0xFC00 == 0xD800 {
+ width = 4
+
+ // Check for incomplete surrogate pair.
+ if raw_unread < 4 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 surrogate pair",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the next character.
+ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+ // Check for a low surrogate area.
+ if value2&0xFC00 != 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "expected low surrogate area",
+ parser.offset+2, int(value2))
+ }
+
+ // Generate the value of the surrogate pair.
+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+ } else {
+ width = 2
+ }
+
+ default:
+ panic("impossible")
+ }
+
+ // Check if the character is in the allowed range:
+ // #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
+ // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
+ // | [#x10000-#x10FFFF] (32 bit)
+ switch {
+ case value == 0x09:
+ case value == 0x0A:
+ case value == 0x0D:
+ case value >= 0x20 && value <= 0x7E:
+ case value == 0x85:
+ case value >= 0xA0 && value <= 0xD7FF:
+ case value >= 0xE000 && value <= 0xFFFD:
+ case value >= 0x10000 && value <= 0x10FFFF:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "control characters are not allowed",
+ parser.offset, int(value))
+ }
+
+ // Move the raw pointers.
+ parser.raw_buffer_pos += width
+ parser.offset += width
+
+ // Finally put the character into the buffer.
+ if value <= 0x7F {
+ // 0000 0000-0000 007F . 0xxxxxxx
+ parser.buffer[buffer_len+0] = byte(value)
+ buffer_len += 1
+ } else if value <= 0x7FF {
+ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+ buffer_len += 2
+ } else if value <= 0xFFFF {
+ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+ buffer_len += 3
+ } else {
+ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+ buffer_len += 4
+ }
+
+ parser.unread++
+ }
+
+ // On EOF, put NUL into the buffer and return.
+ if parser.eof {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ parser.unread++
+ break
+ }
+ }
+ // [Go] Read the documentation of this function above. To return true,
+ // we need to have the given length in the buffer. Not doing that means
+ // every single check that calls this function to make sure the buffer
+ // has a given length is Go) panicking; or C) accessing invalid memory.
+ // This happens here due to the EOF above breaking early.
+ for buffer_len < length {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ }
+ parser.buffer = parser.buffer[:buffer_len]
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/resolve.go b/vendor/gopkg.in/yaml.v2/resolve.go
new file mode 100644
index 0000000..4120e0c
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/resolve.go
@@ -0,0 +1,258 @@
+package yaml
+
+import (
+ "encoding/base64"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type resolveMapItem struct {
+ value interface{}
+ tag string
+}
+
+var resolveTable = make([]byte, 256)
+var resolveMap = make(map[string]resolveMapItem)
+
+func init() {
+ t := resolveTable
+ t[int('+')] = 'S' // Sign
+ t[int('-')] = 'S'
+ for _, c := range "0123456789" {
+ t[int(c)] = 'D' // Digit
+ }
+ for _, c := range "yYnNtTfFoO~" {
+ t[int(c)] = 'M' // In map
+ }
+ t[int('.')] = '.' // Float (potentially in map)
+
+ var resolveMapList = []struct {
+ v interface{}
+ tag string
+ l []string
+ }{
+ {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
+ {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
+ {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
+ {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
+ {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
+ {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
+ {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
+ {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
+ {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
+ {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
+ {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
+ {"<<", yaml_MERGE_TAG, []string{"<<"}},
+ }
+
+ m := resolveMap
+ for _, item := range resolveMapList {
+ for _, s := range item.l {
+ m[s] = resolveMapItem{item.v, item.tag}
+ }
+ }
+}
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+func shortTag(tag string) string {
+ // TODO This can easily be made faster and produce less garbage.
+ if strings.HasPrefix(tag, longTagPrefix) {
+ return "!!" + tag[len(longTagPrefix):]
+ }
+ return tag
+}
+
+func longTag(tag string) string {
+ if strings.HasPrefix(tag, "!!") {
+ return longTagPrefix + tag[2:]
+ }
+ return tag
+}
+
+func resolvableTag(tag string) bool {
+ switch tag {
+ case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
+ return true
+ }
+ return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out interface{}) {
+ if !resolvableTag(tag) {
+ return tag, in
+ }
+
+ defer func() {
+ switch tag {
+ case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
+ return
+ case yaml_FLOAT_TAG:
+ if rtag == yaml_INT_TAG {
+ switch v := out.(type) {
+ case int64:
+ rtag = yaml_FLOAT_TAG
+ out = float64(v)
+ return
+ case int:
+ rtag = yaml_FLOAT_TAG
+ out = float64(v)
+ return
+ }
+ }
+ }
+ failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+ }()
+
+ // Any data is accepted as a !!str or !!binary.
+ // Otherwise, the prefix is enough of a hint about what it might be.
+ hint := byte('N')
+ if in != "" {
+ hint = resolveTable[in[0]]
+ }
+ if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
+ // Handle things we can lookup in a map.
+ if item, ok := resolveMap[in]; ok {
+ return item.tag, item.value
+ }
+
+ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+ // are purposefully unsupported here. They're still quoted on
+ // the way out for compatibility with other parser, though.
+
+ switch hint {
+ case 'M':
+ // We've already checked the map above.
+
+ case '.':
+ // Not in the map, so maybe a normal float.
+ floatv, err := strconv.ParseFloat(in, 64)
+ if err == nil {
+ return yaml_FLOAT_TAG, floatv
+ }
+
+ case 'D', 'S':
+ // Int, float, or timestamp.
+ // Only try values as a timestamp if the value is unquoted or there's an explicit
+ // !!timestamp tag.
+ if tag == "" || tag == yaml_TIMESTAMP_TAG {
+ t, ok := parseTimestamp(in)
+ if ok {
+ return yaml_TIMESTAMP_TAG, t
+ }
+ }
+
+ plain := strings.Replace(in, "_", "", -1)
+ intv, err := strconv.ParseInt(plain, 0, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
+ } else {
+ return yaml_INT_TAG, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain, 0, 64)
+ if err == nil {
+ return yaml_INT_TAG, uintv
+ }
+ if yamlStyleFloat.MatchString(plain) {
+ floatv, err := strconv.ParseFloat(plain, 64)
+ if err == nil {
+ return yaml_FLOAT_TAG, floatv
+ }
+ }
+ if strings.HasPrefix(plain, "0b") {
+ intv, err := strconv.ParseInt(plain[2:], 2, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
+ } else {
+ return yaml_INT_TAG, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 2, 64)
+ if err == nil {
+ return yaml_INT_TAG, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0b") {
+ intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
+ } else {
+ return yaml_INT_TAG, intv
+ }
+ }
+ }
+ default:
+ panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
+ }
+ }
+ return yaml_STR_TAG, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+ const lineLen = 70
+ encLen := base64.StdEncoding.EncodedLen(len(s))
+ lines := encLen/lineLen + 1
+ buf := make([]byte, encLen*2+lines)
+ in := buf[0:encLen]
+ out := buf[encLen:]
+ base64.StdEncoding.Encode(in, []byte(s))
+ k := 0
+ for i := 0; i < len(in); i += lineLen {
+ j := i + lineLen
+ if j > len(in) {
+ j = len(in)
+ }
+ k += copy(out[k:], in[i:j])
+ if lines > 1 {
+ out[k] = '\n'
+ k++
+ }
+ }
+ return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+ "2006-1-2 15:4:5.999999999", // space separated with no time zone
+ "2006-1-2", // date only
+ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+ // from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+ // TODO write code to check all the formats supported by
+ // http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+ // Quick check: all date formats start with YYYY-.
+ i := 0
+ for ; i < len(s); i++ {
+ if c := s[i]; c < '0' || c > '9' {
+ break
+ }
+ }
+ if i != 4 || i == len(s) || s[i] != '-' {
+ return time.Time{}, false
+ }
+ for _, format := range allowedTimestampFormats {
+ if t, err := time.Parse(format, s); err == nil {
+ return t, true
+ }
+ }
+ return time.Time{}, false
+}
diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v2/scannerc.go
new file mode 100644
index 0000000..0b9bb60
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/scannerc.go
@@ -0,0 +1,2711 @@
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward. The issues are "block collection start" and
+// "simple keys". Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented. We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+// STREAM-START(encoding) # The stream start.
+// STREAM-END # The stream end.
+// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
+// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
+// DOCUMENT-START # '---'
+// DOCUMENT-END # '...'
+// BLOCK-SEQUENCE-START # Indentation increase denoting a block
+// BLOCK-MAPPING-START # sequence or a block mapping.
+// BLOCK-END # Indentation decrease.
+// FLOW-SEQUENCE-START # '['
+// FLOW-SEQUENCE-END # ']'
+// BLOCK-SEQUENCE-START # '{'
+// BLOCK-SEQUENCE-END # '}'
+// BLOCK-ENTRY # '-'
+// FLOW-ENTRY # ','
+// KEY # '?' or nothing (simple keys).
+// VALUE # ':'
+// ALIAS(anchor) # '*anchor'
+// ANCHOR(anchor) # '&anchor'
+// TAG(handle,suffix) # '!handle!suffix'
+// SCALAR(value,style) # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+// STREAM-START(encoding)
+// STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+// VERSION-DIRECTIVE(major,minor)
+// TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+// %YAML 1.1
+// %TAG ! !foo
+// %TAG !yaml! tag:yaml.org,2002:
+// ---
+//
+// The correspoding sequence of tokens:
+//
+// STREAM-START(utf-8)
+// VERSION-DIRECTIVE(1,1)
+// TAG-DIRECTIVE("!","!foo")
+// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+// DOCUMENT-START
+// STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+// DOCUMENT-START
+// DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+// 1. An implicit document:
+//
+// 'a scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// STREAM-END
+//
+// 2. An explicit document:
+//
+// ---
+// 'a scalar'
+// ...
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-END
+// STREAM-END
+//
+// 3. Several documents in a stream:
+//
+// 'a scalar'
+// ---
+// 'another scalar'
+// ---
+// 'yet another scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("another scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("yet another scalar",single-quoted)
+// STREAM-END
+//
+// We have already introduced the SCALAR token above. The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+// ALIAS(anchor)
+// ANCHOR(anchor)
+// TAG(handle,suffix)
+// SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+// 1. A recursive sequence:
+//
+// &A [ *A ]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// ANCHOR("A")
+// FLOW-SEQUENCE-START
+// ALIAS("A")
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A tagged scalar:
+//
+// !!float "3.14" # A good approximation.
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// TAG("!!","float")
+// SCALAR("3.14",double-quoted)
+// STREAM-END
+//
+// 3. Various scalar styles:
+//
+// --- # Implicit empty plain scalars do not produce tokens.
+// --- a plain scalar
+// --- 'a single-quoted scalar'
+// --- "a double-quoted scalar"
+// --- |-
+// a literal scalar
+// --- >-
+// a folded
+// scalar
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// DOCUMENT-START
+// SCALAR("a plain scalar",plain)
+// DOCUMENT-START
+// SCALAR("a single-quoted scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("a double-quoted scalar",double-quoted)
+// DOCUMENT-START
+// SCALAR("a literal scalar",literal)
+// DOCUMENT-START
+// SCALAR("a folded scalar",folded)
+// STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+// FLOW-SEQUENCE-START
+// FLOW-SEQUENCE-END
+// FLOW-MAPPING-START
+// FLOW-MAPPING-END
+// FLOW-ENTRY
+// KEY
+// VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+// 1. A flow sequence:
+//
+// [item 1, item 2, item 3]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-SEQUENCE-START
+// SCALAR("item 1",plain)
+// FLOW-ENTRY
+// SCALAR("item 2",plain)
+// FLOW-ENTRY
+// SCALAR("item 3",plain)
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A flow mapping:
+//
+// {
+// a simple key: a value, # Note that the KEY token is produced.
+// ? a complex key: another value,
+// }
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// FLOW-ENTRY
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// FLOW-ENTRY
+// FLOW-MAPPING-END
+// STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator. Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+// BLOCK-SEQUENCE-START
+// BLOCK-MAPPING-START
+// BLOCK-END
+// BLOCK-ENTRY
+// KEY
+// VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python). However YAML has some syntax pecularities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+// 1. Block sequences:
+//
+// - item 1
+// - item 2
+// -
+// - item 3.1
+// - item 3.2
+// -
+// key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 3.1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 3.2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Block mappings:
+//
+// a simple key: a value # The KEY token is produced here.
+// ? a complex key
+// : another value
+// a mapping:
+// key 1: value 1
+// key 2: value 2
+// a sequence:
+// - item 1
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// KEY
+// SCALAR("a mapping",plain)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line. If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line. The following examples
+// illustrate this case:
+//
+// 1. Collections in a sequence:
+//
+// - - item 1
+// - item 2
+// - key 1: value 1
+// key 2: value 2
+// - ? complex key
+// : complex value
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("complex key")
+// VALUE
+// SCALAR("complex value")
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Collections in a mapping:
+//
+// ? a sequence
+// : - item 1
+// - item 2
+// ? a mapping
+// : key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a mapping",plain)
+// VALUE
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+// key:
+// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key",plain)
+// VALUE
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+//
+
+// Ensure that the buffer contains the required number of characters.
+// Return true on success, false on failure (reader error or memory error).
+func cache(parser *yaml_parser_t, length int) bool {
+ // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
+ return parser.unread >= length || yaml_parser_update_buffer(parser, length)
+}
+
+// Advance the buffer pointer.
+func skip(parser *yaml_parser_t) {
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func skip_line(parser *yaml_parser_t) {
+ if is_crlf(parser.buffer, parser.buffer_pos) {
+ parser.mark.index += 2
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread -= 2
+ parser.buffer_pos += 2
+ } else if is_break(parser.buffer, parser.buffer_pos) {
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+ }
+}
+
+// Copy a character to a string buffer and advance pointers.
+func read(parser *yaml_parser_t, s []byte) []byte {
+ w := width(parser.buffer[parser.buffer_pos])
+ if w == 0 {
+ panic("invalid character sequence")
+ }
+ if len(s) == 0 {
+ s = make([]byte, 0, 32)
+ }
+ if w == 1 && len(s)+w <= cap(s) {
+ s = s[:len(s)+1]
+ s[len(s)-1] = parser.buffer[parser.buffer_pos]
+ parser.buffer_pos++
+ } else {
+ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+ parser.buffer_pos += w
+ }
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func read_line(parser *yaml_parser_t, s []byte) []byte {
+ buf := parser.buffer
+ pos := parser.buffer_pos
+ switch {
+ case buf[pos] == '\r' && buf[pos+1] == '\n':
+ // CR LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ parser.mark.index++
+ parser.unread--
+ case buf[pos] == '\r' || buf[pos] == '\n':
+ // CR|LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 1
+ case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+ // NEL . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+ // LS|PS . LS|PS
+ s = append(s, buf[parser.buffer_pos:pos+3]...)
+ parser.buffer_pos += 3
+ default:
+ return s
+ }
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ return s
+}
+
+// Get the next token.
+func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Erase the token object.
+ *token = yaml_token_t{} // [Go] Is this necessary?
+
+ // No tokens after STREAM-END or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
+ return true
+ }
+
+ // Ensure that the tokens queue contains enough tokens.
+ if !parser.token_available {
+ if !yaml_parser_fetch_more_tokens(parser) {
+ return false
+ }
+ }
+
+ // Fetch the next token from the queue.
+ *token = parser.tokens[parser.tokens_head]
+ parser.tokens_head++
+ parser.tokens_parsed++
+ parser.token_available = false
+
+ if token.typ == yaml_STREAM_END_TOKEN {
+ parser.stream_end_produced = true
+ }
+ return true
+}
+
+// Set the scanner error and return false.
+func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
+ parser.error = yaml_SCANNER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = parser.mark
+ return false
+}
+
+func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
+ context := "while parsing a tag"
+ if directive {
+ context = "while parsing a %TAG directive"
+ }
+ return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
+}
+
+func trace(args ...interface{}) func() {
+ pargs := append([]interface{}{"+++"}, args...)
+ fmt.Println(pargs...)
+ pargs = append([]interface{}{"---"}, args...)
+ return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
+ // While we need more tokens to fetch, do it.
+ for {
+ if parser.tokens_head != len(parser.tokens) {
+ // If queue is non-empty, check if any potential simple key may
+ // occupy the head position.
+ head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
+ if !ok {
+ break
+ } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
+ return false
+ } else if !valid {
+ break
+ }
+ }
+ // Fetch the next token.
+ if !yaml_parser_fetch_next_token(parser) {
+ return false
+ }
+ }
+
+ parser.token_available = true
+ return true
+}
+
+// The dispatcher for token fetchers.
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
+ // Ensure that the buffer is initialized.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we just started scanning. Fetch STREAM-START then.
+ if !parser.stream_start_produced {
+ return yaml_parser_fetch_stream_start(parser)
+ }
+
+ // Eat whitespaces and comments until we reach the next token.
+ if !yaml_parser_scan_to_next_token(parser) {
+ return false
+ }
+
+ // Check the indentation level against the current column.
+ if !yaml_parser_unroll_indent(parser, parser.mark.column) {
+ return false
+ }
+
+ // Ensure that the buffer contains at least 4 characters. 4 is the length
+ // of the longest indicators ('--- ' and '... ').
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ // Is it the end of the stream?
+ if is_z(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_fetch_stream_end(parser)
+ }
+
+ // Is it a directive?
+ if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+ return yaml_parser_fetch_directive(parser)
+ }
+
+ buf := parser.buffer
+ pos := parser.buffer_pos
+
+ // Is it the document start indicator?
+ if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
+ }
+
+ // Is it the document end indicator?
+ if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
+ }
+
+ // Is it the flow sequence start indicator?
+ if buf[pos] == '[' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
+ }
+
+ // Is it the flow mapping start indicator?
+ if parser.buffer[parser.buffer_pos] == '{' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
+ }
+
+ // Is it the flow sequence end indicator?
+ if parser.buffer[parser.buffer_pos] == ']' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_SEQUENCE_END_TOKEN)
+ }
+
+ // Is it the flow mapping end indicator?
+ if parser.buffer[parser.buffer_pos] == '}' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_MAPPING_END_TOKEN)
+ }
+
+ // Is it the flow entry indicator?
+ if parser.buffer[parser.buffer_pos] == ',' {
+ return yaml_parser_fetch_flow_entry(parser)
+ }
+
+ // Is it the block entry indicator?
+ if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
+ return yaml_parser_fetch_block_entry(parser)
+ }
+
+ // Is it the key indicator?
+ if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_key(parser)
+ }
+
+ // Is it the value indicator?
+ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_value(parser)
+ }
+
+ // Is it an alias?
+ if parser.buffer[parser.buffer_pos] == '*' {
+ return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
+ }
+
+ // Is it an anchor?
+ if parser.buffer[parser.buffer_pos] == '&' {
+ return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
+ }
+
+ // Is it a tag?
+ if parser.buffer[parser.buffer_pos] == '!' {
+ return yaml_parser_fetch_tag(parser)
+ }
+
+ // Is it a literal scalar?
+ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, true)
+ }
+
+ // Is it a folded scalar?
+ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, false)
+ }
+
+ // Is it a single-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ return yaml_parser_fetch_flow_scalar(parser, true)
+ }
+
+ // Is it a double-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '"' {
+ return yaml_parser_fetch_flow_scalar(parser, false)
+ }
+
+ // Is it a plain scalar?
+ //
+ // A plain scalar may start with any non-blank characters except
+ //
+ // '-', '?', ':', ',', '[', ']', '{', '}',
+ // '#', '&', '*', '!', '|', '>', '\'', '\"',
+ // '%', '@', '`'.
+ //
+ // In the block context (and, for the '-' indicator, in the flow context
+ // too), it may also start with the characters
+ //
+ // '-', '?', ':'
+ //
+ // if it is followed by a non-space character.
+ //
+ // The last rule is more restrictive than the specification requires.
+ // [Go] Make this logic more reasonable.
+ //switch parser.buffer[parser.buffer_pos] {
+ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+ //}
+ if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+ (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level == 0 &&
+ (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+ !is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_plain_scalar(parser)
+ }
+
+ // If we don't determine the token type so far, it is an error.
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning for the next token", parser.mark,
+ "found character that cannot start any token")
+}
+
+func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
+ if !simple_key.possible {
+ return false, true
+ }
+
+ // The 1.2 specification says:
+ //
+ // "If the ? indicator is omitted, parsing needs to see past the
+ // implicit key to recognize it as such. To limit the amount of
+ // lookahead required, the “:” indicator must appear at most 1024
+ // Unicode characters beyond the start of the key. In addition, the key
+ // is restricted to a single line."
+ //
+ if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
+ // Check if the potential simple key to be removed is required.
+ if simple_key.required {
+ return false, yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", simple_key.mark,
+ "could not find expected ':'")
+ }
+ simple_key.possible = false
+ return false, true
+ }
+ return true, true
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
+ // A simple key is required at the current position if the scanner is in
+ // the block context and the current column coincides with the indentation
+ // level.
+
+ required := parser.flow_level == 0 && parser.indent == parser.mark.column
+
+ //
+ // If the current position may start a simple key, save it.
+ //
+ if parser.simple_key_allowed {
+ simple_key := yaml_simple_key_t{
+ possible: true,
+ required: required,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ }
+
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+ parser.simple_keys[len(parser.simple_keys)-1] = simple_key
+ parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
+ }
+ return true
+}
+
+// Remove a potential simple key at the current flow level.
+func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
+ i := len(parser.simple_keys) - 1
+ if parser.simple_keys[i].possible {
+ // If the key is required, it is an error.
+ if parser.simple_keys[i].required {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", parser.simple_keys[i].mark,
+ "could not find expected ':'")
+ }
+ // Remove the key from the stack.
+ parser.simple_keys[i].possible = false
+ delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
+ }
+ return true
+}
+
+// max_flow_level limits the flow_level
+const max_flow_level = 10000
+
+// Increase the flow level and resize the simple key list if needed.
+func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
+ // Reset the simple key on the next level.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
+ possible: false,
+ required: false,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ })
+
+ // Increase the flow level.
+ parser.flow_level++
+ if parser.flow_level > max_flow_level {
+ return yaml_parser_set_scanner_error(parser,
+ "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+ fmt.Sprintf("exceeded max depth of %d", max_flow_level))
+ }
+ return true
+}
+
+// Decrease the flow level.
+func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
+ if parser.flow_level > 0 {
+ parser.flow_level--
+ last := len(parser.simple_keys) - 1
+ delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
+ parser.simple_keys = parser.simple_keys[:last]
+ }
+ return true
+}
+
+// max_indents limits the indents stack size
+const max_indents = 10000
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level. In this case,
+// append or insert the specified token into the token queue.
+func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ if parser.indent < column {
+ // Push the current indentation level to the stack and set the new
+ // indentation level.
+ parser.indents = append(parser.indents, parser.indent)
+ parser.indent = column
+ if len(parser.indents) > max_indents {
+ return yaml_parser_set_scanner_error(parser,
+ "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+ fmt.Sprintf("exceeded max depth of %d", max_indents))
+ }
+
+ // Create a token and insert it into the queue.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: mark,
+ end_mark: mark,
+ }
+ if number > -1 {
+ number -= parser.tokens_parsed
+ }
+ yaml_insert_token(parser, number, &token)
+ }
+ return true
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column. For each indentation level, append
+// the BLOCK-END token.
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ // Loop through the indentation levels in the stack.
+ for parser.indent > column {
+ // Create a token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_END_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+
+ // Pop the indentation level.
+ parser.indent = parser.indents[len(parser.indents)-1]
+ parser.indents = parser.indents[:len(parser.indents)-1]
+ }
+ return true
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
+
+ // Set the initial indentation.
+ parser.indent = -1
+
+ // Initialize the simple key stack.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+ parser.simple_keys_by_tok = make(map[int]int)
+
+ // A simple key is allowed at the beginning of the stream.
+ parser.simple_key_allowed = true
+
+ // We have started.
+ parser.stream_start_produced = true
+
+ // Create the STREAM-START token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_START_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ encoding: parser.encoding,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
+
+ // Force new line.
+ if parser.mark.column != 0 {
+ parser.mark.column = 0
+ parser.mark.line++
+ }
+
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the STREAM-END token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_END_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+ token := yaml_token_t{}
+ if !yaml_parser_scan_directive(parser, &token) {
+ return false
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+ start_mark := parser.mark
+
+ skip(parser)
+ skip(parser)
+ skip(parser)
+
+ end_mark := parser.mark
+
+ // Create the DOCUMENT-START or DOCUMENT-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // The indicators '[' and '{' may start a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // Increase the flow level.
+ if !yaml_parser_increase_flow_level(parser) {
+ return false
+ }
+
+ // A simple key may follow the indicators '[' and '{'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset any potential simple key on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Decrease the flow level.
+ if !yaml_parser_decrease_flow_level(parser) {
+ return false
+ }
+
+ // No simple keys after the indicators ']' and '}'.
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-ENTRY token.
+func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after ','.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_FLOW_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the BLOCK-ENTRY token.
+func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
+ // Check if the scanner is in the block context.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new entry.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "block sequence entries are not allowed in this context")
+ }
+ // Add the BLOCK-SEQUENCE-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
+ return false
+ }
+ } else {
+ // It is an error for the '-' indicator to occur in the flow context,
+ // but we let the Parser detect and report about it because the Parser
+ // is able to point to the context.
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '-'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the BLOCK-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the KEY token.
+func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
+
+ // In the block context, additional checks are required.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new key (not nessesary simple).
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping keys are not allowed in this context")
+ }
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '?' in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the KEY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the VALUE token.
+func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
+
+ simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
+
+ // Have we found a simple key?
+ if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
+ return false
+
+ } else if valid {
+
+ // Create the KEY token and insert it into the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: simple_key.mark,
+ end_mark: simple_key.mark,
+ }
+ yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
+
+ // In the block context, we may need to add the BLOCK-MAPPING-START token.
+ if !yaml_parser_roll_indent(parser, simple_key.mark.column,
+ simple_key.token_number,
+ yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
+ return false
+ }
+
+ // Remove the simple key.
+ simple_key.possible = false
+ delete(parser.simple_keys_by_tok, simple_key.token_number)
+
+ // A simple key cannot follow another simple key.
+ parser.simple_key_allowed = false
+
+ } else {
+ // The ':' indicator follows a complex key.
+
+ // In the block context, extra checks are required.
+ if parser.flow_level == 0 {
+
+ // Check if we are allowed to start a complex value.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping values are not allowed in this context")
+ }
+
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Simple keys after ':' are allowed in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+ }
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the VALUE token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_VALUE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the ALIAS or ANCHOR token.
+func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // An anchor or an alias could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow an anchor or an alias.
+ parser.simple_key_allowed = false
+
+ // Create the ALIAS or ANCHOR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_anchor(parser, &token, typ) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the TAG token.
+func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
+ // A tag could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a tag.
+ parser.simple_key_allowed = false
+
+ // Create the TAG token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_tag(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
+ // Remove any potential simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // A simple key may follow a block scalar.
+ parser.simple_key_allowed = true
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_block_scalar(parser, &token, literal) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_flow_scalar(parser, &token, single) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,plain) token.
+func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_plain_scalar(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Eat whitespaces and comments until the next token is found.
+func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+
+ // Until the next token is not found.
+ for {
+ // Allow the BOM mark to start a line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ }
+
+ // Eat whitespaces.
+ // Tabs are allowed:
+ // - in the flow context
+ // - in the block context, but not at the beginning of the line or
+ // after '-', '?', or ':' (complex value).
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Eat a comment until a line break.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // If it is a line break, eat it.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+
+ // In the block context, a new line may start a simple key.
+ if parser.flow_level == 0 {
+ parser.simple_key_allowed = true
+ }
+ } else {
+ break // We have found a token.
+ }
+ }
+
+ return true
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Eat '%'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the directive name.
+ var name []byte
+ if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
+ return false
+ }
+
+ // Is it a YAML directive?
+ if bytes.Equal(name, []byte("YAML")) {
+ // Scan the VERSION directive value.
+ var major, minor int8
+ if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a VERSION-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_VERSION_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ major: major,
+ minor: minor,
+ }
+
+ // Is it a TAG directive?
+ } else if bytes.Equal(name, []byte("TAG")) {
+ // Scan the TAG directive value.
+ var handle, prefix []byte
+ if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a TAG-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ prefix: prefix,
+ }
+
+ // Unknown directive.
+ } else {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unknown directive name")
+ return false
+ }
+
+ // Eat the rest of the line including any comments.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ if parser.buffer[parser.buffer_pos] == '#' {
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ return true
+}
+
+// Scan the directive name.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^
+//
+func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
+ // Consume the directive name.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ var s []byte
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the name is empty.
+ if len(s) == 0 {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "could not find expected directive name")
+ return false
+ }
+
+ // Check for an blank character after the name.
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unexpected non-alphabetical character")
+ return false
+ }
+ *name = s
+ return true
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^
+func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the major version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
+ return false
+ }
+
+ // Eat '.'.
+ if parser.buffer[parser.buffer_pos] != '.' {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected digit or '.' character")
+ }
+
+ skip(parser)
+
+ // Consume the minor version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
+ return false
+ }
+ return true
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^
+// %YAML 1.1 # a comment \n
+// ^
+func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
+
+ // Repeat while the next character is digit.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var value, length int8
+ for is_digit(parser.buffer, parser.buffer_pos) {
+ // Check if the number is too long.
+ length++
+ if length > max_number_length {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "found extremely long version number")
+ }
+ value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the number was present.
+ if length == 0 {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected version number")
+ }
+ *number = value
+ return true
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
+ var handle_value, prefix_value []byte
+
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
+ return false
+ }
+
+ // Expect a whitespace.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace")
+ return false
+ }
+
+ // Eat whitespaces.
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a prefix.
+ if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
+ return false
+ }
+
+ // Expect a whitespace or line break.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ *handle = handle_value
+ *prefix = prefix_value
+ return true
+}
+
+func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
+ var s []byte
+
+ // Eat the indicator character.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the value.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ end_mark := parser.mark
+
+ /*
+ * Check if length of the anchor is greater than 0 and it is followed by
+ * a whitespace character or one of the indicators:
+ *
+ * '?', ':', ',', ']', '}', '%', '@', '`'.
+ */
+
+ if len(s) == 0 ||
+ !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '`') {
+ context := "while scanning an alias"
+ if typ == yaml_ANCHOR_TOKEN {
+ context = "while scanning an anchor"
+ }
+ yaml_parser_set_scanner_error(parser, context, start_mark,
+ "did not find expected alphabetic or numeric character")
+ return false
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ }
+
+ return true
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
+ var handle, suffix []byte
+
+ start_mark := parser.mark
+
+ // Check if the tag is in the canonical form.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ if parser.buffer[parser.buffer_pos+1] == '<' {
+ // Keep the handle as ''
+
+ // Eat '!<'
+ skip(parser)
+ skip(parser)
+
+ // Consume the tag value.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+
+ // Check for '>' and eat it.
+ if parser.buffer[parser.buffer_pos] != '>' {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find the expected '>'")
+ return false
+ }
+
+ skip(parser)
+ } else {
+ // The tag has either the '!suffix' or the '!handle!suffix' form.
+
+ // First, try to scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
+ return false
+ }
+
+ // Check if it is, indeed, handle.
+ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+ // Scan the suffix now.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+ } else {
+ // It wasn't a handle after all. Scan the rest of the tag.
+ if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
+ return false
+ }
+
+ // Set the handle to '!'.
+ handle = []byte{'!'}
+
+ // A special case: the '!' tag. Set the handle to '' and the
+ // suffix to '!'.
+ if len(suffix) == 0 {
+ handle, suffix = suffix, handle
+ }
+ }
+ }
+
+ // Check the character which ends the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ suffix: suffix,
+ }
+ return true
+}
+
+// Scan a tag handle.
+func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
+ // Check the initial '!' character.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] != '!' {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+
+ var s []byte
+
+ // Copy the '!' character.
+ s = read(parser, s)
+
+ // Copy all subsequent alphabetical and numerical characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the trailing character is '!' and copy it.
+ if parser.buffer[parser.buffer_pos] == '!' {
+ s = read(parser, s)
+ } else {
+ // It's either the '!' tag or not really a tag handle. If it's a %TAG
+ // directive, it's an error. If it's a tag token, it must be a part of URI.
+ if directive && string(s) != "!" {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+ }
+
+ *handle = s
+ return true
+}
+
+// Scan a tag.
+func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
+ //size_t length = head ? strlen((char *)head) : 0
+ var s []byte
+ hasTag := len(head) > 0
+
+ // Copy the head if needed.
+ //
+ // Note that we don't copy the leading '!' character.
+ if len(head) > 1 {
+ s = append(s, head[1:]...)
+ }
+
+ // Scan the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // The set of characters that may appear in URI is as follows:
+ //
+ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+ // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+ // '%'.
+ // [Go] Convert this into more reasonable logic.
+ for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
+ parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
+ parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
+ parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
+ parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
+ parser.buffer[parser.buffer_pos] == '%' {
+ // Check if it is a URI-escape sequence.
+ if parser.buffer[parser.buffer_pos] == '%' {
+ if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
+ return false
+ }
+ } else {
+ s = read(parser, s)
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ hasTag = true
+ }
+
+ if !hasTag {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected tag URI")
+ return false
+ }
+ *uri = s
+ return true
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
+
+ // Decode the required number of characters.
+ w := 1024
+ for w > 0 {
+ // Check for a URI-escaped octet.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+
+ if !(parser.buffer[parser.buffer_pos] == '%' &&
+ is_hex(parser.buffer, parser.buffer_pos+1) &&
+ is_hex(parser.buffer, parser.buffer_pos+2)) {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find URI escaped octet")
+ }
+
+ // Get the octet.
+ octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
+
+ // If it is the leading octet, determine the length of the UTF-8 sequence.
+ if w == 1024 {
+ w = width(octet)
+ if w == 0 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect leading UTF-8 octet")
+ }
+ } else {
+ // Check if the trailing octet is correct.
+ if octet&0xC0 != 0x80 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect trailing UTF-8 octet")
+ }
+ }
+
+ // Copy the octet and move the pointers.
+ *s = append(*s, octet)
+ skip(parser)
+ skip(parser)
+ skip(parser)
+ w--
+ }
+ return true
+}
+
+// Scan a block scalar.
+func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
+ // Eat the indicator '|' or '>'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the additional block scalar indicators.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check for a chomping indicator.
+ var chomping, increment int
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ // Set the chomping method and eat the indicator.
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+
+ // Check for an indentation indicator.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_digit(parser.buffer, parser.buffer_pos) {
+ // Check that the indentation is greater than 0.
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+
+ // Get the indentation level and eat the indicator.
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+ }
+
+ } else if is_digit(parser.buffer, parser.buffer_pos) {
+ // Do the same as above, but in the opposite order.
+
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+ }
+ }
+
+ // Eat whitespaces and comments to the end of the line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.buffer[parser.buffer_pos] == '#' {
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ end_mark := parser.mark
+
+ // Set the indentation level if it was specified.
+ var indent int
+ if increment > 0 {
+ if parser.indent >= 0 {
+ indent = parser.indent + increment
+ } else {
+ indent = increment
+ }
+ }
+
+ // Scan the leading line breaks and determine the indentation level if needed.
+ var s, leading_break, trailing_breaks []byte
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+
+ // Scan the block scalar content.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var leading_blank, trailing_blank bool
+ for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
+ // We are at the beginning of a non-empty line.
+
+ // Is it a trailing whitespace?
+ trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Check if we need to fold the leading line break.
+ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+ // Do we need to join the lines by space?
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ }
+ } else {
+ s = append(s, leading_break...)
+ }
+ leading_break = leading_break[:0]
+
+ // Append the remaining line breaks.
+ s = append(s, trailing_breaks...)
+ trailing_breaks = trailing_breaks[:0]
+
+ // Is it a leading whitespace?
+ leading_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Consume the current line.
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ leading_break = read_line(parser, leading_break)
+
+ // Eat the following indentation spaces and line breaks.
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+ }
+
+ // Chomp the tail.
+ if chomping != -1 {
+ s = append(s, leading_break...)
+ }
+ if chomping == 1 {
+ s = append(s, trailing_breaks...)
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_LITERAL_SCALAR_STYLE,
+ }
+ if !literal {
+ token.style = yaml_FOLDED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan indentation spaces and line breaks for a block scalar. Determine the
+// indentation level if needed.
+func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
+ *end_mark = parser.mark
+
+ // Eat the indentation spaces and line breaks.
+ max_indent := 0
+ for {
+ // Eat the indentation spaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.mark.column > max_indent {
+ max_indent = parser.mark.column
+ }
+
+ // Check for a tab character messing the indentation.
+ if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found a tab character where an indentation space is expected")
+ }
+
+ // Have we found a non-empty line?
+ if !is_break(parser.buffer, parser.buffer_pos) {
+ break
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ // [Go] Should really be returning breaks instead.
+ *breaks = read_line(parser, *breaks)
+ *end_mark = parser.mark
+ }
+
+ // Determine the indentation level if needed.
+ if *indent == 0 {
+ *indent = max_indent
+ if *indent < parser.indent+1 {
+ *indent = parser.indent + 1
+ }
+ if *indent < 1 {
+ *indent = 1
+ }
+ }
+ return true
+}
+
+// Scan a quoted scalar.
+func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
+ // Eat the left quote.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the content of the quoted scalar.
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ for {
+ // Check that there are no document indicators at the beginning of the line.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected document indicator")
+ return false
+ }
+
+ // Check for EOF.
+ if is_z(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected end of stream")
+ return false
+ }
+
+ // Consume non-blank characters.
+ leading_blanks := false
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+ // Is is an escaped single quote.
+ s = append(s, '\'')
+ skip(parser)
+ skip(parser)
+
+ } else if single && parser.buffer[parser.buffer_pos] == '\'' {
+ // It is a right single quote.
+ break
+ } else if !single && parser.buffer[parser.buffer_pos] == '"' {
+ // It is a right double quote.
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
+ // It is an escaped line break.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+ skip(parser)
+ skip_line(parser)
+ leading_blanks = true
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+ // It is an escape sequence.
+ code_length := 0
+
+ // Check the escape character.
+ switch parser.buffer[parser.buffer_pos+1] {
+ case '0':
+ s = append(s, 0)
+ case 'a':
+ s = append(s, '\x07')
+ case 'b':
+ s = append(s, '\x08')
+ case 't', '\t':
+ s = append(s, '\x09')
+ case 'n':
+ s = append(s, '\x0A')
+ case 'v':
+ s = append(s, '\x0B')
+ case 'f':
+ s = append(s, '\x0C')
+ case 'r':
+ s = append(s, '\x0D')
+ case 'e':
+ s = append(s, '\x1B')
+ case ' ':
+ s = append(s, '\x20')
+ case '"':
+ s = append(s, '"')
+ case '\'':
+ s = append(s, '\'')
+ case '\\':
+ s = append(s, '\\')
+ case 'N': // NEL (#x85)
+ s = append(s, '\xC2')
+ s = append(s, '\x85')
+ case '_': // #xA0
+ s = append(s, '\xC2')
+ s = append(s, '\xA0')
+ case 'L': // LS (#x2028)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA8')
+ case 'P': // PS (#x2029)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA9')
+ case 'x':
+ code_length = 2
+ case 'u':
+ code_length = 4
+ case 'U':
+ code_length = 8
+ default:
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found unknown escape character")
+ return false
+ }
+
+ skip(parser)
+ skip(parser)
+
+ // Consume an arbitrary escape code.
+ if code_length > 0 {
+ var value int
+
+ // Scan the character value.
+ if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
+ return false
+ }
+ for k := 0; k < code_length; k++ {
+ if !is_hex(parser.buffer, parser.buffer_pos+k) {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "did not find expected hexdecimal number")
+ return false
+ }
+ value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
+ }
+
+ // Check the value and write the character.
+ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found invalid Unicode character escape code")
+ return false
+ }
+ if value <= 0x7F {
+ s = append(s, byte(value))
+ } else if value <= 0x7FF {
+ s = append(s, byte(0xC0+(value>>6)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else if value <= 0xFFFF {
+ s = append(s, byte(0xE0+(value>>12)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else {
+ s = append(s, byte(0xF0+(value>>18)))
+ s = append(s, byte(0x80+((value>>12)&0x3F)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ }
+
+ // Advance the pointer.
+ for k := 0; k < code_length; k++ {
+ skip(parser)
+ }
+ }
+ } else {
+ // It is a non-escaped non-blank character.
+ s = read(parser, s)
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we are at the end of the scalar.
+ if single {
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ break
+ }
+ } else {
+ if parser.buffer[parser.buffer_pos] == '"' {
+ break
+ }
+ }
+
+ // Consume blank characters.
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Join the whitespaces or fold line breaks.
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if len(leading_break) > 0 && leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Eat the right quote.
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_SINGLE_QUOTED_SCALAR_STYLE,
+ }
+ if !single {
+ token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan a plain scalar.
+func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
+
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ var leading_blanks bool
+ var indent = parser.indent + 1
+
+ start_mark := parser.mark
+ end_mark := parser.mark
+
+ // Consume the content of the plain scalar.
+ for {
+ // Check for a document indicator.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ break
+ }
+
+ // Check for a comment.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ break
+ }
+
+ // Consume non-blank characters.
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+
+ // Check for indicators that may end a plain scalar.
+ if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level > 0 &&
+ (parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}')) {
+ break
+ }
+
+ // Check if we need to join whitespaces and breaks.
+ if leading_blanks || len(whitespaces) > 0 {
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ leading_blanks = false
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Copy the character.
+ s = read(parser, s)
+
+ end_mark = parser.mark
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ // Is it the end?
+ if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
+ break
+ }
+
+ // Consume blank characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+
+ // Check for tab characters that abuse indentation.
+ if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+ start_mark, "found a tab character that violates indentation")
+ return false
+ }
+
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check indentation level.
+ if parser.flow_level == 0 && parser.mark.column < indent {
+ break
+ }
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_PLAIN_SCALAR_STYLE,
+ }
+
+ // Note that we change the 'simple_key_allowed' flag.
+ if leading_blanks {
+ parser.simple_key_allowed = true
+ }
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/sorter.go b/vendor/gopkg.in/yaml.v2/sorter.go
new file mode 100644
index 0000000..4c45e66
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/sorter.go
@@ -0,0 +1,113 @@
+package yaml
+
+import (
+ "reflect"
+ "unicode"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+ a := l[i]
+ b := l[j]
+ ak := a.Kind()
+ bk := b.Kind()
+ for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
+ a = a.Elem()
+ ak = a.Kind()
+ }
+ for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
+ b = b.Elem()
+ bk = b.Kind()
+ }
+ af, aok := keyFloat(a)
+ bf, bok := keyFloat(b)
+ if aok && bok {
+ if af != bf {
+ return af < bf
+ }
+ if ak != bk {
+ return ak < bk
+ }
+ return numLess(a, b)
+ }
+ if ak != reflect.String || bk != reflect.String {
+ return ak < bk
+ }
+ ar, br := []rune(a.String()), []rune(b.String())
+ for i := 0; i < len(ar) && i < len(br); i++ {
+ if ar[i] == br[i] {
+ continue
+ }
+ al := unicode.IsLetter(ar[i])
+ bl := unicode.IsLetter(br[i])
+ if al && bl {
+ return ar[i] < br[i]
+ }
+ if al || bl {
+ return bl
+ }
+ var ai, bi int
+ var an, bn int64
+ if ar[i] == '0' || br[i] == '0' {
+ for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ if ar[j] != '0' {
+ an = 1
+ bn = 1
+ break
+ }
+ }
+ }
+ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+ an = an*10 + int64(ar[ai]-'0')
+ }
+ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+ bn = bn*10 + int64(br[bi]-'0')
+ }
+ if an != bn {
+ return an < bn
+ }
+ if ai != bi {
+ return ai < bi
+ }
+ return ar[i] < br[i]
+ }
+ return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+ switch v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(v.Int()), true
+ case reflect.Float32, reflect.Float64:
+ return v.Float(), true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return float64(v.Uint()), true
+ case reflect.Bool:
+ if v.Bool() {
+ return 1, true
+ }
+ return 0, true
+ }
+ return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return a.Int() < b.Int()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ }
+ panic("not a number")
+}
diff --git a/vendor/gopkg.in/yaml.v2/writerc.go b/vendor/gopkg.in/yaml.v2/writerc.go
new file mode 100644
index 0000000..a2dde60
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/writerc.go
@@ -0,0 +1,26 @@
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_WRITER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+ if emitter.write_handler == nil {
+ panic("write handler not set")
+ }
+
+ // Check if the buffer is empty.
+ if emitter.buffer_pos == 0 {
+ return true
+ }
+
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+ }
+ emitter.buffer_pos = 0
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v2/yaml.go b/vendor/gopkg.in/yaml.v2/yaml.go
new file mode 100644
index 0000000..89650e2
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/yaml.go
@@ -0,0 +1,466 @@
+// Package yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+// https://github.com/go-yaml/yaml
+//
+package yaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "sync"
+)
+
+// MapSlice encodes and decodes as a YAML map.
+// The order of keys is preserved when encoding and decoding.
+type MapSlice []MapItem
+
+// MapItem is an item in a MapSlice.
+type MapItem struct {
+ Key, Value interface{}
+}
+
+// The Unmarshaler interface may be implemented by types to customize their
+// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
+// method receives a function that may be called to unmarshal the original
+// YAML value into a field or variable. It is safe to call the unmarshal
+// function parameter more than once if necessary.
+type Unmarshaler interface {
+ UnmarshalYAML(unmarshal func(interface{}) error) error
+}
+
+// The Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document. The returned value
+// is marshaled in place of the original value implementing Marshaler.
+//
+// If an error is returned by MarshalYAML, the marshaling procedure stops
+// and returns with the provided error.
+type Marshaler interface {
+ MarshalYAML() (interface{}, error)
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.TypeError is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshalling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// var t T
+// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+//
+func Unmarshal(in []byte, out interface{}) (err error) {
+ return unmarshal(in, out, false)
+}
+
+// UnmarshalStrict is like Unmarshal except that any fields that are found
+// in the data that do not have corresponding struct members, or mapping
+// keys that are duplicates, will result in
+// an error.
+func UnmarshalStrict(in []byte, out interface{}) (err error) {
+ return unmarshal(in, out, true)
+}
+
+// A Decoder reads and decodes YAML values from an input stream.
+type Decoder struct {
+ strict bool
+ parser *parser
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ parser: newParserFromReader(r),
+ }
+}
+
+// SetStrict sets whether strict decoding behaviour is enabled when
+// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
+func (dec *Decoder) SetStrict(strict bool) {
+ dec.strict = strict
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+ d := newDecoder(dec.strict)
+ defer handleErr(&err)
+ node := dec.parser.parse()
+ if node == nil {
+ return io.EOF
+ }
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(node, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+ defer handleErr(&err)
+ d := newDecoder(strict)
+ p := newParser(in)
+ defer p.destroy()
+ node := p.parse()
+ if node != nil {
+ v := reflect.ValueOf(out)
+ if v.Kind() == reflect.Ptr && !v.IsNil() {
+ v = v.Elem()
+ }
+ d.unmarshal(node, v)
+ }
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshalling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+// `(...) yaml:"[][,[,]]" (...)`
+//
+// The following flags are currently supported:
+//
+// omitempty Only include the field if it's not set to the zero
+// value for the type or to empty slices or maps.
+// Zero valued structs will be omitted if all their public
+// fields are zero, unless they implement an IsZero
+// method (see the IsZeroer interface type), in which
+// case the field will be included if that method returns true.
+//
+// flow Marshal using a flow style (useful for structs,
+// sequences and maps).
+//
+// inline Inline the field, which must be a struct or a map,
+// causing all of its fields or keys to be processed as if
+// they were part of the outer struct. For maps, keys must
+// not conflict with the yaml keys of other struct fields.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+//
+func Marshal(in interface{}) (out []byte, err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(in))
+ e.finish()
+ out = e.out
+ return
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+ encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ encoder: newEncoderWithWriter(w),
+ }
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e.encoder.marshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+ defer handleErr(&err)
+ e.encoder.finish()
+ return nil
+}
+
+func handleErr(err *error) {
+ if v := recover(); v != nil {
+ if e, ok := v.(yamlError); ok {
+ *err = e.err
+ } else {
+ panic(v)
+ }
+ }
+}
+
+type yamlError struct {
+ err error
+}
+
+func fail(err error) {
+ panic(yamlError{err})
+}
+
+func failf(format string, args ...interface{}) {
+ panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+}
+
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+type TypeError struct {
+ Errors []string
+}
+
+func (e *TypeError) Error() string {
+ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
+}
+
+// --------------------------------------------------------------------------
+// Maintain a mapping of keys to structure field indexes
+
+// The code in this section was copied from mgo/bson.
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+ FieldsMap map[string]fieldInfo
+ FieldsList []fieldInfo
+
+ // InlineMap is the number of the field in the struct that
+ // contains an ,inline map, or -1 if there's none.
+ InlineMap int
+}
+
+type fieldInfo struct {
+ Key string
+ Num int
+ OmitEmpty bool
+ Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
+
+ // Inline holds the field index if the field is part of an inlined struct.
+ Inline []int
+}
+
+var structMap = make(map[reflect.Type]*structInfo)
+var fieldMapMutex sync.RWMutex
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+ fieldMapMutex.RLock()
+ sinfo, found := structMap[st]
+ fieldMapMutex.RUnlock()
+ if found {
+ return sinfo, nil
+ }
+
+ n := st.NumField()
+ fieldsMap := make(map[string]fieldInfo)
+ fieldsList := make([]fieldInfo, 0, n)
+ inlineMap := -1
+ for i := 0; i != n; i++ {
+ field := st.Field(i)
+ if field.PkgPath != "" && !field.Anonymous {
+ continue // Private field
+ }
+
+ info := fieldInfo{Num: i}
+
+ tag := field.Tag.Get("yaml")
+ if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
+ tag = string(field.Tag)
+ }
+ if tag == "-" {
+ continue
+ }
+
+ inline := false
+ fields := strings.Split(tag, ",")
+ if len(fields) > 1 {
+ for _, flag := range fields[1:] {
+ switch flag {
+ case "omitempty":
+ info.OmitEmpty = true
+ case "flow":
+ info.Flow = true
+ case "inline":
+ inline = true
+ default:
+ return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
+ }
+ }
+ tag = fields[0]
+ }
+
+ if inline {
+ switch field.Type.Kind() {
+ case reflect.Map:
+ if inlineMap >= 0 {
+ return nil, errors.New("Multiple ,inline maps in struct " + st.String())
+ }
+ if field.Type.Key() != reflect.TypeOf("") {
+ return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
+ }
+ inlineMap = info.Num
+ case reflect.Struct:
+ sinfo, err := getStructInfo(field.Type)
+ if err != nil {
+ return nil, err
+ }
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
+ }
+ default:
+ //return nil, errors.New("Option ,inline needs a struct value or map field")
+ return nil, errors.New("Option ,inline needs a struct value field")
+ }
+ continue
+ }
+
+ if tag != "" {
+ info.Key = tag
+ } else {
+ info.Key = strings.ToLower(field.Name)
+ }
+
+ if _, found = fieldsMap[info.Key]; found {
+ msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+
+ info.Id = len(fieldsList)
+ fieldsList = append(fieldsList, info)
+ fieldsMap[info.Key] = info
+ }
+
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ }
+
+ fieldMapMutex.Lock()
+ structMap[st] = sinfo
+ fieldMapMutex.Unlock()
+ return sinfo, nil
+}
+
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+ IsZero() bool
+}
+
+func isZero(v reflect.Value) bool {
+ kind := v.Kind()
+ if z, ok := v.Interface().(IsZeroer); ok {
+ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+ return true
+ }
+ return z.IsZero()
+ }
+ switch kind {
+ case reflect.String:
+ return len(v.String()) == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ case reflect.Slice:
+ return v.Len() == 0
+ case reflect.Map:
+ return v.Len() == 0
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Struct:
+ vt := v.Type()
+ for i := v.NumField() - 1; i >= 0; i-- {
+ if vt.Field(i).PkgPath != "" {
+ continue // Private field
+ }
+ if !isZero(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
diff --git a/vendor/gopkg.in/yaml.v2/yamlh.go b/vendor/gopkg.in/yaml.v2/yamlh.go
new file mode 100644
index 0000000..f6a9c8e
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/yamlh.go
@@ -0,0 +1,739 @@
+package yaml
+
+import (
+ "fmt"
+ "io"
+)
+
+// The version directive data.
+type yaml_version_directive_t struct {
+ major int8 // The major version number.
+ minor int8 // The minor version number.
+}
+
+// The tag directive data.
+type yaml_tag_directive_t struct {
+ handle []byte // The tag handle.
+ prefix []byte // The tag prefix.
+}
+
+type yaml_encoding_t int
+
+// The stream encoding.
+const (
+ // Let the parser choose the encoding.
+ yaml_ANY_ENCODING yaml_encoding_t = iota
+
+ yaml_UTF8_ENCODING // The default UTF-8 encoding.
+ yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+ yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type yaml_break_t int
+
+// Line break types.
+const (
+ // Let the parser choose the break type.
+ yaml_ANY_BREAK yaml_break_t = iota
+
+ yaml_CR_BREAK // Use CR for line breaks (Mac style).
+ yaml_LN_BREAK // Use LN for line breaks (Unix style).
+ yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type yaml_error_type_t int
+
+// Many bad things could happen with the parser and emitter.
+const (
+ // No error is produced.
+ yaml_NO_ERROR yaml_error_type_t = iota
+
+ yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
+ yaml_READER_ERROR // Cannot read or decode the input stream.
+ yaml_SCANNER_ERROR // Cannot scan the input stream.
+ yaml_PARSER_ERROR // Cannot parse the input stream.
+ yaml_COMPOSER_ERROR // Cannot compose a YAML document.
+ yaml_WRITER_ERROR // Cannot write to the output stream.
+ yaml_EMITTER_ERROR // Cannot emit a YAML stream.
+)
+
+// The pointer position.
+type yaml_mark_t struct {
+ index int // The position index.
+ line int // The position line.
+ column int // The position column.
+}
+
+// Node Styles
+
+type yaml_style_t int8
+
+type yaml_scalar_style_t yaml_style_t
+
+// Scalar styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
+
+ yaml_PLAIN_SCALAR_STYLE // The plain scalar style.
+ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
+ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
+ yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
+ yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
+)
+
+type yaml_sequence_style_t yaml_style_t
+
+// Sequence styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
+
+ yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
+ yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
+)
+
+type yaml_mapping_style_t yaml_style_t
+
+// Mapping styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
+
+ yaml_BLOCK_MAPPING_STYLE // The block mapping style.
+ yaml_FLOW_MAPPING_STYLE // The flow mapping style.
+)
+
+// Tokens
+
+type yaml_token_type_t int
+
+// Token types.
+const (
+ // An empty token.
+ yaml_NO_TOKEN yaml_token_type_t = iota
+
+ yaml_STREAM_START_TOKEN // A STREAM-START token.
+ yaml_STREAM_END_TOKEN // A STREAM-END token.
+
+ yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+ yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
+ yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
+ yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
+
+ yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+ yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
+ yaml_BLOCK_END_TOKEN // A BLOCK-END token.
+
+ yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+ yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
+ yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
+ yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
+
+ yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+ yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
+ yaml_KEY_TOKEN // A KEY token.
+ yaml_VALUE_TOKEN // A VALUE token.
+
+ yaml_ALIAS_TOKEN // An ALIAS token.
+ yaml_ANCHOR_TOKEN // An ANCHOR token.
+ yaml_TAG_TOKEN // A TAG token.
+ yaml_SCALAR_TOKEN // A SCALAR token.
+)
+
+func (tt yaml_token_type_t) String() string {
+ switch tt {
+ case yaml_NO_TOKEN:
+ return "yaml_NO_TOKEN"
+ case yaml_STREAM_START_TOKEN:
+ return "yaml_STREAM_START_TOKEN"
+ case yaml_STREAM_END_TOKEN:
+ return "yaml_STREAM_END_TOKEN"
+ case yaml_VERSION_DIRECTIVE_TOKEN:
+ return "yaml_VERSION_DIRECTIVE_TOKEN"
+ case yaml_TAG_DIRECTIVE_TOKEN:
+ return "yaml_TAG_DIRECTIVE_TOKEN"
+ case yaml_DOCUMENT_START_TOKEN:
+ return "yaml_DOCUMENT_START_TOKEN"
+ case yaml_DOCUMENT_END_TOKEN:
+ return "yaml_DOCUMENT_END_TOKEN"
+ case yaml_BLOCK_SEQUENCE_START_TOKEN:
+ return "yaml_BLOCK_SEQUENCE_START_TOKEN"
+ case yaml_BLOCK_MAPPING_START_TOKEN:
+ return "yaml_BLOCK_MAPPING_START_TOKEN"
+ case yaml_BLOCK_END_TOKEN:
+ return "yaml_BLOCK_END_TOKEN"
+ case yaml_FLOW_SEQUENCE_START_TOKEN:
+ return "yaml_FLOW_SEQUENCE_START_TOKEN"
+ case yaml_FLOW_SEQUENCE_END_TOKEN:
+ return "yaml_FLOW_SEQUENCE_END_TOKEN"
+ case yaml_FLOW_MAPPING_START_TOKEN:
+ return "yaml_FLOW_MAPPING_START_TOKEN"
+ case yaml_FLOW_MAPPING_END_TOKEN:
+ return "yaml_FLOW_MAPPING_END_TOKEN"
+ case yaml_BLOCK_ENTRY_TOKEN:
+ return "yaml_BLOCK_ENTRY_TOKEN"
+ case yaml_FLOW_ENTRY_TOKEN:
+ return "yaml_FLOW_ENTRY_TOKEN"
+ case yaml_KEY_TOKEN:
+ return "yaml_KEY_TOKEN"
+ case yaml_VALUE_TOKEN:
+ return "yaml_VALUE_TOKEN"
+ case yaml_ALIAS_TOKEN:
+ return "yaml_ALIAS_TOKEN"
+ case yaml_ANCHOR_TOKEN:
+ return "yaml_ANCHOR_TOKEN"
+ case yaml_TAG_TOKEN:
+ return "yaml_TAG_TOKEN"
+ case yaml_SCALAR_TOKEN:
+ return "yaml_SCALAR_TOKEN"
+ }
+ return ""
+}
+
+// The token structure.
+type yaml_token_t struct {
+ // The token type.
+ typ yaml_token_type_t
+
+ // The start/end of the token.
+ start_mark, end_mark yaml_mark_t
+
+ // The stream encoding (for yaml_STREAM_START_TOKEN).
+ encoding yaml_encoding_t
+
+ // The alias/anchor/scalar value or tag/tag directive handle
+ // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
+ value []byte
+
+ // The tag suffix (for yaml_TAG_TOKEN).
+ suffix []byte
+
+ // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
+ prefix []byte
+
+ // The scalar style (for yaml_SCALAR_TOKEN).
+ style yaml_scalar_style_t
+
+ // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
+ major, minor int8
+}
+
+// Events
+
+type yaml_event_type_t int8
+
+// Event types.
+const (
+ // An empty event.
+ yaml_NO_EVENT yaml_event_type_t = iota
+
+ yaml_STREAM_START_EVENT // A STREAM-START event.
+ yaml_STREAM_END_EVENT // A STREAM-END event.
+ yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
+ yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
+ yaml_ALIAS_EVENT // An ALIAS event.
+ yaml_SCALAR_EVENT // A SCALAR event.
+ yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
+ yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
+ yaml_MAPPING_START_EVENT // A MAPPING-START event.
+ yaml_MAPPING_END_EVENT // A MAPPING-END event.
+)
+
+var eventStrings = []string{
+ yaml_NO_EVENT: "none",
+ yaml_STREAM_START_EVENT: "stream start",
+ yaml_STREAM_END_EVENT: "stream end",
+ yaml_DOCUMENT_START_EVENT: "document start",
+ yaml_DOCUMENT_END_EVENT: "document end",
+ yaml_ALIAS_EVENT: "alias",
+ yaml_SCALAR_EVENT: "scalar",
+ yaml_SEQUENCE_START_EVENT: "sequence start",
+ yaml_SEQUENCE_END_EVENT: "sequence end",
+ yaml_MAPPING_START_EVENT: "mapping start",
+ yaml_MAPPING_END_EVENT: "mapping end",
+}
+
+func (e yaml_event_type_t) String() string {
+ if e < 0 || int(e) >= len(eventStrings) {
+ return fmt.Sprintf("unknown event %d", e)
+ }
+ return eventStrings[e]
+}
+
+// The event structure.
+type yaml_event_t struct {
+
+ // The event type.
+ typ yaml_event_type_t
+
+ // The start and end of the event.
+ start_mark, end_mark yaml_mark_t
+
+ // The document encoding (for yaml_STREAM_START_EVENT).
+ encoding yaml_encoding_t
+
+ // The version directive (for yaml_DOCUMENT_START_EVENT).
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives (for yaml_DOCUMENT_START_EVENT).
+ tag_directives []yaml_tag_directive_t
+
+ // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
+ anchor []byte
+
+ // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ tag []byte
+
+ // The scalar value (for yaml_SCALAR_EVENT).
+ value []byte
+
+ // Is the document start/end indicator implicit, or the tag optional?
+ // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
+ implicit bool
+
+ // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
+ quoted_implicit bool
+
+ // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ style yaml_style_t
+}
+
+func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
+func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
+func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
+
+// Nodes
+
+const (
+ yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
+ yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
+ yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
+ yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
+ yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
+ yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+ yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+ yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+ // Not in original libyaml.
+ yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
+ yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
+
+ yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
+ yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
+ yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
+)
+
+type yaml_node_type_t int
+
+// Node types.
+const (
+ // An empty node.
+ yaml_NO_NODE yaml_node_type_t = iota
+
+ yaml_SCALAR_NODE // A scalar node.
+ yaml_SEQUENCE_NODE // A sequence node.
+ yaml_MAPPING_NODE // A mapping node.
+)
+
+// An element of a sequence node.
+type yaml_node_item_t int
+
+// An element of a mapping node.
+type yaml_node_pair_t struct {
+ key int // The key of the element.
+ value int // The value of the element.
+}
+
+// The node structure.
+type yaml_node_t struct {
+ typ yaml_node_type_t // The node type.
+ tag []byte // The node tag.
+
+ // The node data.
+
+ // The scalar parameters (for yaml_SCALAR_NODE).
+ scalar struct {
+ value []byte // The scalar value.
+ length int // The length of the scalar value.
+ style yaml_scalar_style_t // The scalar style.
+ }
+
+ // The sequence parameters (for YAML_SEQUENCE_NODE).
+ sequence struct {
+ items_data []yaml_node_item_t // The stack of sequence items.
+ style yaml_sequence_style_t // The sequence style.
+ }
+
+ // The mapping parameters (for yaml_MAPPING_NODE).
+ mapping struct {
+ pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
+ pairs_start *yaml_node_pair_t // The beginning of the stack.
+ pairs_end *yaml_node_pair_t // The end of the stack.
+ pairs_top *yaml_node_pair_t // The top of the stack.
+ style yaml_mapping_style_t // The mapping style.
+ }
+
+ start_mark yaml_mark_t // The beginning of the node.
+ end_mark yaml_mark_t // The end of the node.
+
+}
+
+// The document structure.
+type yaml_document_t struct {
+
+ // The document nodes.
+ nodes []yaml_node_t
+
+ // The version directive.
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives.
+ tag_directives_data []yaml_tag_directive_t
+ tag_directives_start int // The beginning of the tag directives list.
+ tag_directives_end int // The end of the tag directives list.
+
+ start_implicit int // Is the document start indicator implicit?
+ end_implicit int // Is the document end indicator implicit?
+
+ // The start/end of the document.
+ start_mark, end_mark yaml_mark_t
+}
+
+// The prototype of a read handler.
+//
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out] data A pointer to an application data specified by
+// yaml_parser_set_input().
+// [out] buffer The buffer to write the data from the source.
+// [in] size The size of the buffer.
+// [out] size_read The actual number of bytes read from the source.
+//
+// On success, the handler should return 1. If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
+
+// This structure holds information about a potential simple key.
+type yaml_simple_key_t struct {
+ possible bool // Is a simple key possible?
+ required bool // Is a simple key required?
+ token_number int // The number of the token.
+ mark yaml_mark_t // The position mark.
+}
+
+// The states of the parser.
+type yaml_parser_state_t int
+
+const (
+ yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
+
+ yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
+ yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
+ yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
+ yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
+ yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
+ yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
+ yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
+ yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
+ yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
+ yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
+ yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
+ yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
+ yaml_PARSE_END_STATE // Expect nothing.
+)
+
+func (ps yaml_parser_state_t) String() string {
+ switch ps {
+ case yaml_PARSE_STREAM_START_STATE:
+ return "yaml_PARSE_STREAM_START_STATE"
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return "yaml_PARSE_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return "yaml_PARSE_DOCUMENT_END_STATE"
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_STATE"
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return "yaml_PARSE_FLOW_NODE_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+ case yaml_PARSE_END_STATE:
+ return "yaml_PARSE_END_STATE"
+ }
+ return ""
+}
+
+// This structure holds aliases data.
+type yaml_alias_data_t struct {
+ anchor []byte // The anchor.
+ index int // The node id.
+ mark yaml_mark_t // The anchor mark.
+}
+
+// The parser structure.
+//
+// All members are internal. Manage the structure using the
+// yaml_parser_ family of functions.
+type yaml_parser_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+
+ problem string // Error description.
+
+ // The byte about which the problem occurred.
+ problem_offset int
+ problem_value int
+ problem_mark yaml_mark_t
+
+ // The error context.
+ context string
+ context_mark yaml_mark_t
+
+ // Reader stuff
+
+ read_handler yaml_read_handler_t // Read handler.
+
+ input_reader io.Reader // File input data.
+ input []byte // String input data.
+ input_pos int
+
+ eof bool // EOF flag
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ unread int // The number of unread characters in the buffer.
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The input encoding.
+
+ offset int // The offset of the current position (in bytes).
+ mark yaml_mark_t // The mark of the current position.
+
+ // Scanner stuff
+
+ stream_start_produced bool // Have we started to scan the input stream?
+ stream_end_produced bool // Have we reached the end of the input stream?
+
+ flow_level int // The number of unclosed '[' and '{' indicators.
+
+ tokens []yaml_token_t // The tokens queue.
+ tokens_head int // The head of the tokens queue.
+ tokens_parsed int // The number of tokens fetched from the queue.
+ token_available bool // Does the tokens queue contain a token ready for dequeueing.
+
+ indent int // The current indentation level.
+ indents []int // The indentation levels stack.
+
+ simple_key_allowed bool // May a simple key occur at the current position?
+ simple_keys []yaml_simple_key_t // The stack of simple keys.
+ simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
+
+ // Parser stuff
+
+ state yaml_parser_state_t // The current parser state.
+ states []yaml_parser_state_t // The parser states stack.
+ marks []yaml_mark_t // The stack of marks.
+ tag_directives []yaml_tag_directive_t // The list of TAG directives.
+
+ // Dumper stuff
+
+ aliases []yaml_alias_data_t // The alias data.
+
+ document *yaml_document_t // The currently parsed document.
+}
+
+// Emitter Definitions
+
+// The prototype of a write handler.
+//
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output. The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out] data A pointer to an application data specified by
+// yaml_emitter_set_output().
+// @param[in] buffer The buffer with bytes to be written.
+// @param[in] size The size of the buffer.
+//
+// @returns On success, the handler should return @c 1. If the handler failed,
+// the returned value should be @c 0.
+//
+type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
+
+type yaml_emitter_state_t int
+
+// The emitter states.
+const (
+ // Expect STREAM-START.
+ yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
+
+ yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
+ yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
+ yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
+ yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
+ yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
+ yaml_EMIT_END_STATE // Expect nothing.
+)
+
+// The emitter structure.
+//
+// All members are internal. Manage the structure using the @c yaml_emitter_
+// family of functions.
+type yaml_emitter_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+ problem string // Error description.
+
+ // Writer stuff
+
+ write_handler yaml_write_handler_t // Write handler.
+
+ output_buffer *[]byte // String output data.
+ output_writer io.Writer // File output data.
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The stream encoding.
+
+ // Emitter stuff
+
+ canonical bool // If the output is in the canonical style?
+ best_indent int // The number of indentation spaces.
+ best_width int // The preferred width of the output lines.
+ unicode bool // Allow unescaped non-ASCII characters?
+ line_break yaml_break_t // The preferred line break.
+
+ state yaml_emitter_state_t // The current emitter state.
+ states []yaml_emitter_state_t // The stack of states.
+
+ events []yaml_event_t // The event queue.
+ events_head int // The head of the event queue.
+
+ indents []int // The stack of indentation levels.
+
+ tag_directives []yaml_tag_directive_t // The list of tag directives.
+
+ indent int // The current indentation level.
+
+ flow_level int // The current flow level.
+
+ root_context bool // Is it the document root context?
+ sequence_context bool // Is it a sequence context?
+ mapping_context bool // Is it a mapping context?
+ simple_key_context bool // Is it a simple mapping key context?
+
+ line int // The current line.
+ column int // The current column.
+ whitespace bool // If the last character was a whitespace?
+ indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
+ open_ended bool // If an explicit document end is required?
+
+ // Anchor analysis.
+ anchor_data struct {
+ anchor []byte // The anchor value.
+ alias bool // Is it an alias?
+ }
+
+ // Tag analysis.
+ tag_data struct {
+ handle []byte // The tag handle.
+ suffix []byte // The tag suffix.
+ }
+
+ // Scalar analysis.
+ scalar_data struct {
+ value []byte // The scalar value.
+ multiline bool // Does the scalar contain line breaks?
+ flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
+ block_plain_allowed bool // Can the scalar be expressed in the block plain style?
+ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
+ block_allowed bool // Can the scalar be expressed in the literal or folded styles?
+ style yaml_scalar_style_t // The output style.
+ }
+
+ // Dumper stuff
+
+ opened bool // If the stream was already opened?
+ closed bool // If the stream was already closed?
+
+ // The information associated with the document nodes.
+ anchors *struct {
+ references int // The number of references.
+ anchor int // The anchor id.
+ serialized bool // If the node has been emitted?
+ }
+
+ last_anchor_id int // The last assigned anchor id.
+
+ document *yaml_document_t // The currently emitted document.
+}
diff --git a/vendor/gopkg.in/yaml.v2/yamlprivateh.go b/vendor/gopkg.in/yaml.v2/yamlprivateh.go
new file mode 100644
index 0000000..8110ce3
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/yamlprivateh.go
@@ -0,0 +1,173 @@
+package yaml
+
+const (
+ // The size of the input raw buffer.
+ input_raw_buffer_size = 512
+
+ // The size of the input buffer.
+ // It should be possible to decode the whole raw buffer.
+ input_buffer_size = input_raw_buffer_size * 3
+
+ // The size of the output buffer.
+ output_buffer_size = 128
+
+ // The size of the output raw buffer.
+ // It should be possible to encode the whole output buffer.
+ output_raw_buffer_size = (output_buffer_size*2 + 2)
+
+ // The size of other stacks and queues.
+ initial_stack_size = 16
+ initial_queue_size = 16
+ initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func is_alpha(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a digit.
+func is_digit(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func as_digit(b []byte, i int) int {
+ return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func is_hex(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func as_hex(b []byte, i int) int {
+ bi := b[i]
+ if bi >= 'A' && bi <= 'F' {
+ return int(bi) - 'A' + 10
+ }
+ if bi >= 'a' && bi <= 'f' {
+ return int(bi) - 'a' + 10
+ }
+ return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func is_ascii(b []byte, i int) bool {
+ return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func is_printable(b []byte, i int) bool {
+ return ((b[i] == 0x0A) || // . == #x0A
+ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+ (b[i] > 0xC2 && b[i] < 0xED) ||
+ (b[i] == 0xED && b[i+1] < 0xA0) ||
+ (b[i] == 0xEE) ||
+ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func is_z(b []byte, i int) bool {
+ return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func is_bom(b []byte, i int) bool {
+ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func is_space(b []byte, i int) bool {
+ return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func is_tab(b []byte, i int) bool {
+ return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func is_blank(b []byte, i int) bool {
+ //return is_space(b, i) || is_tab(b, i)
+ return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func is_break(b []byte, i int) bool {
+ return (b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func is_crlf(b []byte, i int) bool {
+ return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func is_breakz(b []byte, i int) bool {
+ //return is_break(b, i) || is_z(b, i)
+ return ( // is_break:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ // is_z:
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func is_spacez(b []byte, i int) bool {
+ //return is_space(b, i) || is_breakz(b, i)
+ return ( // is_space:
+ b[i] == ' ' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func is_blankz(b []byte, i int) bool {
+ //return is_blank(b, i) || is_breakz(b, i)
+ return ( // is_blank:
+ b[i] == ' ' || b[i] == '\t' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+ // Don't replace these by a switch without first
+ // confirming that it is being inlined.
+ if b&0x80 == 0x00 {
+ return 1
+ }
+ if b&0xE0 == 0xC0 {
+ return 2
+ }
+ if b&0xF0 == 0xE0 {
+ return 3
+ }
+ if b&0xF8 == 0xF0 {
+ return 4
+ }
+ return 0
+
+}
diff --git a/vendor/gopkg.in/yaml.v3/LICENSE b/vendor/gopkg.in/yaml.v3/LICENSE
new file mode 100644
index 0000000..2683e4b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/LICENSE
@@ -0,0 +1,50 @@
+
+This project is covered by two different licenses: MIT and Apache.
+
+#### MIT License ####
+
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original MIT license, with the additional
+copyright staring in 2011 when the project was ported over:
+
+ apic.go emitterc.go parserc.go readerc.go scannerc.go
+ writerc.go yamlh.go yamlprivateh.go
+
+Copyright (c) 2006-2010 Kirill Simonov
+Copyright (c) 2006-2011 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+### Apache License ###
+
+All the remaining project files are covered by the Apache license:
+
+Copyright (c) 2011-2019 Canonical Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v3/NOTICE b/vendor/gopkg.in/yaml.v3/NOTICE
new file mode 100644
index 0000000..866d74a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/NOTICE
@@ -0,0 +1,13 @@
+Copyright 2011-2016 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/gopkg.in/yaml.v3/README.md b/vendor/gopkg.in/yaml.v3/README.md
new file mode 100644
index 0000000..08eb1ba
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/README.md
@@ -0,0 +1,150 @@
+# YAML support for the Go language
+
+Introduction
+------------
+
+The yaml package enables Go programs to comfortably encode and decode YAML
+values. It was developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a
+pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
+C library to parse and generate YAML data quickly and reliably.
+
+Compatibility
+-------------
+
+The yaml package supports most of YAML 1.2, but preserves some behavior
+from 1.1 for backwards compatibility.
+
+Specifically, as of v3 of the yaml package:
+
+ - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
+ decoded into a typed bool value. Otherwise they behave as a string. Booleans
+ in YAML 1.2 are _true/false_ only.
+ - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
+ as specified in YAML 1.2, because most parsers still use the old format.
+ Octals in the _0o777_ format are supported though, so new files work.
+ - Does not support base-60 floats. These are gone from YAML 1.2, and were
+ actually never supported by this package as it's clearly a poor choice.
+
+and offers backwards
+compatibility with YAML 1.1 in some cases.
+1.2, including support for
+anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
+implemented, and base-60 floats from YAML 1.1 are purposefully not
+supported since they're a poor design and are gone in YAML 1.2.
+
+Installation and usage
+----------------------
+
+The import path for the package is *gopkg.in/yaml.v3*.
+
+To install it, run:
+
+ go get gopkg.in/yaml.v3
+
+API documentation
+-----------------
+
+If opened in a browser, the import path itself leads to the API documentation:
+
+ - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
+
+API stability
+-------------
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
+
+
+License
+-------
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
+
+
+Example
+-------
+
+```Go
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "gopkg.in/yaml.v3"
+)
+
+var data = `
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+ A string
+ B struct {
+ RenamedC int `yaml:"c"`
+ D []int `yaml:",flow"`
+ }
+}
+
+func main() {
+ t := T{}
+
+ err := yaml.Unmarshal([]byte(data), &t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t:\n%v\n\n", t)
+
+ d, err := yaml.Marshal(&t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+ m := make(map[interface{}]interface{})
+
+ err = yaml.Unmarshal([]byte(data), &m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m:\n%v\n\n", m)
+
+ d, err = yaml.Marshal(&m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+ c: 2
+ d:
+ - 3
+ - 4
+```
+
diff --git a/vendor/gopkg.in/yaml.v3/apic.go b/vendor/gopkg.in/yaml.v3/apic.go
new file mode 100644
index 0000000..ae7d049
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/apic.go
@@ -0,0 +1,747 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+ // Check if we can move the queue at the beginning of the buffer.
+ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+ if parser.tokens_head != len(parser.tokens) {
+ copy(parser.tokens, parser.tokens[parser.tokens_head:])
+ }
+ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+ parser.tokens_head = 0
+ }
+ parser.tokens = append(parser.tokens, *token)
+ if pos < 0 {
+ return
+ }
+ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+ parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+ *parser = yaml_parser_t{
+ raw_buffer: make([]byte, 0, input_raw_buffer_size),
+ buffer: make([]byte, 0, input_buffer_size),
+ }
+ return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+ *parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ if parser.input_pos == len(parser.input) {
+ return 0, io.EOF
+ }
+ n = copy(buffer, parser.input[parser.input_pos:])
+ parser.input_pos += n
+ return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_string_read_handler
+ parser.input = input
+ parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_reader_read_handler
+ parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+ if parser.encoding != yaml_ANY_ENCODING {
+ panic("must set the encoding only once")
+ }
+ parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{
+ buffer: make([]byte, output_buffer_size),
+ raw_buffer: make([]byte, 0, output_raw_buffer_size),
+ states: make([]yaml_emitter_state_t, 0, initial_stack_size),
+ events: make([]yaml_event_t, 0, initial_queue_size),
+ best_width: -1,
+ }
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+ return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ _, err := emitter.output_writer.Write(buffer)
+ return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_string_write_handler
+ emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_writer_write_handler
+ emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+ if emitter.encoding != yaml_ANY_ENCODING {
+ panic("must set the output encoding only once")
+ }
+ emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+ emitter.canonical = canonical
+}
+
+// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+ if indent < 2 || indent > 9 {
+ indent = 2
+ }
+ emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+ if width < 0 {
+ width = -1
+ }
+ emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+ emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+ emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+// assert(token); // Non-NULL token object expected.
+//
+// switch (token.type)
+// {
+// case YAML_TAG_DIRECTIVE_TOKEN:
+// yaml_free(token.data.tag_directive.handle);
+// yaml_free(token.data.tag_directive.prefix);
+// break;
+//
+// case YAML_ALIAS_TOKEN:
+// yaml_free(token.data.alias.value);
+// break;
+//
+// case YAML_ANCHOR_TOKEN:
+// yaml_free(token.data.anchor.value);
+// break;
+//
+// case YAML_TAG_TOKEN:
+// yaml_free(token.data.tag.handle);
+// yaml_free(token.data.tag.suffix);
+// break;
+//
+// case YAML_SCALAR_TOKEN:
+// yaml_free(token.data.scalar.value);
+// break;
+//
+// default:
+// break;
+// }
+//
+// memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+// yaml_char_t *end = start+length;
+// yaml_char_t *pointer = start;
+//
+// while (pointer < end) {
+// unsigned char octet;
+// unsigned int width;
+// unsigned int value;
+// size_t k;
+//
+// octet = pointer[0];
+// width = (octet & 0x80) == 0x00 ? 1 :
+// (octet & 0xE0) == 0xC0 ? 2 :
+// (octet & 0xF0) == 0xE0 ? 3 :
+// (octet & 0xF8) == 0xF0 ? 4 : 0;
+// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+// if (!width) return 0;
+// if (pointer+width > end) return 0;
+// for (k = 1; k < width; k ++) {
+// octet = pointer[k];
+// if ((octet & 0xC0) != 0x80) return 0;
+// value = (value << 6) + (octet & 0x3F);
+// }
+// if (!((width == 1) ||
+// (width == 2 && value >= 0x80) ||
+// (width == 3 && value >= 0x800) ||
+// (width == 4 && value >= 0x10000))) return 0;
+//
+// pointer += width;
+// }
+//
+// return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ encoding: encoding,
+ }
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ }
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+ event *yaml_event_t,
+ version_directive *yaml_version_directive_t,
+ tag_directives []yaml_tag_directive_t,
+ implicit bool,
+) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: implicit,
+ }
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ implicit: implicit,
+ }
+}
+
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ anchor: anchor,
+ }
+ return true
+}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ anchor: anchor,
+ tag: tag,
+ value: value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ }
+ return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ }
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+ *event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+// version_directive *yaml_version_directive_t,
+// tag_directives_start *yaml_tag_directive_t,
+// tag_directives_end *yaml_tag_directive_t,
+// start_implicit int, end_implicit int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// struct {
+// start *yaml_node_t
+// end *yaml_node_t
+// top *yaml_node_t
+// } nodes = { NULL, NULL, NULL }
+// version_directive_copy *yaml_version_directive_t = NULL
+// struct {
+// start *yaml_tag_directive_t
+// end *yaml_tag_directive_t
+// top *yaml_tag_directive_t
+// } tag_directives_copy = { NULL, NULL, NULL }
+// value yaml_tag_directive_t = { NULL, NULL }
+// mark yaml_mark_t = { 0, 0, 0 }
+//
+// assert(document) // Non-NULL document object is expected.
+// assert((tag_directives_start && tag_directives_end) ||
+// (tag_directives_start == tag_directives_end))
+// // Valid tag directives are expected.
+//
+// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+// if (version_directive) {
+// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+// if (!version_directive_copy) goto error
+// version_directive_copy.major = version_directive.major
+// version_directive_copy.minor = version_directive.minor
+// }
+//
+// if (tag_directives_start != tag_directives_end) {
+// tag_directive *yaml_tag_directive_t
+// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+// goto error
+// for (tag_directive = tag_directives_start
+// tag_directive != tag_directives_end; tag_directive ++) {
+// assert(tag_directive.handle)
+// assert(tag_directive.prefix)
+// if (!yaml_check_utf8(tag_directive.handle,
+// strlen((char *)tag_directive.handle)))
+// goto error
+// if (!yaml_check_utf8(tag_directive.prefix,
+// strlen((char *)tag_directive.prefix)))
+// goto error
+// value.handle = yaml_strdup(tag_directive.handle)
+// value.prefix = yaml_strdup(tag_directive.prefix)
+// if (!value.handle || !value.prefix) goto error
+// if (!PUSH(&context, tag_directives_copy, value))
+// goto error
+// value.handle = NULL
+// value.prefix = NULL
+// }
+// }
+//
+// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+// tag_directives_copy.start, tag_directives_copy.top,
+// start_implicit, end_implicit, mark, mark)
+//
+// return 1
+//
+//error:
+// STACK_DEL(&context, nodes)
+// yaml_free(version_directive_copy)
+// while (!STACK_EMPTY(&context, tag_directives_copy)) {
+// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+// }
+// STACK_DEL(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+//
+// return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// tag_directive *yaml_tag_directive_t
+//
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// while (!STACK_EMPTY(&context, document.nodes)) {
+// node yaml_node_t = POP(&context, document.nodes)
+// yaml_free(node.tag)
+// switch (node.type) {
+// case YAML_SCALAR_NODE:
+// yaml_free(node.data.scalar.value)
+// break
+// case YAML_SEQUENCE_NODE:
+// STACK_DEL(&context, node.data.sequence.items)
+// break
+// case YAML_MAPPING_NODE:
+// STACK_DEL(&context, node.data.mapping.pairs)
+// break
+// default:
+// assert(0) // Should not happen.
+// }
+// }
+// STACK_DEL(&context, document.nodes)
+//
+// yaml_free(document.version_directive)
+// for (tag_directive = document.tag_directives.start
+// tag_directive != document.tag_directives.end
+// tag_directive++) {
+// yaml_free(tag_directive.handle)
+// yaml_free(tag_directive.prefix)
+// }
+// yaml_free(document.tag_directives.start)
+//
+// memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+// return document.nodes.start + index - 1
+// }
+// return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (document.nodes.top != document.nodes.start) {
+// return document.nodes.start
+// }
+// return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+// tag *yaml_char_t, value *yaml_char_t, length int,
+// style yaml_scalar_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// value_copy *yaml_char_t = NULL
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+// assert(value) // Non-NULL value is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (length < 0) {
+// length = strlen((char *)value)
+// }
+//
+// if (!yaml_check_utf8(value, length)) goto error
+// value_copy = yaml_malloc(length+1)
+// if (!value_copy) goto error
+// memcpy(value_copy, value, length)
+// value_copy[length] = '\0'
+//
+// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// yaml_free(tag_copy)
+// yaml_free(value_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_item_t
+// end *yaml_node_item_t
+// top *yaml_node_item_t
+// } items = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, items)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_pair_t
+// end *yaml_node_pair_t
+// top *yaml_node_pair_t
+// } pairs = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, pairs)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+// sequence int, item int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// assert(document) // Non-NULL document is required.
+// assert(sequence > 0
+// && document.nodes.start + sequence <= document.nodes.top)
+// // Valid sequence id is required.
+// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+// // A sequence node is required.
+// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+// // Valid item id is required.
+//
+// if (!PUSH(&context,
+// document.nodes.start[sequence-1].data.sequence.items, item))
+// return 0
+//
+// return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+// mapping int, key int, value int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// pair yaml_node_pair_t
+//
+// assert(document) // Non-NULL document is required.
+// assert(mapping > 0
+// && document.nodes.start + mapping <= document.nodes.top)
+// // Valid mapping id is required.
+// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+// // A mapping node is required.
+// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+// // Valid key id is required.
+// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+// // Valid value id is required.
+//
+// pair.key = key
+// pair.value = value
+//
+// if (!PUSH(&context,
+// document.nodes.start[mapping-1].data.mapping.pairs, pair))
+// return 0
+//
+// return 1
+//}
+//
+//
diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go
new file mode 100644
index 0000000..df36e3a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/decode.go
@@ -0,0 +1,950 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+ parser yaml_parser_t
+ event yaml_event_t
+ doc *Node
+ anchors map[string]*Node
+ doneInit bool
+ textless bool
+}
+
+func newParser(b []byte) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ if len(b) == 0 {
+ b = []byte{'\n'}
+ }
+ yaml_parser_set_input_string(&p.parser, b)
+ return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ yaml_parser_set_input_reader(&p.parser, r)
+ return &p
+}
+
+func (p *parser) init() {
+ if p.doneInit {
+ return
+ }
+ p.anchors = make(map[string]*Node)
+ p.expect(yaml_STREAM_START_EVENT)
+ p.doneInit = true
+}
+
+func (p *parser) destroy() {
+ if p.event.typ != yaml_NO_EVENT {
+ yaml_event_delete(&p.event)
+ }
+ yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+ if p.event.typ == yaml_NO_EVENT {
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ }
+ if p.event.typ == yaml_STREAM_END_EVENT {
+ failf("attempted to go past the end of stream; corrupted value?")
+ }
+ if p.event.typ != e {
+ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+ p.fail()
+ }
+ yaml_event_delete(&p.event)
+ p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+ if p.event.typ != yaml_NO_EVENT {
+ return p.event.typ
+ }
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ return p.event.typ
+}
+
+func (p *parser) fail() {
+ var where string
+ var line int
+ if p.parser.context_mark.line != 0 {
+ line = p.parser.context_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ } else if p.parser.problem_mark.line != 0 {
+ line = p.parser.problem_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ }
+ if line != 0 {
+ where = "line " + strconv.Itoa(line) + ": "
+ }
+ var msg string
+ if len(p.parser.problem) > 0 {
+ msg = p.parser.problem
+ } else {
+ msg = "unknown problem parsing YAML content"
+ }
+ failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *Node, anchor []byte) {
+ if anchor != nil {
+ n.Anchor = string(anchor)
+ p.anchors[n.Anchor] = n
+ }
+}
+
+func (p *parser) parse() *Node {
+ p.init()
+ switch p.peek() {
+ case yaml_SCALAR_EVENT:
+ return p.scalar()
+ case yaml_ALIAS_EVENT:
+ return p.alias()
+ case yaml_MAPPING_START_EVENT:
+ return p.mapping()
+ case yaml_SEQUENCE_START_EVENT:
+ return p.sequence()
+ case yaml_DOCUMENT_START_EVENT:
+ return p.document()
+ case yaml_STREAM_END_EVENT:
+ // Happens when attempting to decode an empty buffer.
+ return nil
+ case yaml_TAIL_COMMENT_EVENT:
+ panic("internal error: unexpected tail comment event (please report)")
+ default:
+ panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
+ }
+}
+
+func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
+ var style Style
+ if tag != "" && tag != "!" {
+ tag = shortTag(tag)
+ style = TaggedStyle
+ } else if defaultTag != "" {
+ tag = defaultTag
+ } else if kind == ScalarNode {
+ tag, _ = resolve("", value)
+ }
+ n := &Node{
+ Kind: kind,
+ Tag: tag,
+ Value: value,
+ Style: style,
+ }
+ if !p.textless {
+ n.Line = p.event.start_mark.line + 1
+ n.Column = p.event.start_mark.column + 1
+ n.HeadComment = string(p.event.head_comment)
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ }
+ return n
+}
+
+func (p *parser) parseChild(parent *Node) *Node {
+ child := p.parse()
+ parent.Content = append(parent.Content, child)
+ return child
+}
+
+func (p *parser) document() *Node {
+ n := p.node(DocumentNode, "", "", "")
+ p.doc = n
+ p.expect(yaml_DOCUMENT_START_EVENT)
+ p.parseChild(n)
+ if p.peek() == yaml_DOCUMENT_END_EVENT {
+ n.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_DOCUMENT_END_EVENT)
+ return n
+}
+
+func (p *parser) alias() *Node {
+ n := p.node(AliasNode, "", "", string(p.event.anchor))
+ n.Alias = p.anchors[n.Value]
+ if n.Alias == nil {
+ failf("unknown anchor '%s' referenced", n.Value)
+ }
+ p.expect(yaml_ALIAS_EVENT)
+ return n
+}
+
+func (p *parser) scalar() *Node {
+ var parsedStyle = p.event.scalar_style()
+ var nodeStyle Style
+ switch {
+ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = DoubleQuotedStyle
+ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = SingleQuotedStyle
+ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
+ nodeStyle = LiteralStyle
+ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
+ nodeStyle = FoldedStyle
+ }
+ var nodeValue = string(p.event.value)
+ var nodeTag = string(p.event.tag)
+ var defaultTag string
+ if nodeStyle == 0 {
+ if nodeValue == "<<" {
+ defaultTag = mergeTag
+ }
+ } else {
+ defaultTag = strTag
+ }
+ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+ n.Style |= nodeStyle
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SCALAR_EVENT)
+ return n
+}
+
+func (p *parser) sequence() *Node {
+ n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
+ if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
+ n.Style |= FlowStyle
+ }
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SEQUENCE_START_EVENT)
+ for p.peek() != yaml_SEQUENCE_END_EVENT {
+ p.parseChild(n)
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ p.expect(yaml_SEQUENCE_END_EVENT)
+ return n
+}
+
+func (p *parser) mapping() *Node {
+ n := p.node(MappingNode, mapTag, string(p.event.tag), "")
+ block := true
+ if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
+ block = false
+ n.Style |= FlowStyle
+ }
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_MAPPING_START_EVENT)
+ for p.peek() != yaml_MAPPING_END_EVENT {
+ k := p.parseChild(n)
+ if block && k.FootComment != "" {
+ // Must be a foot comment for the prior value when being dedented.
+ if len(n.Content) > 2 {
+ n.Content[len(n.Content)-3].FootComment = k.FootComment
+ k.FootComment = ""
+ }
+ }
+ v := p.parseChild(n)
+ if k.FootComment == "" && v.FootComment != "" {
+ k.FootComment = v.FootComment
+ v.FootComment = ""
+ }
+ if p.peek() == yaml_TAIL_COMMENT_EVENT {
+ if k.FootComment == "" {
+ k.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_TAIL_COMMENT_EVENT)
+ }
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+ n.Content[len(n.Content)-2].FootComment = n.FootComment
+ n.FootComment = ""
+ }
+ p.expect(yaml_MAPPING_END_EVENT)
+ return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+ doc *Node
+ aliases map[*Node]bool
+ terrors []string
+
+ stringMapType reflect.Type
+ generalMapType reflect.Type
+
+ knownFields bool
+ uniqueKeys bool
+ decodeCount int
+ aliasCount int
+ aliasDepth int
+}
+
+var (
+ nodeType = reflect.TypeOf(Node{})
+ durationType = reflect.TypeOf(time.Duration(0))
+ stringMapType = reflect.TypeOf(map[string]interface{}{})
+ generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
+ ifaceType = generalMapType.Elem()
+ timeType = reflect.TypeOf(time.Time{})
+ ptrTimeType = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder() *decoder {
+ d := &decoder{
+ stringMapType: stringMapType,
+ generalMapType: generalMapType,
+ uniqueKeys: true,
+ }
+ d.aliases = make(map[*Node]bool)
+ return d
+}
+
+func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
+ if n.Tag != "" {
+ tag = n.Tag
+ }
+ value := n.Value
+ if tag != seqTag && tag != mapTag {
+ if len(value) > 10 {
+ value = " `" + value[:7] + "...`"
+ } else {
+ value = " `" + value + "`"
+ }
+ }
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
+ err := u.UnmarshalYAML(n)
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
+ terrlen := len(d.terrors)
+ err := u.UnmarshalYAML(func(v interface{}) (err error) {
+ defer handleErr(&err)
+ d.unmarshal(n, reflect.ValueOf(v))
+ if len(d.terrors) > terrlen {
+ issues := d.terrors[terrlen:]
+ d.terrors = d.terrors[:terrlen]
+ return &TypeError{issues}
+ }
+ return nil
+ })
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+ if n.ShortTag() == nullTag {
+ return out, false, false
+ }
+ again := true
+ for again {
+ again = false
+ if out.Kind() == reflect.Ptr {
+ if out.IsNil() {
+ out.Set(reflect.New(out.Type().Elem()))
+ }
+ out = out.Elem()
+ again = true
+ }
+ if out.CanAddr() {
+ outi := out.Addr().Interface()
+ if u, ok := outi.(Unmarshaler); ok {
+ good = d.callUnmarshaler(n, u)
+ return out, true, good
+ }
+ if u, ok := outi.(obsoleteUnmarshaler); ok {
+ good = d.callObsoleteUnmarshaler(n, u)
+ return out, true, good
+ }
+ }
+ }
+ return out, false, false
+}
+
+func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+ if n.ShortTag() == nullTag {
+ return reflect.Value{}
+ }
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+const (
+ // 400,000 decode operations is ~500kb of dense object declarations, or
+ // ~5kb of dense object declarations with 10000% alias expansion
+ alias_ratio_range_low = 400000
+
+ // 4,000,000 decode operations is ~5MB of dense object declarations, or
+ // ~4.5MB of dense object declarations with 10% alias expansion
+ alias_ratio_range_high = 4000000
+
+ // alias_ratio_range is the range over which we scale allowed alias ratios
+ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(decodeCount int) float64 {
+ switch {
+ case decodeCount <= alias_ratio_range_low:
+ // allow 99% to come from alias expansion for small-to-medium documents
+ return 0.99
+ case decodeCount >= alias_ratio_range_high:
+ // allow 10% to come from alias expansion for very large documents
+ return 0.10
+ default:
+ // scale smoothly from 99% down to 10% over the range.
+ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+ return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
+ }
+}
+
+func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
+ d.decodeCount++
+ if d.aliasDepth > 0 {
+ d.aliasCount++
+ }
+ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
+ failf("document contains excessive aliasing")
+ }
+ if out.Type() == nodeType {
+ out.Set(reflect.ValueOf(n).Elem())
+ return true
+ }
+ switch n.Kind {
+ case DocumentNode:
+ return d.document(n, out)
+ case AliasNode:
+ return d.alias(n, out)
+ }
+ out, unmarshaled, good := d.prepare(n, out)
+ if unmarshaled {
+ return good
+ }
+ switch n.Kind {
+ case ScalarNode:
+ good = d.scalar(n, out)
+ case MappingNode:
+ good = d.mapping(n, out)
+ case SequenceNode:
+ good = d.sequence(n, out)
+ case 0:
+ if n.IsZero() {
+ return d.null(out)
+ }
+ fallthrough
+ default:
+ failf("cannot decode node with unknown kind %d", n.Kind)
+ }
+ return good
+}
+
+func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
+ if len(n.Content) == 1 {
+ d.doc = n
+ d.unmarshal(n.Content[0], out)
+ return true
+ }
+ return false
+}
+
+func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
+ if d.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
+ failf("anchor '%s' value contains itself", n.Value)
+ }
+ d.aliases[n] = true
+ d.aliasDepth++
+ good = d.unmarshal(n.Alias, out)
+ d.aliasDepth--
+ delete(d.aliases, n)
+ return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+ for _, k := range out.MapKeys() {
+ out.SetMapIndex(k, zeroValue)
+ }
+}
+
+func (d *decoder) null(out reflect.Value) bool {
+ if out.CanAddr() {
+ switch out.Kind() {
+ case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+ out.Set(reflect.Zero(out.Type()))
+ return true
+ }
+ }
+ return false
+}
+
+func (d *decoder) scalar(n *Node, out reflect.Value) bool {
+ var tag string
+ var resolved interface{}
+ if n.indicatedString() {
+ tag = strTag
+ resolved = n.Value
+ } else {
+ tag, resolved = resolve(n.Tag, n.Value)
+ if tag == binaryTag {
+ data, err := base64.StdEncoding.DecodeString(resolved.(string))
+ if err != nil {
+ failf("!!binary value contains invalid base64 data")
+ }
+ resolved = string(data)
+ }
+ }
+ if resolved == nil {
+ return d.null(out)
+ }
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ // We've resolved to exactly the type we want, so use that.
+ out.Set(resolvedv)
+ return true
+ }
+ // Perhaps we can use the value as a TextUnmarshaler to
+ // set its value.
+ if out.CanAddr() {
+ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ if ok {
+ var text []byte
+ if tag == binaryTag {
+ text = []byte(resolved.(string))
+ } else {
+ // We let any value be unmarshaled into TextUnmarshaler.
+ // That might be more lax than we'd like, but the
+ // TextUnmarshaler itself should bowl out any dubious values.
+ text = []byte(n.Value)
+ }
+ err := u.UnmarshalText(text)
+ if err != nil {
+ fail(err)
+ }
+ return true
+ }
+ }
+ switch out.Kind() {
+ case reflect.String:
+ if tag == binaryTag {
+ out.SetString(resolved.(string))
+ return true
+ }
+ out.SetString(n.Value)
+ return true
+ case reflect.Interface:
+ out.Set(reflect.ValueOf(resolved))
+ return true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ // This used to work in v2, but it's very unfriendly.
+ isDuration := out.Type() == durationType
+
+ switch resolved := resolved.(type) {
+ case int:
+ if !isDuration && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case int64:
+ if !isDuration && !out.OverflowInt(resolved) {
+ out.SetInt(resolved)
+ return true
+ }
+ case uint64:
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case float64:
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case string:
+ if out.Type() == durationType {
+ d, err := time.ParseDuration(resolved)
+ if err == nil {
+ out.SetInt(int64(d))
+ return true
+ }
+ }
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch resolved := resolved.(type) {
+ case int:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case int64:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case uint64:
+ if !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ }
+ case reflect.Bool:
+ switch resolved := resolved.(type) {
+ case bool:
+ out.SetBool(resolved)
+ return true
+ case string:
+ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+ // It only works if explicitly attempting to unmarshal into a typed bool value.
+ switch resolved {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+ out.SetBool(true)
+ return true
+ case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ out.SetBool(false)
+ return true
+ }
+ }
+ case reflect.Float32, reflect.Float64:
+ switch resolved := resolved.(type) {
+ case int:
+ out.SetFloat(float64(resolved))
+ return true
+ case int64:
+ out.SetFloat(float64(resolved))
+ return true
+ case uint64:
+ out.SetFloat(float64(resolved))
+ return true
+ case float64:
+ out.SetFloat(resolved)
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
+ }
+ case reflect.Ptr:
+ panic("yaml internal error: please report the issue")
+ }
+ d.terror(n, tag, out)
+ return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+ v := reflect.ValueOf(i)
+ sv := reflect.New(v.Type()).Elem()
+ sv.Set(v)
+ return sv
+}
+
+func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+
+ var iface reflect.Value
+ switch out.Kind() {
+ case reflect.Slice:
+ out.Set(reflect.MakeSlice(out.Type(), l, l))
+ case reflect.Array:
+ if l != out.Len() {
+ failf("invalid array: want %d elements but got %d", out.Len(), l)
+ }
+ case reflect.Interface:
+ // No type hints. Will have to use a generic sequence.
+ iface = out
+ out = settableValueOf(make([]interface{}, l))
+ default:
+ d.terror(n, seqTag, out)
+ return false
+ }
+ et := out.Type().Elem()
+
+ j := 0
+ for i := 0; i < l; i++ {
+ e := reflect.New(et).Elem()
+ if ok := d.unmarshal(n.Content[i], e); ok {
+ out.Index(j).Set(e)
+ j++
+ }
+ }
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
+ if iface.IsValid() {
+ iface.Set(out)
+ }
+ return true
+}
+
+func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+ if d.uniqueKeys {
+ nerrs := len(d.terrors)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ for j := i + 2; j < l; j += 2 {
+ nj := n.Content[j]
+ if ni.Kind == nj.Kind && ni.Value == nj.Value {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
+ }
+ }
+ }
+ if len(d.terrors) > nerrs {
+ return false
+ }
+ }
+ switch out.Kind() {
+ case reflect.Struct:
+ return d.mappingStruct(n, out)
+ case reflect.Map:
+ // okay
+ case reflect.Interface:
+ iface := out
+ if isStringMap(n) {
+ out = reflect.MakeMap(d.stringMapType)
+ } else {
+ out = reflect.MakeMap(d.generalMapType)
+ }
+ iface.Set(out)
+ default:
+ d.terror(n, mapTag, out)
+ return false
+ }
+
+ outt := out.Type()
+ kt := outt.Key()
+ et := outt.Elem()
+
+ stringMapType := d.stringMapType
+ generalMapType := d.generalMapType
+ if outt.Elem() == ifaceType {
+ if outt.Key().Kind() == reflect.String {
+ d.stringMapType = outt
+ } else if outt.Key() == ifaceType {
+ d.generalMapType = outt
+ }
+ }
+
+ mapIsNew := false
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(outt))
+ mapIsNew = true
+ }
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.Content[i]) {
+ d.merge(n.Content[i+1], out)
+ continue
+ }
+ k := reflect.New(kt).Elem()
+ if d.unmarshal(n.Content[i], k) {
+ kkind := k.Kind()
+ if kkind == reflect.Interface {
+ kkind = k.Elem().Kind()
+ }
+ if kkind == reflect.Map || kkind == reflect.Slice {
+ failf("invalid map key: %#v", k.Interface())
+ }
+ e := reflect.New(et).Elem()
+ if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+ out.SetMapIndex(k, e)
+ }
+ }
+ }
+ d.stringMapType = stringMapType
+ d.generalMapType = generalMapType
+ return true
+}
+
+func isStringMap(n *Node) bool {
+ if n.Kind != MappingNode {
+ return false
+ }
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ if n.Content[i].ShortTag() != strTag {
+ return false
+ }
+ }
+ return true
+}
+
+func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
+ sinfo, err := getStructInfo(out.Type())
+ if err != nil {
+ panic(err)
+ }
+
+ var inlineMap reflect.Value
+ var elemType reflect.Type
+ if sinfo.InlineMap != -1 {
+ inlineMap = out.Field(sinfo.InlineMap)
+ inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
+ elemType = inlineMap.Type().Elem()
+ }
+
+ for _, index := range sinfo.InlineUnmarshalers {
+ field := d.fieldByIndex(n, out, index)
+ d.prepare(n, field)
+ }
+
+ var doneFields []bool
+ if d.uniqueKeys {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
+ name := settableValueOf("")
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ if isMerge(ni) {
+ d.merge(n.Content[i+1], out)
+ continue
+ }
+ if !d.unmarshal(ni, name) {
+ continue
+ }
+ if info, ok := sinfo.FieldsMap[name.String()]; ok {
+ if d.uniqueKeys {
+ if doneFields[info.Id] {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
+ continue
+ }
+ doneFields[info.Id] = true
+ }
+ var field reflect.Value
+ if info.Inline == nil {
+ field = out.Field(info.Num)
+ } else {
+ field = d.fieldByIndex(n, out, info.Inline)
+ }
+ d.unmarshal(n.Content[i+1], field)
+ } else if sinfo.InlineMap != -1 {
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+ value := reflect.New(elemType).Elem()
+ d.unmarshal(n.Content[i+1], value)
+ inlineMap.SetMapIndex(name, value)
+ } else if d.knownFields {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
+ }
+ }
+ return true
+}
+
+func failWantMap() {
+ failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) merge(n *Node, out reflect.Value) {
+ switch n.Kind {
+ case MappingNode:
+ d.unmarshal(n, out)
+ case AliasNode:
+ if n.Alias != nil && n.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ d.unmarshal(n, out)
+ case SequenceNode:
+ // Step backwards as earlier nodes take precedence.
+ for i := len(n.Content) - 1; i >= 0; i-- {
+ ni := n.Content[i]
+ if ni.Kind == AliasNode {
+ if ni.Alias != nil && ni.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ } else if ni.Kind != MappingNode {
+ failWantMap()
+ }
+ d.unmarshal(ni, out)
+ }
+ default:
+ failWantMap()
+ }
+}
+
+func isMerge(n *Node) bool {
+ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
+}
diff --git a/vendor/gopkg.in/yaml.v3/emitterc.go b/vendor/gopkg.in/yaml.v3/emitterc.go
new file mode 100644
index 0000000..0f47c9c
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/emitterc.go
@@ -0,0 +1,2020 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ return yaml_emitter_flush(emitter)
+ }
+ return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.buffer[emitter.buffer_pos] = value
+ emitter.buffer_pos++
+ emitter.column++
+ return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ switch emitter.line_break {
+ case yaml_CR_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\r'
+ emitter.buffer_pos += 1
+ case yaml_LN_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\n'
+ emitter.buffer_pos += 1
+ case yaml_CRLN_BREAK:
+ emitter.buffer[emitter.buffer_pos+0] = '\r'
+ emitter.buffer[emitter.buffer_pos+1] = '\n'
+ emitter.buffer_pos += 2
+ default:
+ panic("unknown line break setting")
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and below and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ p := emitter.buffer_pos
+ w := width(s[*i])
+ switch w {
+ case 4:
+ emitter.buffer[p+3] = s[*i+3]
+ fallthrough
+ case 3:
+ emitter.buffer[p+2] = s[*i+2]
+ fallthrough
+ case 2:
+ emitter.buffer[p+1] = s[*i+1]
+ fallthrough
+ case 1:
+ emitter.buffer[p+0] = s[*i+0]
+ default:
+ panic("unknown character width")
+ }
+ emitter.column++
+ emitter.buffer_pos += w
+ *i += w
+ return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+ for i := 0; i < len(s); {
+ if !write(emitter, s, &i) {
+ return false
+ }
+ }
+ return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if s[*i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ *i++
+ } else {
+ if !write(emitter, s, i) {
+ return false
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and above and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ }
+ return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_EMITTER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.events = append(emitter.events, *event)
+ for !yaml_emitter_need_more_events(emitter) {
+ event := &emitter.events[emitter.events_head]
+ if !yaml_emitter_analyze_event(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_state_machine(emitter, event) {
+ return false
+ }
+ yaml_event_delete(event)
+ emitter.events_head++
+ }
+ return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+// - 1 event for DOCUMENT-START
+// - 2 events for SEQUENCE-START
+// - 3 events for MAPPING-START
+//
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+ if emitter.events_head == len(emitter.events) {
+ return true
+ }
+ var accumulate int
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_DOCUMENT_START_EVENT:
+ accumulate = 1
+ break
+ case yaml_SEQUENCE_START_EVENT:
+ accumulate = 2
+ break
+ case yaml_MAPPING_START_EVENT:
+ accumulate = 3
+ break
+ default:
+ return false
+ }
+ if len(emitter.events)-emitter.events_head > accumulate {
+ return false
+ }
+ var level int
+ for i := emitter.events_head; i < len(emitter.events); i++ {
+ switch emitter.events[i].typ {
+ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+ level++
+ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+ level--
+ }
+ if level == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+ }
+ }
+
+ // [Go] Do we actually need to copy this given garbage collection
+ // and the lack of deallocating destructors?
+ tag_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(tag_copy.handle, value.handle)
+ copy(tag_copy.prefix, value.prefix)
+ emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+ return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
+ emitter.indents = append(emitter.indents, emitter.indent)
+ if emitter.indent < 0 {
+ if flow {
+ emitter.indent = emitter.best_indent
+ } else {
+ emitter.indent = 0
+ }
+ } else if !indentless {
+ // [Go] This was changed so that indentations are more regular.
+ if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+ // The first indent inside a sequence will just skip the "- " indicator.
+ emitter.indent += 2
+ } else {
+ // Everything else aligns to the chosen indentation.
+ emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
+ }
+ }
+ return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ switch emitter.state {
+ default:
+ case yaml_EMIT_STREAM_START_STATE:
+ return yaml_emitter_emit_stream_start(emitter, event)
+
+ case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, true)
+
+ case yaml_EMIT_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, false)
+
+ case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+ return yaml_emitter_emit_document_content(emitter, event)
+
+ case yaml_EMIT_DOCUMENT_END_STATE:
+ return yaml_emitter_emit_document_end(emitter, event)
+
+ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
+
+ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
+
+ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
+
+ case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
+
+ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_END_STATE:
+ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+ }
+ panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_STREAM_START_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+ }
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = event.encoding
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = yaml_UTF8_ENCODING
+ }
+ }
+ if emitter.best_indent < 2 || emitter.best_indent > 9 {
+ emitter.best_indent = 2
+ }
+ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+ emitter.best_width = 80
+ }
+ if emitter.best_width < 0 {
+ emitter.best_width = 1<<31 - 1
+ }
+ if emitter.line_break == yaml_ANY_BREAK {
+ emitter.line_break = yaml_LN_BREAK
+ }
+
+ emitter.indent = -1
+ emitter.line = 0
+ emitter.column = 0
+ emitter.whitespace = true
+ emitter.indention = true
+ emitter.space_above = true
+ emitter.foot_indent = -1
+
+ if emitter.encoding != yaml_UTF8_ENCODING {
+ if !yaml_emitter_write_bom(emitter) {
+ return false
+ }
+ }
+ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+ return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+ if event.typ == yaml_DOCUMENT_START_EVENT {
+
+ if event.version_directive != nil {
+ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+ return false
+ }
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(default_tag_directives); i++ {
+ tag_directive := &default_tag_directives[i]
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+ return false
+ }
+ }
+
+ implicit := event.implicit
+ if !first || emitter.canonical {
+ implicit = false
+ }
+
+ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if event.version_directive != nil {
+ implicit = false
+ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if len(event.tag_directives) > 0 {
+ implicit = false
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if yaml_emitter_check_empty_document(emitter) {
+ implicit = false
+ }
+ if !implicit {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+ return false
+ }
+ if emitter.canonical || true {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if len(emitter.head_comment) > 0 {
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !put_break(emitter) {
+ return false
+ }
+ }
+
+ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+ return true
+ }
+
+ if event.typ == yaml_STREAM_END_EVENT {
+ if emitter.open_ended {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_END_STATE
+ return true
+ }
+
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_DOCUMENT_END_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+ }
+ // [Go] Force document foot separation.
+ emitter.foot_indent = 0
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.foot_indent = -1
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !event.implicit {
+ // [Go] Allocate the slice elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+ emitter.tag_directives = emitter.tag_directives[:0]
+ return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ if emitter.canonical && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.column == 0 || emitter.canonical && !first {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+
+ return true
+ }
+
+ if !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_MAPPING_END_EVENT {
+ if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+
+ if !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+ return false
+ }
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ return false
+ }
+ }
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if len(emitter.line_comment) > 0 {
+ // [Go] A line comment was provided for the key. That's unusual as the
+ // scanner associates line comments with the value. Either way,
+ // save the line comment and render it appropriately later.
+ emitter.key_line_comment = emitter.line_comment
+ emitter.line_comment = nil
+ }
+ if yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+ return false
+ }
+ }
+ if len(emitter.key_line_comment) > 0 {
+ // [Go] Line comments are generally associated with the value, but when there's
+ // no value on the same line as a mapping key they end up attached to the
+ // key itself.
+ if event.typ == yaml_SCALAR_EVENT {
+ if len(emitter.line_comment) == 0 {
+ // A scalar is coming and it has no line comments by itself yet,
+ // so just let it handle the line comment as usual. If it has a
+ // line comment, we can't have both so the one from the key is lost.
+ emitter.line_comment = emitter.key_line_comment
+ emitter.key_line_comment = nil
+ }
+ } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+ // An indented block follows, so write the comment right now.
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+ root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+ emitter.root_context = root
+ emitter.sequence_context = sequence
+ emitter.mapping_context = mapping
+ emitter.simple_key_context = simple_key
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ return yaml_emitter_emit_alias(emitter, event)
+ case yaml_SCALAR_EVENT:
+ return yaml_emitter_emit_scalar(emitter, event)
+ case yaml_SEQUENCE_START_EVENT:
+ return yaml_emitter_emit_sequence_start(emitter, event)
+ case yaml_MAPPING_START_EVENT:
+ return yaml_emitter_emit_mapping_start(emitter, event)
+ default:
+ return yaml_emitter_set_emitter_error(emitter,
+ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+ }
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_select_scalar_style(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_scalar(emitter) {
+ return false
+ }
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+ yaml_emitter_check_empty_sequence(emitter) {
+ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+ }
+ return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+ yaml_emitter_check_empty_mapping(emitter) {
+ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+ }
+ return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+ return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+ length := 0
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_ALIAS_EVENT:
+ length += len(emitter.anchor_data.anchor)
+ case yaml_SCALAR_EVENT:
+ if emitter.scalar_data.multiline {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix) +
+ len(emitter.scalar_data.value)
+ case yaml_SEQUENCE_START_EVENT:
+ if !yaml_emitter_check_empty_sequence(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ case yaml_MAPPING_START_EVENT:
+ if !yaml_emitter_check_empty_mapping(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ default:
+ return false
+ }
+ return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+ if no_tag && !event.implicit && !event.quoted_implicit {
+ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+ }
+
+ style := event.scalar_style()
+ if style == yaml_ANY_SCALAR_STYLE {
+ style = yaml_PLAIN_SCALAR_STYLE
+ }
+ if emitter.canonical {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ if emitter.simple_key_context && emitter.scalar_data.multiline {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ if style == yaml_PLAIN_SCALAR_STYLE {
+ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if no_tag && !event.implicit {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+ if !emitter.scalar_data.single_quoted_allowed {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+
+ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+ emitter.tag_data.handle = []byte{'!'}
+ }
+ emitter.scalar_data.style = style
+ return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+ if emitter.anchor_data.anchor == nil {
+ return true
+ }
+ c := []byte{'&'}
+ if emitter.anchor_data.alias {
+ c[0] = '*'
+ }
+ if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+ return false
+ }
+ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+ return true
+ }
+ if len(emitter.tag_data.handle) > 0 {
+ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+ return false
+ }
+ if len(emitter.tag_data.suffix) > 0 {
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ }
+ } else {
+ // [Go] Allocate these slices elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+ switch emitter.scalar_data.style {
+ case yaml_PLAIN_SCALAR_STYLE:
+ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_LITERAL_SCALAR_STYLE:
+ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+ case yaml_FOLDED_SCALAR_STYLE:
+ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+ }
+ panic("unknown scalar style")
+}
+
+// Write a head comment.
+func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
+ return false
+ }
+ emitter.tail_comment = emitter.tail_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ }
+
+ if len(emitter.head_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
+ return false
+ }
+ emitter.head_comment = emitter.head_comment[:0]
+ return true
+}
+
+// Write an line comment.
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.line_comment) == 0 {
+ return true
+ }
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
+ return false
+ }
+ emitter.line_comment = emitter.line_comment[:0]
+ return true
+}
+
+// Write a foot comment.
+func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.foot_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
+ return false
+ }
+ emitter.foot_comment = emitter.foot_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ return true
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+ if version_directive.major != 1 || version_directive.minor != 1 {
+ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+ }
+ return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+ handle := tag_directive.handle
+ prefix := tag_directive.prefix
+ if len(handle) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+ }
+ if handle[0] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+ }
+ if handle[len(handle)-1] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+ }
+ for i := 1; i < len(handle)-1; i += width(handle[i]) {
+ if !is_alpha(handle, i) {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+ }
+ }
+ if len(prefix) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+ }
+ return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+ if len(anchor) == 0 {
+ problem := "anchor value must not be empty"
+ if alias {
+ problem = "alias value must not be empty"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ for i := 0; i < len(anchor); i += width(anchor[i]) {
+ if !is_alpha(anchor, i) {
+ problem := "anchor value must contain alphanumerical characters only"
+ if alias {
+ problem = "alias value must contain alphanumerical characters only"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ }
+ emitter.anchor_data.anchor = anchor
+ emitter.anchor_data.alias = alias
+ return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+ if len(tag) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+ }
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ tag_directive := &emitter.tag_directives[i]
+ if bytes.HasPrefix(tag, tag_directive.prefix) {
+ emitter.tag_data.handle = tag_directive.handle
+ emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+ return true
+ }
+ }
+ emitter.tag_data.suffix = tag
+ return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ var (
+ block_indicators = false
+ flow_indicators = false
+ line_breaks = false
+ special_characters = false
+ tab_characters = false
+
+ leading_space = false
+ leading_break = false
+ trailing_space = false
+ trailing_break = false
+ break_space = false
+ space_break = false
+
+ preceded_by_whitespace = false
+ followed_by_whitespace = false
+ previous_space = false
+ previous_break = false
+ )
+
+ emitter.scalar_data.value = value
+
+ if len(value) == 0 {
+ emitter.scalar_data.multiline = false
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = false
+ return true
+ }
+
+ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+ block_indicators = true
+ flow_indicators = true
+ }
+
+ preceded_by_whitespace = true
+ for i, w := 0, 0; i < len(value); i += w {
+ w = width(value[i])
+ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+ if i == 0 {
+ switch value[i] {
+ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+ flow_indicators = true
+ block_indicators = true
+ case '?', ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '-':
+ if followed_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ } else {
+ switch value[i] {
+ case ',', '?', '[', ']', '{', '}':
+ flow_indicators = true
+ case ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '#':
+ if preceded_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ }
+
+ if value[i] == '\t' {
+ tab_characters = true
+ } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+ special_characters = true
+ }
+ if is_space(value, i) {
+ if i == 0 {
+ leading_space = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_space = true
+ }
+ if previous_break {
+ break_space = true
+ }
+ previous_space = true
+ previous_break = false
+ } else if is_break(value, i) {
+ line_breaks = true
+ if i == 0 {
+ leading_break = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_break = true
+ }
+ if previous_space {
+ space_break = true
+ }
+ previous_space = false
+ previous_break = true
+ } else {
+ previous_space = false
+ previous_break = false
+ }
+
+ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+ preceded_by_whitespace = is_blankz(value, i)
+ }
+
+ emitter.scalar_data.multiline = line_breaks
+ emitter.scalar_data.flow_plain_allowed = true
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = true
+
+ if leading_space || leading_break || trailing_space || trailing_break {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if trailing_space {
+ emitter.scalar_data.block_allowed = false
+ }
+ if break_space {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || tab_characters || special_characters {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
+ emitter.scalar_data.block_allowed = false
+ }
+ if line_breaks {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if flow_indicators {
+ emitter.scalar_data.flow_plain_allowed = false
+ }
+ if block_indicators {
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ emitter.anchor_data.anchor = nil
+ emitter.tag_data.handle = nil
+ emitter.tag_data.suffix = nil
+ emitter.scalar_data.value = nil
+
+ if len(event.head_comment) > 0 {
+ emitter.head_comment = event.head_comment
+ }
+ if len(event.line_comment) > 0 {
+ emitter.line_comment = event.line_comment
+ }
+ if len(event.foot_comment) > 0 {
+ emitter.foot_comment = event.foot_comment
+ }
+ if len(event.tail_comment) > 0 {
+ emitter.tail_comment = event.tail_comment
+ }
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+ return false
+ }
+
+ case yaml_SCALAR_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ if !yaml_emitter_analyze_scalar(emitter, event.value) {
+ return false
+ }
+
+ case yaml_SEQUENCE_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+
+ case yaml_MAPPING_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+ if !flush(emitter) {
+ return false
+ }
+ pos := emitter.buffer_pos
+ emitter.buffer[pos+0] = '\xEF'
+ emitter.buffer[pos+1] = '\xBB'
+ emitter.buffer[pos+2] = '\xBF'
+ emitter.buffer_pos += 3
+ return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+ indent := emitter.indent
+ if indent < 0 {
+ indent = 0
+ }
+ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if emitter.foot_indent == indent {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ for emitter.column < indent {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ emitter.whitespace = true
+ //emitter.indention = true
+ emitter.space_above = false
+ emitter.foot_indent = -1
+ return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, indicator) {
+ return false
+ }
+ emitter.whitespace = is_whitespace
+ emitter.indention = (emitter.indention && is_indention)
+ emitter.open_ended = false
+ return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ for i := 0; i < len(value); {
+ var must_write bool
+ switch value[i] {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+ must_write = true
+ default:
+ must_write = is_alpha(value, i)
+ }
+ if must_write {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ } else {
+ w := width(value[i])
+ for k := 0; k < w; k++ {
+ octet := value[i]
+ i++
+ if !put(emitter, '%') {
+ return false
+ }
+
+ c := octet >> 4
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+
+ c = octet & 0x0f
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+ }
+ }
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ if len(value) > 0 && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+
+ if len(value) > 0 {
+ emitter.whitespace = false
+ }
+ emitter.indention = false
+ if emitter.root_context {
+ emitter.open_ended = true
+ }
+
+ return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+ return false
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if value[i] == '\'' {
+ if !put(emitter, '\'') {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ spaces := false
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+ return false
+ }
+
+ for i := 0; i < len(value); {
+ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+ is_bom(value, i) || is_break(value, i) ||
+ value[i] == '"' || value[i] == '\\' {
+
+ octet := value[i]
+
+ var w int
+ var v rune
+ switch {
+ case octet&0x80 == 0x00:
+ w, v = 1, rune(octet&0x7F)
+ case octet&0xE0 == 0xC0:
+ w, v = 2, rune(octet&0x1F)
+ case octet&0xF0 == 0xE0:
+ w, v = 3, rune(octet&0x0F)
+ case octet&0xF8 == 0xF0:
+ w, v = 4, rune(octet&0x07)
+ }
+ for k := 1; k < w; k++ {
+ octet = value[i+k]
+ v = (v << 6) + (rune(octet) & 0x3F)
+ }
+ i += w
+
+ if !put(emitter, '\\') {
+ return false
+ }
+
+ var ok bool
+ switch v {
+ case 0x00:
+ ok = put(emitter, '0')
+ case 0x07:
+ ok = put(emitter, 'a')
+ case 0x08:
+ ok = put(emitter, 'b')
+ case 0x09:
+ ok = put(emitter, 't')
+ case 0x0A:
+ ok = put(emitter, 'n')
+ case 0x0b:
+ ok = put(emitter, 'v')
+ case 0x0c:
+ ok = put(emitter, 'f')
+ case 0x0d:
+ ok = put(emitter, 'r')
+ case 0x1b:
+ ok = put(emitter, 'e')
+ case 0x22:
+ ok = put(emitter, '"')
+ case 0x5c:
+ ok = put(emitter, '\\')
+ case 0x85:
+ ok = put(emitter, 'N')
+ case 0xA0:
+ ok = put(emitter, '_')
+ case 0x2028:
+ ok = put(emitter, 'L')
+ case 0x2029:
+ ok = put(emitter, 'P')
+ default:
+ if v <= 0xFF {
+ ok = put(emitter, 'x')
+ w = 2
+ } else if v <= 0xFFFF {
+ ok = put(emitter, 'u')
+ w = 4
+ } else {
+ ok = put(emitter, 'U')
+ w = 8
+ }
+ for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+ digit := byte((v >> uint(k)) & 0x0F)
+ if digit < 10 {
+ ok = put(emitter, digit+'0')
+ } else {
+ ok = put(emitter, digit+'A'-10)
+ }
+ }
+ }
+ if !ok {
+ return false
+ }
+ spaces = false
+ } else if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if is_space(value, i+1) {
+ if !put(emitter, '\\') {
+ return false
+ }
+ }
+ i += width(value[i])
+ } else if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = true
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+ if is_space(value, 0) || is_break(value, 0) {
+ indent_hint := []byte{'0' + byte(emitter.best_indent)}
+ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+ return false
+ }
+ }
+
+ emitter.open_ended = false
+
+ var chomp_hint [1]byte
+ if len(value) == 0 {
+ chomp_hint[0] = '-'
+ } else {
+ i := len(value) - 1
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if !is_break(value, i) {
+ chomp_hint[0] = '-'
+ } else if i == 0 {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ } else {
+ i--
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if is_break(value, i) {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ }
+ }
+ }
+ if chomp_hint[0] != 0 {
+ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+ //emitter.indention = true
+ emitter.whitespace = true
+ breaks := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+
+ return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter) {
+ return false
+ }
+
+ //emitter.indention = true
+ emitter.whitespace = true
+
+ breaks := true
+ leading_spaces := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !breaks && !leading_spaces && value[i] == '\n' {
+ k := 0
+ for is_break(value, k) {
+ k += width(value[k])
+ }
+ if !is_blankz(value, k) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ leading_spaces = is_blank(value, i)
+ }
+ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
+ breaks := false
+ pound := false
+ for i := 0; i < len(comment); {
+ if is_break(comment, i) {
+ if !write_break(emitter, comment, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ pound = false
+ } else {
+ if breaks && !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !pound {
+ if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
+ return false
+ }
+ pound = true
+ }
+ if !write(emitter, comment, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ if !breaks && !put_break(emitter) {
+ return false
+ }
+
+ emitter.whitespace = true
+ //emitter.indention = true
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/encode.go b/vendor/gopkg.in/yaml.v3/encode.go
new file mode 100644
index 0000000..de9e72a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/encode.go
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+type encoder struct {
+ emitter yaml_emitter_t
+ event yaml_event_t
+ out []byte
+ flow bool
+ indent int
+ doneInit bool
+}
+
+func newEncoder() *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_string(&e.emitter, &e.out)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_writer(&e.emitter, w)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func (e *encoder) init() {
+ if e.doneInit {
+ return
+ }
+ if e.indent == 0 {
+ e.indent = 4
+ }
+ e.emitter.best_indent = e.indent
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+ e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
+ e.emitter.open_ended = false
+ yaml_stream_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) destroy() {
+ yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+ // This will internally delete the e.event value.
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+ if !ok {
+ msg := e.emitter.problem
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ var node *Node
+ if in.IsValid() {
+ node, _ = in.Interface().(*Node)
+ }
+ if node != nil && node.Kind == DocumentNode {
+ e.nodev(in)
+ } else {
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.emit()
+ e.marshal(tag, in)
+ yaml_document_end_event_initialize(&e.event, true)
+ e.emit()
+ }
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+ tag = shortTag(tag)
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+ e.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch value := iface.(type) {
+ case *Node:
+ e.nodev(in)
+ return
+ case Node:
+ if !in.CanAddr() {
+ var n = reflect.New(in.Type()).Elem()
+ n.Set(in)
+ in = n
+ }
+ e.nodev(in.Addr())
+ return
+ case time.Time:
+ e.timev(tag, in)
+ return
+ case *time.Time:
+ e.timev(tag, in.Elem())
+ return
+ case time.Duration:
+ e.stringv(tag, reflect.ValueOf(value.String()))
+ return
+ case Marshaler:
+ v, err := value.MarshalYAML()
+ if err != nil {
+ fail(err)
+ }
+ if v == nil {
+ e.nilv()
+ return
+ }
+ e.marshal(tag, reflect.ValueOf(v))
+ return
+ case encoding.TextMarshaler:
+ text, err := value.MarshalText()
+ if err != nil {
+ fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ e.marshal(tag, in.Elem())
+ case reflect.Map:
+ e.mapv(tag, in)
+ case reflect.Ptr:
+ e.marshal(tag, in.Elem())
+ case reflect.Struct:
+ e.structv(tag, in)
+ case reflect.Slice, reflect.Array:
+ e.slicev(tag, in)
+ case reflect.String:
+ e.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ e.intv(tag, in)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ e.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ e.floatv(tag, in)
+ case reflect.Bool:
+ e.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ e.marshal("", k)
+ e.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ e.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = e.fieldByIndex(in, info.Inline)
+ if !value.IsValid() {
+ continue
+ }
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ e.marshal("", reflect.ValueOf(info.Key))
+ e.flow = info.Flow
+ e.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ e.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+ }
+ e.marshal("", k)
+ e.flow = false
+ e.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := yaml_BLOCK_MAPPING_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+ e.emit()
+ f()
+ yaml_mapping_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ e.emit()
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ e.marshal("", in.Index(i))
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshalled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+ switch s {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+ "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ return true
+ default:
+ return false
+ }
+}
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+ var style yaml_scalar_style_t
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when encoded unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ if e.flow {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ } else {
+ style = yaml_LITERAL_SCALAR_STYLE
+ }
+ case canUsePlain:
+ style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) nilv() {
+ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
+ // TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+ implicit := tag == ""
+ if !implicit {
+ tag = longTag(tag)
+ }
+ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+ e.event.head_comment = head
+ e.event.line_comment = line
+ e.event.foot_comment = foot
+ e.event.tail_comment = tail
+ e.emit()
+}
+
+func (e *encoder) nodev(in reflect.Value) {
+ e.node(in.Interface().(*Node), "")
+}
+
+func (e *encoder) node(node *Node, tail string) {
+ // Zero nodes behave as nil.
+ if node.Kind == 0 && node.IsZero() {
+ e.nilv()
+ return
+ }
+
+ // If the tag was not explicitly requested, and dropping it won't change the
+ // implicit tag of the value, don't include it in the presentation.
+ var tag = node.Tag
+ var stag = shortTag(tag)
+ var forceQuoting bool
+ if tag != "" && node.Style&TaggedStyle == 0 {
+ if node.Kind == ScalarNode {
+ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+ tag = ""
+ } else {
+ rtag, _ := resolve("", node.Value)
+ if rtag == stag {
+ tag = ""
+ } else if stag == strTag {
+ tag = ""
+ forceQuoting = true
+ }
+ }
+ } else {
+ var rtag string
+ switch node.Kind {
+ case MappingNode:
+ rtag = mapTag
+ case SequenceNode:
+ rtag = seqTag
+ }
+ if rtag == stag {
+ tag = ""
+ }
+ }
+ }
+
+ switch node.Kind {
+ case DocumentNode:
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ yaml_document_end_event_initialize(&e.event, true)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case SequenceNode:
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case MappingNode:
+ style := yaml_BLOCK_MAPPING_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+ e.event.tail_comment = []byte(tail)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+
+ // The tail logic below moves the foot comment of prior keys to the following key,
+ // since the value for each key may be a nested structure and the foot needs to be
+ // processed only the entirety of the value is streamed. The last tail is processed
+ // with the mapping end event.
+ var tail string
+ for i := 0; i+1 < len(node.Content); i += 2 {
+ k := node.Content[i]
+ foot := k.FootComment
+ if foot != "" {
+ kopy := *k
+ kopy.FootComment = ""
+ k = &kopy
+ }
+ e.node(k, tail)
+ tail = foot
+
+ v := node.Content[i+1]
+ e.node(v, "")
+ }
+
+ yaml_mapping_end_event_initialize(&e.event)
+ e.event.tail_comment = []byte(tail)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case AliasNode:
+ yaml_alias_event_initialize(&e.event, []byte(node.Value))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case ScalarNode:
+ value := node.Value
+ if !utf8.ValidString(value) {
+ if stag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if stag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", stag)
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ value = encodeBase64(value)
+ }
+
+ style := yaml_PLAIN_SCALAR_STYLE
+ switch {
+ case node.Style&DoubleQuotedStyle != 0:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ case node.Style&SingleQuotedStyle != 0:
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ case node.Style&LiteralStyle != 0:
+ style = yaml_LITERAL_SCALAR_STYLE
+ case node.Style&FoldedStyle != 0:
+ style = yaml_FOLDED_SCALAR_STYLE
+ case strings.Contains(value, "\n"):
+ style = yaml_LITERAL_SCALAR_STYLE
+ case forceQuoting:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+ default:
+ failf("cannot encode node with unknown kind %d", node.Kind)
+ }
+}
diff --git a/vendor/gopkg.in/yaml.v3/parserc.go b/vendor/gopkg.in/yaml.v3/parserc.go
new file mode 100644
index 0000000..ac66fcc
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/parserc.go
@@ -0,0 +1,1249 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+)
+
+// The parser implements the following grammar:
+//
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// implicit_document ::= block_node DOCUMENT-END*
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// | properties (block_content | indentless_block_sequence)?
+// | block_content
+// | indentless_block_sequence
+// block_node ::= ALIAS
+// | properties block_content?
+// | block_content
+// flow_node ::= ALIAS
+// | properties flow_content?
+// | flow_content
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// block_content ::= block_collection | flow_collection | SCALAR
+// flow_content ::= flow_collection | SCALAR
+// block_collection ::= block_sequence | block_mapping
+// flow_collection ::= flow_sequence | flow_mapping
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// block_mapping ::= BLOCK-MAPPING_START
+// ((KEY block_node_or_indentless_sequence?)?
+// (VALUE block_node_or_indentless_sequence?)?)*
+// BLOCK-END
+// flow_sequence ::= FLOW-SEQUENCE-START
+// (flow_sequence_entry FLOW-ENTRY)*
+// flow_sequence_entry?
+// FLOW-SEQUENCE-END
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// flow_mapping ::= FLOW-MAPPING-START
+// (flow_mapping_entry FLOW-ENTRY)*
+// flow_mapping_entry?
+// FLOW-MAPPING-END
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+
+// Peek the next token in the token queue.
+func peek_token(parser *yaml_parser_t) *yaml_token_t {
+ if parser.token_available || yaml_parser_fetch_more_tokens(parser) {
+ token := &parser.tokens[parser.tokens_head]
+ yaml_parser_unfold_comments(parser, token)
+ return token
+ }
+ return nil
+}
+
+// yaml_parser_unfold_comments walks through the comments queue and joins all
+// comments behind the position of the provided token into the respective
+// top-level comment slices in the parser.
+func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) {
+ for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index {
+ comment := &parser.comments[parser.comments_head]
+ if len(comment.head) > 0 {
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ // No heads on ends, so keep comment.head for a follow up token.
+ break
+ }
+ if len(parser.head_comment) > 0 {
+ parser.head_comment = append(parser.head_comment, '\n')
+ }
+ parser.head_comment = append(parser.head_comment, comment.head...)
+ }
+ if len(comment.foot) > 0 {
+ if len(parser.foot_comment) > 0 {
+ parser.foot_comment = append(parser.foot_comment, '\n')
+ }
+ parser.foot_comment = append(parser.foot_comment, comment.foot...)
+ }
+ if len(comment.line) > 0 {
+ if len(parser.line_comment) > 0 {
+ parser.line_comment = append(parser.line_comment, '\n')
+ }
+ parser.line_comment = append(parser.line_comment, comment.line...)
+ }
+ *comment = yaml_comment_t{}
+ parser.comments_head++
+ }
+}
+
+// Remove the next token from the queue (must be called after peek_token).
+func skip_token(parser *yaml_parser_t) {
+ parser.token_available = false
+ parser.tokens_parsed++
+ parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN
+ parser.tokens_head++
+}
+
+// Get the next event.
+func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
+ // Erase the event object.
+ *event = yaml_event_t{}
+
+ // No events after the end of the stream or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE {
+ return true
+ }
+
+ // Generate the next event.
+ return yaml_parser_state_machine(parser, event)
+}
+
+// Set parser error.
+func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool {
+ parser.error = yaml_PARSER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = problem_mark
+ return false
+}
+
+// State dispatcher.
+func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool {
+ //trace("yaml_parser_state_machine", "state:", parser.state.String())
+
+ switch parser.state {
+ case yaml_PARSE_STREAM_START_STATE:
+ return yaml_parser_parse_stream_start(parser, event)
+
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, true)
+
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return yaml_parser_parse_document_start(parser, event, false)
+
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return yaml_parser_parse_document_content(parser, event)
+
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return yaml_parser_parse_document_end(parser, event)
+
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, true, false)
+
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return yaml_parser_parse_node(parser, event, true, true)
+
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return yaml_parser_parse_node(parser, event, false, false)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_block_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_indentless_sequence_entry(parser, event)
+
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, true)
+
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return yaml_parser_parse_block_mapping_key(parser, event, false)
+
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_block_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, true)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return yaml_parser_parse_flow_sequence_entry(parser, event, false)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event)
+
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event)
+
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, true)
+
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return yaml_parser_parse_flow_mapping_key(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, false)
+
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return yaml_parser_parse_flow_mapping_value(parser, event, true)
+
+ default:
+ panic("invalid parser state")
+ }
+}
+
+// Parse the production:
+// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
+// ************
+func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_STREAM_START_TOKEN {
+ return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark)
+ }
+ parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ encoding: token.encoding,
+ }
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// *************************
+func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ // Parse extra document end indicators.
+ if !implicit {
+ for token.typ == yaml_DOCUMENT_END_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN &&
+ token.typ != yaml_TAG_DIRECTIVE_TOKEN &&
+ token.typ != yaml_DOCUMENT_START_TOKEN &&
+ token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an implicit document.
+ if !yaml_parser_process_directives(parser, nil, nil) {
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_BLOCK_NODE_STATE
+
+ var head_comment []byte
+ if len(parser.head_comment) > 0 {
+ // [Go] Scan the header comment backwards, and if an empty line is found, break
+ // the header so the part before the last empty line goes into the
+ // document header, while the bottom of it goes into a follow up event.
+ for i := len(parser.head_comment) - 1; i > 0; i-- {
+ if parser.head_comment[i] == '\n' {
+ if i == len(parser.head_comment)-1 {
+ head_comment = parser.head_comment[:i]
+ parser.head_comment = parser.head_comment[i+1:]
+ break
+ } else if parser.head_comment[i-1] == '\n' {
+ head_comment = parser.head_comment[:i-1]
+ parser.head_comment = parser.head_comment[i+1:]
+ break
+ }
+ }
+ }
+ }
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+
+ head_comment: head_comment,
+ }
+
+ } else if token.typ != yaml_STREAM_END_TOKEN {
+ // Parse an explicit document.
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+ start_mark := token.start_mark
+ if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) {
+ return false
+ }
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_DOCUMENT_START_TOKEN {
+ yaml_parser_set_parser_error(parser,
+ "did not find expected ", token.start_mark)
+ return false
+ }
+ parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE)
+ parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE
+ end_mark := token.end_mark
+
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: false,
+ }
+ skip_token(parser)
+
+ } else {
+ // Parse the stream end.
+ parser.state = yaml_PARSE_END_STATE
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ skip_token(parser)
+ }
+
+ return true
+}
+
+// Parse the productions:
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+// ***********
+//
+func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN ||
+ token.typ == yaml_TAG_DIRECTIVE_TOKEN ||
+ token.typ == yaml_DOCUMENT_START_TOKEN ||
+ token.typ == yaml_DOCUMENT_END_TOKEN ||
+ token.typ == yaml_STREAM_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ return yaml_parser_process_empty_scalar(parser, event,
+ token.start_mark)
+ }
+ return yaml_parser_parse_node(parser, event, true, false)
+}
+
+// Parse the productions:
+// implicit_document ::= block_node DOCUMENT-END*
+// *************
+// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
+//
+func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ implicit := true
+ if token.typ == yaml_DOCUMENT_END_TOKEN {
+ end_mark = token.end_mark
+ skip_token(parser)
+ implicit = false
+ }
+
+ parser.tag_directives = parser.tag_directives[:0]
+
+ parser.state = yaml_PARSE_DOCUMENT_START_STATE
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ implicit: implicit,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ if len(event.head_comment) > 0 && len(event.foot_comment) == 0 {
+ event.foot_comment = event.head_comment
+ event.head_comment = nil
+ }
+ return true
+}
+
+func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) {
+ event.head_comment = parser.head_comment
+ event.line_comment = parser.line_comment
+ event.foot_comment = parser.foot_comment
+ parser.head_comment = nil
+ parser.line_comment = nil
+ parser.foot_comment = nil
+ parser.tail_comment = nil
+ parser.stem_comment = nil
+}
+
+// Parse the productions:
+// block_node_or_indentless_sequence ::=
+// ALIAS
+// *****
+// | properties (block_content | indentless_block_sequence)?
+// ********** *
+// | block_content | indentless_block_sequence
+// *
+// block_node ::= ALIAS
+// *****
+// | properties block_content?
+// ********** *
+// | block_content
+// *
+// flow_node ::= ALIAS
+// *****
+// | properties flow_content?
+// ********** *
+// | flow_content
+// *
+// properties ::= TAG ANCHOR? | ANCHOR TAG?
+// *************************
+// block_content ::= block_collection | flow_collection | SCALAR
+// ******
+// flow_content ::= flow_collection | SCALAR
+// ******
+func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
+ //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_ALIAS_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ anchor: token.value,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+ }
+
+ start_mark := token.start_mark
+ end_mark := token.start_mark
+
+ var tag_token bool
+ var tag_handle, tag_suffix, anchor []byte
+ var tag_mark yaml_mark_t
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ start_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ } else if token.typ == yaml_TAG_TOKEN {
+ tag_token = true
+ tag_handle = token.value
+ tag_suffix = token.suffix
+ start_mark = token.start_mark
+ tag_mark = token.start_mark
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_ANCHOR_TOKEN {
+ anchor = token.value
+ end_mark = token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+ }
+
+ var tag []byte
+ if tag_token {
+ if len(tag_handle) == 0 {
+ tag = tag_suffix
+ tag_suffix = nil
+ } else {
+ for i := range parser.tag_directives {
+ if bytes.Equal(parser.tag_directives[i].handle, tag_handle) {
+ tag = append([]byte(nil), parser.tag_directives[i].prefix...)
+ tag = append(tag, tag_suffix...)
+ break
+ }
+ }
+ if len(tag) == 0 {
+ yaml_parser_set_parser_error_context(parser,
+ "while parsing a node", start_mark,
+ "found undefined tag handle", tag_mark)
+ return false
+ }
+ }
+ }
+
+ implicit := len(tag) == 0
+ if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ return true
+ }
+ if token.typ == yaml_SCALAR_TOKEN {
+ var plain_implicit, quoted_implicit bool
+ end_mark = token.end_mark
+ if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') {
+ plain_implicit = true
+ } else if len(tag) == 0 {
+ quoted_implicit = true
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ value: token.value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(token.style),
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+ }
+ if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN {
+ // [Go] Some of the events below can be merged as they differ only on style.
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE),
+ }
+ yaml_parser_set_event_comments(parser, event)
+ return true
+ }
+ if token.typ == yaml_FLOW_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ yaml_parser_set_event_comments(parser, event)
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE),
+ }
+ if parser.stem_comment != nil {
+ event.head_comment = parser.stem_comment
+ parser.stem_comment = nil
+ }
+ return true
+ }
+ if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN {
+ end_mark = token.end_mark
+ parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE),
+ }
+ if parser.stem_comment != nil {
+ event.head_comment = parser.stem_comment
+ parser.stem_comment = nil
+ }
+ return true
+ }
+ if len(anchor) > 0 || len(tag) > 0 {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ quoted_implicit: false,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+ }
+
+ context := "while parsing a flow node"
+ if block {
+ context = "while parsing a block node"
+ }
+ yaml_parser_set_parser_error_context(parser, context, start_mark,
+ "did not find expected node content", token.start_mark)
+ return false
+}
+
+// Parse the productions:
+// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
+// ******************** *********** * *********
+//
+func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ prior_head_len := len(parser.head_comment)
+ skip_token(parser)
+ yaml_parser_split_stem_comment(parser, prior_head_len)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ }
+ if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block collection", context_mark,
+ "did not find expected '-' indicator", token.start_mark)
+}
+
+// Parse the productions:
+// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
+// *********** *
+func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ == yaml_BLOCK_ENTRY_TOKEN {
+ mark := token.end_mark
+ prior_head_len := len(parser.head_comment)
+ skip_token(parser)
+ yaml_parser_split_stem_comment(parser, prior_head_len)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_BLOCK_ENTRY_TOKEN &&
+ token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, true, false)
+ }
+ parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark?
+ }
+ return true
+}
+
+// Split stem comment from head comment.
+//
+// When a sequence or map is found under a sequence entry, the former head comment
+// is assigned to the underlying sequence or map as a whole, not the individual
+// sequence or map entry as would be expected otherwise. To handle this case the
+// previous head comment is moved aside as the stem comment.
+func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
+ if stem_len == 0 {
+ return
+ }
+
+ token := peek_token(parser)
+ if token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN {
+ return
+ }
+
+ parser.stem_comment = parser.head_comment[:stem_len]
+ if len(parser.head_comment) == stem_len {
+ parser.head_comment = nil
+ } else {
+ // Copy suffix to prevent very strange bugs if someone ever appends
+ // further bytes to the prefix in the stem_comment slice above.
+ parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...)
+ }
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+// *******************
+// ((KEY block_node_or_indentless_sequence?)?
+// *** *
+// (VALUE block_node_or_indentless_sequence?)?)*
+//
+// BLOCK-END
+// *********
+//
+func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ // [Go] A tail comment was left from the prior mapping value processed. Emit an event
+ // as it needs to be processed with that value and not the following key.
+ if len(parser.tail_comment) > 0 {
+ *event = yaml_event_t{
+ typ: yaml_TAIL_COMMENT_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ foot_comment: parser.tail_comment,
+ }
+ parser.tail_comment = nil
+ return true
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ } else {
+ parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ } else if token.typ == yaml_BLOCK_END_TOKEN {
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+ }
+
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a block mapping", context_mark,
+ "did not find expected key", token.start_mark)
+}
+
+// Parse the productions:
+// block_mapping ::= BLOCK-MAPPING_START
+//
+// ((KEY block_node_or_indentless_sequence?)?
+//
+// (VALUE block_node_or_indentless_sequence?)?)*
+// ***** *
+// BLOCK-END
+//
+//
+func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ mark := token.end_mark
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_KEY_TOKEN &&
+ token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_BLOCK_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, true, true)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+ }
+ parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence ::= FLOW-SEQUENCE-START
+// *******************
+// (flow_sequence_entry FLOW-ENTRY)*
+// * **********
+// flow_sequence_entry?
+// *
+// FLOW-SEQUENCE-END
+// *****************
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow sequence", context_mark,
+ "did not find expected ',' or ']'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ implicit: true,
+ style: yaml_style_t(yaml_FLOW_MAPPING_STYLE),
+ }
+ skip_token(parser)
+ return true
+ } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ yaml_parser_set_event_comments(parser, event)
+
+ skip_token(parser)
+ return true
+}
+
+//
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ mark := token.end_mark
+ skip_token(parser)
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// ***** *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Parse the productions:
+// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// *
+//
+func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.start_mark, // [Go] Shouldn't this be end_mark?
+ }
+ return true
+}
+
+// Parse the productions:
+// flow_mapping ::= FLOW-MAPPING-START
+// ******************
+// (flow_mapping_entry FLOW-ENTRY)*
+// * **********
+// flow_mapping_entry?
+// ******************
+// FLOW-MAPPING-END
+// ****************
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * *** *
+//
+func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
+ if first {
+ token := peek_token(parser)
+ parser.marks = append(parser.marks, token.start_mark)
+ skip_token(parser)
+ }
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ if !first {
+ if token.typ == yaml_FLOW_ENTRY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ } else {
+ context_mark := parser.marks[len(parser.marks)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ return yaml_parser_set_parser_error_context(parser,
+ "while parsing a flow mapping", context_mark,
+ "did not find expected ',' or '}'", token.start_mark)
+ }
+ }
+
+ if token.typ == yaml_KEY_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_VALUE_TOKEN &&
+ token.typ != yaml_FLOW_ENTRY_TOKEN &&
+ token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ } else {
+ parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+
+ parser.state = parser.states[len(parser.states)-1]
+ parser.states = parser.states[:len(parser.states)-1]
+ parser.marks = parser.marks[:len(parser.marks)-1]
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ start_mark: token.start_mark,
+ end_mark: token.end_mark,
+ }
+ yaml_parser_set_event_comments(parser, event)
+ skip_token(parser)
+ return true
+}
+
+// Parse the productions:
+// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
+// * ***** *
+//
+func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if empty {
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+ }
+ if token.typ == yaml_VALUE_TOKEN {
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN {
+ parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE)
+ return yaml_parser_parse_node(parser, event, false, false)
+ }
+ }
+ parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE
+ return yaml_parser_process_empty_scalar(parser, event, token.start_mark)
+}
+
+// Generate an empty scalar event.
+func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ start_mark: mark,
+ end_mark: mark,
+ value: nil, // Empty
+ implicit: true,
+ style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE),
+ }
+ return true
+}
+
+var default_tag_directives = []yaml_tag_directive_t{
+ {[]byte("!"), []byte("!")},
+ {[]byte("!!"), []byte("tag:yaml.org,2002:")},
+}
+
+// Parse directives.
+func yaml_parser_process_directives(parser *yaml_parser_t,
+ version_directive_ref **yaml_version_directive_t,
+ tag_directives_ref *[]yaml_tag_directive_t) bool {
+
+ var version_directive *yaml_version_directive_t
+ var tag_directives []yaml_tag_directive_t
+
+ token := peek_token(parser)
+ if token == nil {
+ return false
+ }
+
+ for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ if token.typ == yaml_VERSION_DIRECTIVE_TOKEN {
+ if version_directive != nil {
+ yaml_parser_set_parser_error(parser,
+ "found duplicate %YAML directive", token.start_mark)
+ return false
+ }
+ if token.major != 1 || token.minor != 1 {
+ yaml_parser_set_parser_error(parser,
+ "found incompatible YAML document", token.start_mark)
+ return false
+ }
+ version_directive = &yaml_version_directive_t{
+ major: token.major,
+ minor: token.minor,
+ }
+ } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN {
+ value := yaml_tag_directive_t{
+ handle: token.value,
+ prefix: token.prefix,
+ }
+ if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) {
+ return false
+ }
+ tag_directives = append(tag_directives, value)
+ }
+
+ skip_token(parser)
+ token = peek_token(parser)
+ if token == nil {
+ return false
+ }
+ }
+
+ for i := range default_tag_directives {
+ if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) {
+ return false
+ }
+ }
+
+ if version_directive_ref != nil {
+ *version_directive_ref = version_directive
+ }
+ if tag_directives_ref != nil {
+ *tag_directives_ref = tag_directives
+ }
+ return true
+}
+
+// Append a tag directive to the directives stack.
+func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool {
+ for i := range parser.tag_directives {
+ if bytes.Equal(value.handle, parser.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark)
+ }
+ }
+
+ // [Go] I suspect the copy is unnecessary. This was likely done
+ // because there was no way to track ownership of the data.
+ value_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(value_copy.handle, value.handle)
+ copy(value_copy.prefix, value.prefix)
+ parser.tag_directives = append(parser.tag_directives, value_copy)
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/readerc.go b/vendor/gopkg.in/yaml.v3/readerc.go
new file mode 100644
index 0000000..b7de0a8
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/readerc.go
@@ -0,0 +1,434 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "io"
+)
+
+// Set the reader error and return 0.
+func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
+ parser.error = yaml_READER_ERROR
+ parser.problem = problem
+ parser.problem_offset = offset
+ parser.problem_value = value
+ return false
+}
+
+// Byte order marks.
+const (
+ bom_UTF8 = "\xef\xbb\xbf"
+ bom_UTF16LE = "\xff\xfe"
+ bom_UTF16BE = "\xfe\xff"
+)
+
+// Determine the input stream encoding by checking the BOM symbol. If no BOM is
+// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
+func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
+ // Ensure that we had enough bytes in the raw buffer.
+ for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
+ if !yaml_parser_update_raw_buffer(parser) {
+ return false
+ }
+ }
+
+ // Determine the encoding.
+ buf := parser.raw_buffer
+ pos := parser.raw_buffer_pos
+ avail := len(buf) - pos
+ if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
+ parser.encoding = yaml_UTF16LE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
+ parser.encoding = yaml_UTF16BE_ENCODING
+ parser.raw_buffer_pos += 2
+ parser.offset += 2
+ } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
+ parser.encoding = yaml_UTF8_ENCODING
+ parser.raw_buffer_pos += 3
+ parser.offset += 3
+ } else {
+ parser.encoding = yaml_UTF8_ENCODING
+ }
+ return true
+}
+
+// Update the raw buffer.
+func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
+ size_read := 0
+
+ // Return if the raw buffer is full.
+ if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
+ return true
+ }
+
+ // Return on EOF.
+ if parser.eof {
+ return true
+ }
+
+ // Move the remaining bytes in the raw buffer to the beginning.
+ if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
+ copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
+ }
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
+ parser.raw_buffer_pos = 0
+
+ // Call the read handler to fill the buffer.
+ size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
+ parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
+ if err == io.EOF {
+ parser.eof = true
+ } else if err != nil {
+ return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
+ }
+ return true
+}
+
+// Ensure that the buffer contains at least `length` characters.
+// Return true on success, false on failure.
+//
+// The length is supposed to be significantly less that the buffer size.
+func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
+ if parser.read_handler == nil {
+ panic("read handler must be set")
+ }
+
+ // [Go] This function was changed to guarantee the requested length size at EOF.
+ // The fact we need to do this is pretty awful, but the description above implies
+ // for that to be the case, and there are tests
+
+ // If the EOF flag is set and the raw buffer is empty, do nothing.
+ if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
+ // [Go] ACTUALLY! Read the documentation of this function above.
+ // This is just broken. To return true, we need to have the
+ // given length in the buffer. Not doing that means every single
+ // check that calls this function to make sure the buffer has a
+ // given length is Go) panicking; or C) accessing invalid memory.
+ //return true
+ }
+
+ // Return if the buffer contains enough characters.
+ if parser.unread >= length {
+ return true
+ }
+
+ // Determine the input encoding if it is not known yet.
+ if parser.encoding == yaml_ANY_ENCODING {
+ if !yaml_parser_determine_encoding(parser) {
+ return false
+ }
+ }
+
+ // Move the unread characters to the beginning of the buffer.
+ buffer_len := len(parser.buffer)
+ if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
+ copy(parser.buffer, parser.buffer[parser.buffer_pos:])
+ buffer_len -= parser.buffer_pos
+ parser.buffer_pos = 0
+ } else if parser.buffer_pos == buffer_len {
+ buffer_len = 0
+ parser.buffer_pos = 0
+ }
+
+ // Open the whole buffer for writing, and cut it before returning.
+ parser.buffer = parser.buffer[:cap(parser.buffer)]
+
+ // Fill the buffer until it has enough characters.
+ first := true
+ for parser.unread < length {
+
+ // Fill the raw buffer if necessary.
+ if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
+ if !yaml_parser_update_raw_buffer(parser) {
+ parser.buffer = parser.buffer[:buffer_len]
+ return false
+ }
+ }
+ first = false
+
+ // Decode the raw buffer.
+ inner:
+ for parser.raw_buffer_pos != len(parser.raw_buffer) {
+ var value rune
+ var width int
+
+ raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
+
+ // Decode the next character.
+ switch parser.encoding {
+ case yaml_UTF8_ENCODING:
+ // Decode a UTF-8 character. Check RFC 3629
+ // (http://www.ietf.org/rfc/rfc3629.txt) for more details.
+ //
+ // The following table (taken from the RFC) is used for
+ // decoding.
+ //
+ // Char. number range | UTF-8 octet sequence
+ // (hexadecimal) | (binary)
+ // --------------------+------------------------------------
+ // 0000 0000-0000 007F | 0xxxxxxx
+ // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+ // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+ // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ //
+ // Additionally, the characters in the range 0xD800-0xDFFF
+ // are prohibited as they are reserved for use with UTF-16
+ // surrogate pairs.
+
+ // Determine the length of the UTF-8 sequence.
+ octet := parser.raw_buffer[parser.raw_buffer_pos]
+ switch {
+ case octet&0x80 == 0x00:
+ width = 1
+ case octet&0xE0 == 0xC0:
+ width = 2
+ case octet&0xF0 == 0xE0:
+ width = 3
+ case octet&0xF8 == 0xF0:
+ width = 4
+ default:
+ // The leading octet is invalid.
+ return yaml_parser_set_reader_error(parser,
+ "invalid leading UTF-8 octet",
+ parser.offset, int(octet))
+ }
+
+ // Check if the raw buffer contains an incomplete character.
+ if width > raw_unread {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-8 octet sequence",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Decode the leading octet.
+ switch {
+ case octet&0x80 == 0x00:
+ value = rune(octet & 0x7F)
+ case octet&0xE0 == 0xC0:
+ value = rune(octet & 0x1F)
+ case octet&0xF0 == 0xE0:
+ value = rune(octet & 0x0F)
+ case octet&0xF8 == 0xF0:
+ value = rune(octet & 0x07)
+ default:
+ value = 0
+ }
+
+ // Check and decode the trailing octets.
+ for k := 1; k < width; k++ {
+ octet = parser.raw_buffer[parser.raw_buffer_pos+k]
+
+ // Check if the octet is valid.
+ if (octet & 0xC0) != 0x80 {
+ return yaml_parser_set_reader_error(parser,
+ "invalid trailing UTF-8 octet",
+ parser.offset+k, int(octet))
+ }
+
+ // Decode the octet.
+ value = (value << 6) + rune(octet&0x3F)
+ }
+
+ // Check the length of the sequence against the value.
+ switch {
+ case width == 1:
+ case width == 2 && value >= 0x80:
+ case width == 3 && value >= 0x800:
+ case width == 4 && value >= 0x10000:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "invalid length of a UTF-8 sequence",
+ parser.offset, -1)
+ }
+
+ // Check the range of the value.
+ if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
+ return yaml_parser_set_reader_error(parser,
+ "invalid Unicode character",
+ parser.offset, int(value))
+ }
+
+ case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
+ var low, high int
+ if parser.encoding == yaml_UTF16LE_ENCODING {
+ low, high = 0, 1
+ } else {
+ low, high = 1, 0
+ }
+
+ // The UTF-16 encoding is not as simple as one might
+ // naively think. Check RFC 2781
+ // (http://www.ietf.org/rfc/rfc2781.txt).
+ //
+ // Normally, two subsequent bytes describe a Unicode
+ // character. However a special technique (called a
+ // surrogate pair) is used for specifying character
+ // values larger than 0xFFFF.
+ //
+ // A surrogate pair consists of two pseudo-characters:
+ // high surrogate area (0xD800-0xDBFF)
+ // low surrogate area (0xDC00-0xDFFF)
+ //
+ // The following formulas are used for decoding
+ // and encoding characters using surrogate pairs:
+ //
+ // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
+ // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
+ // W1 = 110110yyyyyyyyyy
+ // W2 = 110111xxxxxxxxxx
+ //
+ // where U is the character value, W1 is the high surrogate
+ // area, W2 is the low surrogate area.
+
+ // Check for incomplete UTF-16 character.
+ if raw_unread < 2 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 character",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the character.
+ value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
+
+ // Check for unexpected low surrogate area.
+ if value&0xFC00 == 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "unexpected low surrogate area",
+ parser.offset, int(value))
+ }
+
+ // Check for a high surrogate area.
+ if value&0xFC00 == 0xD800 {
+ width = 4
+
+ // Check for incomplete surrogate pair.
+ if raw_unread < 4 {
+ if parser.eof {
+ return yaml_parser_set_reader_error(parser,
+ "incomplete UTF-16 surrogate pair",
+ parser.offset, -1)
+ }
+ break inner
+ }
+
+ // Get the next character.
+ value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
+ (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
+
+ // Check for a low surrogate area.
+ if value2&0xFC00 != 0xDC00 {
+ return yaml_parser_set_reader_error(parser,
+ "expected low surrogate area",
+ parser.offset+2, int(value2))
+ }
+
+ // Generate the value of the surrogate pair.
+ value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
+ } else {
+ width = 2
+ }
+
+ default:
+ panic("impossible")
+ }
+
+ // Check if the character is in the allowed range:
+ // #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
+ // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
+ // | [#x10000-#x10FFFF] (32 bit)
+ switch {
+ case value == 0x09:
+ case value == 0x0A:
+ case value == 0x0D:
+ case value >= 0x20 && value <= 0x7E:
+ case value == 0x85:
+ case value >= 0xA0 && value <= 0xD7FF:
+ case value >= 0xE000 && value <= 0xFFFD:
+ case value >= 0x10000 && value <= 0x10FFFF:
+ default:
+ return yaml_parser_set_reader_error(parser,
+ "control characters are not allowed",
+ parser.offset, int(value))
+ }
+
+ // Move the raw pointers.
+ parser.raw_buffer_pos += width
+ parser.offset += width
+
+ // Finally put the character into the buffer.
+ if value <= 0x7F {
+ // 0000 0000-0000 007F . 0xxxxxxx
+ parser.buffer[buffer_len+0] = byte(value)
+ buffer_len += 1
+ } else if value <= 0x7FF {
+ // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
+ parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
+ buffer_len += 2
+ } else if value <= 0xFFFF {
+ // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
+ buffer_len += 3
+ } else {
+ // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
+ parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
+ parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
+ parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
+ buffer_len += 4
+ }
+
+ parser.unread++
+ }
+
+ // On EOF, put NUL into the buffer and return.
+ if parser.eof {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ parser.unread++
+ break
+ }
+ }
+ // [Go] Read the documentation of this function above. To return true,
+ // we need to have the given length in the buffer. Not doing that means
+ // every single check that calls this function to make sure the buffer
+ // has a given length is Go) panicking; or C) accessing invalid memory.
+ // This happens here due to the EOF above breaking early.
+ for buffer_len < length {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ }
+ parser.buffer = parser.buffer[:buffer_len]
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/resolve.go b/vendor/gopkg.in/yaml.v3/resolve.go
new file mode 100644
index 0000000..64ae888
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/resolve.go
@@ -0,0 +1,326 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "encoding/base64"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type resolveMapItem struct {
+ value interface{}
+ tag string
+}
+
+var resolveTable = make([]byte, 256)
+var resolveMap = make(map[string]resolveMapItem)
+
+func init() {
+ t := resolveTable
+ t[int('+')] = 'S' // Sign
+ t[int('-')] = 'S'
+ for _, c := range "0123456789" {
+ t[int(c)] = 'D' // Digit
+ }
+ for _, c := range "yYnNtTfFoO~" {
+ t[int(c)] = 'M' // In map
+ }
+ t[int('.')] = '.' // Float (potentially in map)
+
+ var resolveMapList = []struct {
+ v interface{}
+ tag string
+ l []string
+ }{
+ {true, boolTag, []string{"true", "True", "TRUE"}},
+ {false, boolTag, []string{"false", "False", "FALSE"}},
+ {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}},
+ {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}},
+ {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}},
+ {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}},
+ {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}},
+ {"<<", mergeTag, []string{"<<"}},
+ }
+
+ m := resolveMap
+ for _, item := range resolveMapList {
+ for _, s := range item.l {
+ m[s] = resolveMapItem{item.v, item.tag}
+ }
+ }
+}
+
+const (
+ nullTag = "!!null"
+ boolTag = "!!bool"
+ strTag = "!!str"
+ intTag = "!!int"
+ floatTag = "!!float"
+ timestampTag = "!!timestamp"
+ seqTag = "!!seq"
+ mapTag = "!!map"
+ binaryTag = "!!binary"
+ mergeTag = "!!merge"
+)
+
+var longTags = make(map[string]string)
+var shortTags = make(map[string]string)
+
+func init() {
+ for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} {
+ ltag := longTag(stag)
+ longTags[stag] = ltag
+ shortTags[ltag] = stag
+ }
+}
+
+const longTagPrefix = "tag:yaml.org,2002:"
+
+func shortTag(tag string) string {
+ if strings.HasPrefix(tag, longTagPrefix) {
+ if stag, ok := shortTags[tag]; ok {
+ return stag
+ }
+ return "!!" + tag[len(longTagPrefix):]
+ }
+ return tag
+}
+
+func longTag(tag string) string {
+ if strings.HasPrefix(tag, "!!") {
+ if ltag, ok := longTags[tag]; ok {
+ return ltag
+ }
+ return longTagPrefix + tag[2:]
+ }
+ return tag
+}
+
+func resolvableTag(tag string) bool {
+ switch tag {
+ case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag:
+ return true
+ }
+ return false
+}
+
+var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
+
+func resolve(tag string, in string) (rtag string, out interface{}) {
+ tag = shortTag(tag)
+ if !resolvableTag(tag) {
+ return tag, in
+ }
+
+ defer func() {
+ switch tag {
+ case "", rtag, strTag, binaryTag:
+ return
+ case floatTag:
+ if rtag == intTag {
+ switch v := out.(type) {
+ case int64:
+ rtag = floatTag
+ out = float64(v)
+ return
+ case int:
+ rtag = floatTag
+ out = float64(v)
+ return
+ }
+ }
+ }
+ failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+ }()
+
+ // Any data is accepted as a !!str or !!binary.
+ // Otherwise, the prefix is enough of a hint about what it might be.
+ hint := byte('N')
+ if in != "" {
+ hint = resolveTable[in[0]]
+ }
+ if hint != 0 && tag != strTag && tag != binaryTag {
+ // Handle things we can lookup in a map.
+ if item, ok := resolveMap[in]; ok {
+ return item.tag, item.value
+ }
+
+ // Base 60 floats are a bad idea, were dropped in YAML 1.2, and
+ // are purposefully unsupported here. They're still quoted on
+ // the way out for compatibility with other parser, though.
+
+ switch hint {
+ case 'M':
+ // We've already checked the map above.
+
+ case '.':
+ // Not in the map, so maybe a normal float.
+ floatv, err := strconv.ParseFloat(in, 64)
+ if err == nil {
+ return floatTag, floatv
+ }
+
+ case 'D', 'S':
+ // Int, float, or timestamp.
+ // Only try values as a timestamp if the value is unquoted or there's an explicit
+ // !!timestamp tag.
+ if tag == "" || tag == timestampTag {
+ t, ok := parseTimestamp(in)
+ if ok {
+ return timestampTag, t
+ }
+ }
+
+ plain := strings.Replace(in, "_", "", -1)
+ intv, err := strconv.ParseInt(plain, 0, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain, 0, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ if yamlStyleFloat.MatchString(plain) {
+ floatv, err := strconv.ParseFloat(plain, 64)
+ if err == nil {
+ return floatTag, floatv
+ }
+ }
+ if strings.HasPrefix(plain, "0b") {
+ intv, err := strconv.ParseInt(plain[2:], 2, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 2, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0b") {
+ intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ }
+ // Octals as introduced in version 1.2 of the spec.
+ // Octals from the 1.1 spec, spelled as 0777, are still
+ // decoded by default in v3 as well for compatibility.
+ // May be dropped in v4 depending on how usage evolves.
+ if strings.HasPrefix(plain, "0o") {
+ intv, err := strconv.ParseInt(plain[2:], 8, 64)
+ if err == nil {
+ if intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ uintv, err := strconv.ParseUint(plain[2:], 8, 64)
+ if err == nil {
+ return intTag, uintv
+ }
+ } else if strings.HasPrefix(plain, "-0o") {
+ intv, err := strconv.ParseInt("-"+plain[3:], 8, 64)
+ if err == nil {
+ if true || intv == int64(int(intv)) {
+ return intTag, int(intv)
+ } else {
+ return intTag, intv
+ }
+ }
+ }
+ default:
+ panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")")
+ }
+ }
+ return strTag, in
+}
+
+// encodeBase64 encodes s as base64 that is broken up into multiple lines
+// as appropriate for the resulting length.
+func encodeBase64(s string) string {
+ const lineLen = 70
+ encLen := base64.StdEncoding.EncodedLen(len(s))
+ lines := encLen/lineLen + 1
+ buf := make([]byte, encLen*2+lines)
+ in := buf[0:encLen]
+ out := buf[encLen:]
+ base64.StdEncoding.Encode(in, []byte(s))
+ k := 0
+ for i := 0; i < len(in); i += lineLen {
+ j := i + lineLen
+ if j > len(in) {
+ j = len(in)
+ }
+ k += copy(out[k:], in[i:j])
+ if lines > 1 {
+ out[k] = '\n'
+ k++
+ }
+ }
+ return string(out[:k])
+}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+ "2006-1-2 15:4:5.999999999", // space separated with no time zone
+ "2006-1-2", // date only
+ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+ // from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+ // TODO write code to check all the formats supported by
+ // http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+ // Quick check: all date formats start with YYYY-.
+ i := 0
+ for ; i < len(s); i++ {
+ if c := s[i]; c < '0' || c > '9' {
+ break
+ }
+ }
+ if i != 4 || i == len(s) || s[i] != '-' {
+ return time.Time{}, false
+ }
+ for _, format := range allowedTimestampFormats {
+ if t, err := time.Parse(format, s); err == nil {
+ return t, true
+ }
+ }
+ return time.Time{}, false
+}
diff --git a/vendor/gopkg.in/yaml.v3/scannerc.go b/vendor/gopkg.in/yaml.v3/scannerc.go
new file mode 100644
index 0000000..ca00701
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/scannerc.go
@@ -0,0 +1,3038 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Introduction
+// ************
+//
+// The following notes assume that you are familiar with the YAML specification
+// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in
+// some cases we are less restrictive that it requires.
+//
+// The process of transforming a YAML stream into a sequence of events is
+// divided on two steps: Scanning and Parsing.
+//
+// The Scanner transforms the input stream into a sequence of tokens, while the
+// parser transform the sequence of tokens produced by the Scanner into a
+// sequence of parsing events.
+//
+// The Scanner is rather clever and complicated. The Parser, on the contrary,
+// is a straightforward implementation of a recursive-descendant parser (or,
+// LL(1) parser, as it is usually called).
+//
+// Actually there are two issues of Scanning that might be called "clever", the
+// rest is quite straightforward. The issues are "block collection start" and
+// "simple keys". Both issues are explained below in details.
+//
+// Here the Scanning step is explained and implemented. We start with the list
+// of all the tokens produced by the Scanner together with short descriptions.
+//
+// Now, tokens:
+//
+// STREAM-START(encoding) # The stream start.
+// STREAM-END # The stream end.
+// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive.
+// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive.
+// DOCUMENT-START # '---'
+// DOCUMENT-END # '...'
+// BLOCK-SEQUENCE-START # Indentation increase denoting a block
+// BLOCK-MAPPING-START # sequence or a block mapping.
+// BLOCK-END # Indentation decrease.
+// FLOW-SEQUENCE-START # '['
+// FLOW-SEQUENCE-END # ']'
+// BLOCK-SEQUENCE-START # '{'
+// BLOCK-SEQUENCE-END # '}'
+// BLOCK-ENTRY # '-'
+// FLOW-ENTRY # ','
+// KEY # '?' or nothing (simple keys).
+// VALUE # ':'
+// ALIAS(anchor) # '*anchor'
+// ANCHOR(anchor) # '&anchor'
+// TAG(handle,suffix) # '!handle!suffix'
+// SCALAR(value,style) # A scalar.
+//
+// The following two tokens are "virtual" tokens denoting the beginning and the
+// end of the stream:
+//
+// STREAM-START(encoding)
+// STREAM-END
+//
+// We pass the information about the input stream encoding with the
+// STREAM-START token.
+//
+// The next two tokens are responsible for tags:
+//
+// VERSION-DIRECTIVE(major,minor)
+// TAG-DIRECTIVE(handle,prefix)
+//
+// Example:
+//
+// %YAML 1.1
+// %TAG ! !foo
+// %TAG !yaml! tag:yaml.org,2002:
+// ---
+//
+// The correspoding sequence of tokens:
+//
+// STREAM-START(utf-8)
+// VERSION-DIRECTIVE(1,1)
+// TAG-DIRECTIVE("!","!foo")
+// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
+// DOCUMENT-START
+// STREAM-END
+//
+// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
+// line.
+//
+// The document start and end indicators are represented by:
+//
+// DOCUMENT-START
+// DOCUMENT-END
+//
+// Note that if a YAML stream contains an implicit document (without '---'
+// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
+// produced.
+//
+// In the following examples, we present whole documents together with the
+// produced tokens.
+//
+// 1. An implicit document:
+//
+// 'a scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// STREAM-END
+//
+// 2. An explicit document:
+//
+// ---
+// 'a scalar'
+// ...
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-END
+// STREAM-END
+//
+// 3. Several documents in a stream:
+//
+// 'a scalar'
+// ---
+// 'another scalar'
+// ---
+// 'yet another scalar'
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// SCALAR("a scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("another scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("yet another scalar",single-quoted)
+// STREAM-END
+//
+// We have already introduced the SCALAR token above. The following tokens are
+// used to describe aliases, anchors, tag, and scalars:
+//
+// ALIAS(anchor)
+// ANCHOR(anchor)
+// TAG(handle,suffix)
+// SCALAR(value,style)
+//
+// The following series of examples illustrate the usage of these tokens:
+//
+// 1. A recursive sequence:
+//
+// &A [ *A ]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// ANCHOR("A")
+// FLOW-SEQUENCE-START
+// ALIAS("A")
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A tagged scalar:
+//
+// !!float "3.14" # A good approximation.
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// TAG("!!","float")
+// SCALAR("3.14",double-quoted)
+// STREAM-END
+//
+// 3. Various scalar styles:
+//
+// --- # Implicit empty plain scalars do not produce tokens.
+// --- a plain scalar
+// --- 'a single-quoted scalar'
+// --- "a double-quoted scalar"
+// --- |-
+// a literal scalar
+// --- >-
+// a folded
+// scalar
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// DOCUMENT-START
+// DOCUMENT-START
+// SCALAR("a plain scalar",plain)
+// DOCUMENT-START
+// SCALAR("a single-quoted scalar",single-quoted)
+// DOCUMENT-START
+// SCALAR("a double-quoted scalar",double-quoted)
+// DOCUMENT-START
+// SCALAR("a literal scalar",literal)
+// DOCUMENT-START
+// SCALAR("a folded scalar",folded)
+// STREAM-END
+//
+// Now it's time to review collection-related tokens. We will start with
+// flow collections:
+//
+// FLOW-SEQUENCE-START
+// FLOW-SEQUENCE-END
+// FLOW-MAPPING-START
+// FLOW-MAPPING-END
+// FLOW-ENTRY
+// KEY
+// VALUE
+//
+// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
+// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
+// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the
+// indicators '?' and ':', which are used for denoting mapping keys and values,
+// are represented by the KEY and VALUE tokens.
+//
+// The following examples show flow collections:
+//
+// 1. A flow sequence:
+//
+// [item 1, item 2, item 3]
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-SEQUENCE-START
+// SCALAR("item 1",plain)
+// FLOW-ENTRY
+// SCALAR("item 2",plain)
+// FLOW-ENTRY
+// SCALAR("item 3",plain)
+// FLOW-SEQUENCE-END
+// STREAM-END
+//
+// 2. A flow mapping:
+//
+// {
+// a simple key: a value, # Note that the KEY token is produced.
+// ? a complex key: another value,
+// }
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// FLOW-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// FLOW-ENTRY
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// FLOW-ENTRY
+// FLOW-MAPPING-END
+// STREAM-END
+//
+// A simple key is a key which is not denoted by the '?' indicator. Note that
+// the Scanner still produce the KEY token whenever it encounters a simple key.
+//
+// For scanning block collections, the following tokens are used (note that we
+// repeat KEY and VALUE here):
+//
+// BLOCK-SEQUENCE-START
+// BLOCK-MAPPING-START
+// BLOCK-END
+// BLOCK-ENTRY
+// KEY
+// VALUE
+//
+// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
+// increase that precedes a block collection (cf. the INDENT token in Python).
+// The token BLOCK-END denote indentation decrease that ends a block collection
+// (cf. the DEDENT token in Python). However YAML has some syntax pecularities
+// that makes detections of these tokens more complex.
+//
+// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
+// '-', '?', and ':' correspondingly.
+//
+// The following examples show how the tokens BLOCK-SEQUENCE-START,
+// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
+//
+// 1. Block sequences:
+//
+// - item 1
+// - item 2
+// -
+// - item 3.1
+// - item 3.2
+// -
+// key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 3.1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 3.2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Block mappings:
+//
+// a simple key: a value # The KEY token is produced here.
+// ? a complex key
+// : another value
+// a mapping:
+// key 1: value 1
+// key 2: value 2
+// a sequence:
+// - item 1
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a simple key",plain)
+// VALUE
+// SCALAR("a value",plain)
+// KEY
+// SCALAR("a complex key",plain)
+// VALUE
+// SCALAR("another value",plain)
+// KEY
+// SCALAR("a mapping",plain)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML does not always require to start a new block collection from a new
+// line. If the current line contains only '-', '?', and ':' indicators, a new
+// block collection may start at the current line. The following examples
+// illustrate this case:
+//
+// 1. Collections in a sequence:
+//
+// - - item 1
+// - item 2
+// - key 1: value 1
+// key 2: value 2
+// - ? complex key
+// : complex value
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-ENTRY
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("complex key")
+// VALUE
+// SCALAR("complex value")
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// 2. Collections in a mapping:
+//
+// ? a sequence
+// : - item 1
+// - item 2
+// ? a mapping
+// : key 1: value 1
+// key 2: value 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("a sequence",plain)
+// VALUE
+// BLOCK-SEQUENCE-START
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+// KEY
+// SCALAR("a mapping",plain)
+// VALUE
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key 1",plain)
+// VALUE
+// SCALAR("value 1",plain)
+// KEY
+// SCALAR("key 2",plain)
+// VALUE
+// SCALAR("value 2",plain)
+// BLOCK-END
+// BLOCK-END
+// STREAM-END
+//
+// YAML also permits non-indented sequences if they are included into a block
+// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced:
+//
+// key:
+// - item 1 # BLOCK-SEQUENCE-START is NOT produced here.
+// - item 2
+//
+// Tokens:
+//
+// STREAM-START(utf-8)
+// BLOCK-MAPPING-START
+// KEY
+// SCALAR("key",plain)
+// VALUE
+// BLOCK-ENTRY
+// SCALAR("item 1",plain)
+// BLOCK-ENTRY
+// SCALAR("item 2",plain)
+// BLOCK-END
+//
+
+// Ensure that the buffer contains the required number of characters.
+// Return true on success, false on failure (reader error or memory error).
+func cache(parser *yaml_parser_t, length int) bool {
+ // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B)
+ return parser.unread >= length || yaml_parser_update_buffer(parser, length)
+}
+
+// Advance the buffer pointer.
+func skip(parser *yaml_parser_t) {
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+}
+
+func skip_line(parser *yaml_parser_t) {
+ if is_crlf(parser.buffer, parser.buffer_pos) {
+ parser.mark.index += 2
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread -= 2
+ parser.buffer_pos += 2
+ parser.newlines++
+ } else if is_break(parser.buffer, parser.buffer_pos) {
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ parser.buffer_pos += width(parser.buffer[parser.buffer_pos])
+ parser.newlines++
+ }
+}
+
+// Copy a character to a string buffer and advance pointers.
+func read(parser *yaml_parser_t, s []byte) []byte {
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ parser.newlines = 0
+ }
+ w := width(parser.buffer[parser.buffer_pos])
+ if w == 0 {
+ panic("invalid character sequence")
+ }
+ if len(s) == 0 {
+ s = make([]byte, 0, 32)
+ }
+ if w == 1 && len(s)+w <= cap(s) {
+ s = s[:len(s)+1]
+ s[len(s)-1] = parser.buffer[parser.buffer_pos]
+ parser.buffer_pos++
+ } else {
+ s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...)
+ parser.buffer_pos += w
+ }
+ parser.mark.index++
+ parser.mark.column++
+ parser.unread--
+ return s
+}
+
+// Copy a line break character to a string buffer and advance pointers.
+func read_line(parser *yaml_parser_t, s []byte) []byte {
+ buf := parser.buffer
+ pos := parser.buffer_pos
+ switch {
+ case buf[pos] == '\r' && buf[pos+1] == '\n':
+ // CR LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ parser.mark.index++
+ parser.unread--
+ case buf[pos] == '\r' || buf[pos] == '\n':
+ // CR|LF . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 1
+ case buf[pos] == '\xC2' && buf[pos+1] == '\x85':
+ // NEL . LF
+ s = append(s, '\n')
+ parser.buffer_pos += 2
+ case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'):
+ // LS|PS . LS|PS
+ s = append(s, buf[parser.buffer_pos:pos+3]...)
+ parser.buffer_pos += 3
+ default:
+ return s
+ }
+ parser.mark.index++
+ parser.mark.column = 0
+ parser.mark.line++
+ parser.unread--
+ parser.newlines++
+ return s
+}
+
+// Get the next token.
+func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Erase the token object.
+ *token = yaml_token_t{} // [Go] Is this necessary?
+
+ // No tokens after STREAM-END or error.
+ if parser.stream_end_produced || parser.error != yaml_NO_ERROR {
+ return true
+ }
+
+ // Ensure that the tokens queue contains enough tokens.
+ if !parser.token_available {
+ if !yaml_parser_fetch_more_tokens(parser) {
+ return false
+ }
+ }
+
+ // Fetch the next token from the queue.
+ *token = parser.tokens[parser.tokens_head]
+ parser.tokens_head++
+ parser.tokens_parsed++
+ parser.token_available = false
+
+ if token.typ == yaml_STREAM_END_TOKEN {
+ parser.stream_end_produced = true
+ }
+ return true
+}
+
+// Set the scanner error and return false.
+func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool {
+ parser.error = yaml_SCANNER_ERROR
+ parser.context = context
+ parser.context_mark = context_mark
+ parser.problem = problem
+ parser.problem_mark = parser.mark
+ return false
+}
+
+func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool {
+ context := "while parsing a tag"
+ if directive {
+ context = "while parsing a %TAG directive"
+ }
+ return yaml_parser_set_scanner_error(parser, context, context_mark, problem)
+}
+
+func trace(args ...interface{}) func() {
+ pargs := append([]interface{}{"+++"}, args...)
+ fmt.Println(pargs...)
+ pargs = append([]interface{}{"---"}, args...)
+ return func() { fmt.Println(pargs...) }
+}
+
+// Ensure that the tokens queue contains at least one token which can be
+// returned to the Parser.
+func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
+ // While we need more tokens to fetch, do it.
+ for {
+ // [Go] The comment parsing logic requires a lookahead of two tokens
+ // so that foot comments may be parsed in time of associating them
+ // with the tokens that are parsed before them, and also for line
+ // comments to be transformed into head comments in some edge cases.
+ if parser.tokens_head < len(parser.tokens)-2 {
+ // If a potential simple key is at the head position, we need to fetch
+ // the next token to disambiguate it.
+ head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
+ if !ok {
+ break
+ } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
+ return false
+ } else if !valid {
+ break
+ }
+ }
+ // Fetch the next token.
+ if !yaml_parser_fetch_next_token(parser) {
+ return false
+ }
+ }
+
+ parser.token_available = true
+ return true
+}
+
+// The dispatcher for token fetchers.
+func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) {
+ // Ensure that the buffer is initialized.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we just started scanning. Fetch STREAM-START then.
+ if !parser.stream_start_produced {
+ return yaml_parser_fetch_stream_start(parser)
+ }
+
+ scan_mark := parser.mark
+
+ // Eat whitespaces and comments until we reach the next token.
+ if !yaml_parser_scan_to_next_token(parser) {
+ return false
+ }
+
+ // [Go] While unrolling indents, transform the head comments of prior
+ // indentation levels observed after scan_start into foot comments at
+ // the respective indexes.
+
+ // Check the indentation level against the current column.
+ if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) {
+ return false
+ }
+
+ // Ensure that the buffer contains at least 4 characters. 4 is the length
+ // of the longest indicators ('--- ' and '... ').
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ // Is it the end of the stream?
+ if is_z(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_fetch_stream_end(parser)
+ }
+
+ // Is it a directive?
+ if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' {
+ return yaml_parser_fetch_directive(parser)
+ }
+
+ buf := parser.buffer
+ pos := parser.buffer_pos
+
+ // Is it the document start indicator?
+ if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN)
+ }
+
+ // Is it the document end indicator?
+ if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) {
+ return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN)
+ }
+
+ comment_mark := parser.mark
+ if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') {
+ // Associate any following comments with the prior token.
+ comment_mark = parser.tokens[len(parser.tokens)-1].start_mark
+ }
+ defer func() {
+ if !ok {
+ return
+ }
+ if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN {
+ // Sequence indicators alone have no line comments. It becomes
+ // a head comment for whatever follows.
+ return
+ }
+ if !yaml_parser_scan_line_comment(parser, comment_mark) {
+ ok = false
+ return
+ }
+ }()
+
+ // Is it the flow sequence start indicator?
+ if buf[pos] == '[' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN)
+ }
+
+ // Is it the flow mapping start indicator?
+ if parser.buffer[parser.buffer_pos] == '{' {
+ return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN)
+ }
+
+ // Is it the flow sequence end indicator?
+ if parser.buffer[parser.buffer_pos] == ']' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_SEQUENCE_END_TOKEN)
+ }
+
+ // Is it the flow mapping end indicator?
+ if parser.buffer[parser.buffer_pos] == '}' {
+ return yaml_parser_fetch_flow_collection_end(parser,
+ yaml_FLOW_MAPPING_END_TOKEN)
+ }
+
+ // Is it the flow entry indicator?
+ if parser.buffer[parser.buffer_pos] == ',' {
+ return yaml_parser_fetch_flow_entry(parser)
+ }
+
+ // Is it the block entry indicator?
+ if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) {
+ return yaml_parser_fetch_block_entry(parser)
+ }
+
+ // Is it the key indicator?
+ if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_key(parser)
+ }
+
+ // Is it the value indicator?
+ if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_value(parser)
+ }
+
+ // Is it an alias?
+ if parser.buffer[parser.buffer_pos] == '*' {
+ return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN)
+ }
+
+ // Is it an anchor?
+ if parser.buffer[parser.buffer_pos] == '&' {
+ return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN)
+ }
+
+ // Is it a tag?
+ if parser.buffer[parser.buffer_pos] == '!' {
+ return yaml_parser_fetch_tag(parser)
+ }
+
+ // Is it a literal scalar?
+ if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, true)
+ }
+
+ // Is it a folded scalar?
+ if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 {
+ return yaml_parser_fetch_block_scalar(parser, false)
+ }
+
+ // Is it a single-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ return yaml_parser_fetch_flow_scalar(parser, true)
+ }
+
+ // Is it a double-quoted scalar?
+ if parser.buffer[parser.buffer_pos] == '"' {
+ return yaml_parser_fetch_flow_scalar(parser, false)
+ }
+
+ // Is it a plain scalar?
+ //
+ // A plain scalar may start with any non-blank characters except
+ //
+ // '-', '?', ':', ',', '[', ']', '{', '}',
+ // '#', '&', '*', '!', '|', '>', '\'', '\"',
+ // '%', '@', '`'.
+ //
+ // In the block context (and, for the '-' indicator, in the flow context
+ // too), it may also start with the characters
+ //
+ // '-', '?', ':'
+ //
+ // if it is followed by a non-space character.
+ //
+ // The last rule is more restrictive than the specification requires.
+ // [Go] TODO Make this logic more reasonable.
+ //switch parser.buffer[parser.buffer_pos] {
+ //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`':
+ //}
+ if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' ||
+ parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' ||
+ parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') ||
+ (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level == 0 &&
+ (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') &&
+ !is_blankz(parser.buffer, parser.buffer_pos+1)) {
+ return yaml_parser_fetch_plain_scalar(parser)
+ }
+
+ // If we don't determine the token type so far, it is an error.
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning for the next token", parser.mark,
+ "found character that cannot start any token")
+}
+
+func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
+ if !simple_key.possible {
+ return false, true
+ }
+
+ // The 1.2 specification says:
+ //
+ // "If the ? indicator is omitted, parsing needs to see past the
+ // implicit key to recognize it as such. To limit the amount of
+ // lookahead required, the “:” indicator must appear at most 1024
+ // Unicode characters beyond the start of the key. In addition, the key
+ // is restricted to a single line."
+ //
+ if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
+ // Check if the potential simple key to be removed is required.
+ if simple_key.required {
+ return false, yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", simple_key.mark,
+ "could not find expected ':'")
+ }
+ simple_key.possible = false
+ return false, true
+ }
+ return true, true
+}
+
+// Check if a simple key may start at the current position and add it if
+// needed.
+func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
+ // A simple key is required at the current position if the scanner is in
+ // the block context and the current column coincides with the indentation
+ // level.
+
+ required := parser.flow_level == 0 && parser.indent == parser.mark.column
+
+ //
+ // If the current position may start a simple key, save it.
+ //
+ if parser.simple_key_allowed {
+ simple_key := yaml_simple_key_t{
+ possible: true,
+ required: required,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ }
+
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+ parser.simple_keys[len(parser.simple_keys)-1] = simple_key
+ parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
+ }
+ return true
+}
+
+// Remove a potential simple key at the current flow level.
+func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
+ i := len(parser.simple_keys) - 1
+ if parser.simple_keys[i].possible {
+ // If the key is required, it is an error.
+ if parser.simple_keys[i].required {
+ return yaml_parser_set_scanner_error(parser,
+ "while scanning a simple key", parser.simple_keys[i].mark,
+ "could not find expected ':'")
+ }
+ // Remove the key from the stack.
+ parser.simple_keys[i].possible = false
+ delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
+ }
+ return true
+}
+
+// max_flow_level limits the flow_level
+const max_flow_level = 10000
+
+// Increase the flow level and resize the simple key list if needed.
+func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
+ // Reset the simple key on the next level.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
+ possible: false,
+ required: false,
+ token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
+ mark: parser.mark,
+ })
+
+ // Increase the flow level.
+ parser.flow_level++
+ if parser.flow_level > max_flow_level {
+ return yaml_parser_set_scanner_error(parser,
+ "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+ fmt.Sprintf("exceeded max depth of %d", max_flow_level))
+ }
+ return true
+}
+
+// Decrease the flow level.
+func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
+ if parser.flow_level > 0 {
+ parser.flow_level--
+ last := len(parser.simple_keys) - 1
+ delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
+ parser.simple_keys = parser.simple_keys[:last]
+ }
+ return true
+}
+
+// max_indents limits the indents stack size
+const max_indents = 10000
+
+// Push the current indentation level to the stack and set the new level
+// the current column is greater than the indentation level. In this case,
+// append or insert the specified token into the token queue.
+func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ if parser.indent < column {
+ // Push the current indentation level to the stack and set the new
+ // indentation level.
+ parser.indents = append(parser.indents, parser.indent)
+ parser.indent = column
+ if len(parser.indents) > max_indents {
+ return yaml_parser_set_scanner_error(parser,
+ "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
+ fmt.Sprintf("exceeded max depth of %d", max_indents))
+ }
+
+ // Create a token and insert it into the queue.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: mark,
+ end_mark: mark,
+ }
+ if number > -1 {
+ number -= parser.tokens_parsed
+ }
+ yaml_insert_token(parser, number, &token)
+ }
+ return true
+}
+
+// Pop indentation levels from the indents stack until the current level
+// becomes less or equal to the column. For each indentation level, append
+// the BLOCK-END token.
+func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool {
+ // In the flow context, do nothing.
+ if parser.flow_level > 0 {
+ return true
+ }
+
+ block_mark := scan_mark
+ block_mark.index--
+
+ // Loop through the indentation levels in the stack.
+ for parser.indent > column {
+
+ // [Go] Reposition the end token before potential following
+ // foot comments of parent blocks. For that, search
+ // backwards for recent comments that were at the same
+ // indent as the block that is ending now.
+ stop_index := block_mark.index
+ for i := len(parser.comments) - 1; i >= 0; i-- {
+ comment := &parser.comments[i]
+
+ if comment.end_mark.index < stop_index {
+ // Don't go back beyond the start of the comment/whitespace scan, unless column < 0.
+ // If requested indent column is < 0, then the document is over and everything else
+ // is a foot anyway.
+ break
+ }
+ if comment.start_mark.column == parser.indent+1 {
+ // This is a good match. But maybe there's a former comment
+ // at that same indent level, so keep searching.
+ block_mark = comment.start_mark
+ }
+
+ // While the end of the former comment matches with
+ // the start of the following one, we know there's
+ // nothing in between and scanning is still safe.
+ stop_index = comment.scan_mark.index
+ }
+
+ // Create a token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_END_TOKEN,
+ start_mark: block_mark,
+ end_mark: block_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+
+ // Pop the indentation level.
+ parser.indent = parser.indents[len(parser.indents)-1]
+ parser.indents = parser.indents[:len(parser.indents)-1]
+ }
+ return true
+}
+
+// Initialize the scanner and produce the STREAM-START token.
+func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
+
+ // Set the initial indentation.
+ parser.indent = -1
+
+ // Initialize the simple key stack.
+ parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
+
+ parser.simple_keys_by_tok = make(map[int]int)
+
+ // A simple key is allowed at the beginning of the stream.
+ parser.simple_key_allowed = true
+
+ // We have started.
+ parser.stream_start_produced = true
+
+ // Create the STREAM-START token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_START_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ encoding: parser.encoding,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the STREAM-END token and shut down the scanner.
+func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
+
+ // Force new line.
+ if parser.mark.column != 0 {
+ parser.mark.column = 0
+ parser.mark.line++
+ }
+
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the STREAM-END token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_STREAM_END_TOKEN,
+ start_mark: parser.mark,
+ end_mark: parser.mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token.
+func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
+ token := yaml_token_t{}
+ if !yaml_parser_scan_directive(parser, &token) {
+ return false
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the DOCUMENT-START or DOCUMENT-END token.
+func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset the indentation level.
+ if !yaml_parser_unroll_indent(parser, -1, parser.mark) {
+ return false
+ }
+
+ // Reset simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+ start_mark := parser.mark
+
+ skip(parser)
+ skip(parser)
+ skip(parser)
+
+ end_mark := parser.mark
+
+ // Create the DOCUMENT-START or DOCUMENT-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
+func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+
+ // The indicators '[' and '{' may start a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // Increase the flow level.
+ if !yaml_parser_increase_flow_level(parser) {
+ return false
+ }
+
+ // A simple key may follow the indicators '[' and '{'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
+func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // Reset any potential simple key on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Decrease the flow level.
+ if !yaml_parser_decrease_flow_level(parser) {
+ return false
+ }
+
+ // No simple keys after the indicators ']' and '}'.
+ parser.simple_key_allowed = false
+
+ // Consume the token.
+
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token.
+ token := yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ // Append the token to the queue.
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the FLOW-ENTRY token.
+func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after ','.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the FLOW-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_FLOW_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the BLOCK-ENTRY token.
+func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
+ // Check if the scanner is in the block context.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new entry.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "block sequence entries are not allowed in this context")
+ }
+ // Add the BLOCK-SEQUENCE-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) {
+ return false
+ }
+ } else {
+ // It is an error for the '-' indicator to occur in the flow context,
+ // but we let the Parser detect and report about it because the Parser
+ // is able to point to the context.
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '-'.
+ parser.simple_key_allowed = true
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the BLOCK-ENTRY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_BLOCK_ENTRY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the KEY token.
+func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
+
+ // In the block context, additional checks are required.
+ if parser.flow_level == 0 {
+ // Check if we are allowed to start a new key (not nessesary simple).
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping keys are not allowed in this context")
+ }
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Reset any potential simple keys on the current flow level.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // Simple keys are allowed after '?' in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the KEY token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the VALUE token.
+func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
+
+ simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
+
+ // Have we found a simple key?
+ if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
+ return false
+
+ } else if valid {
+
+ // Create the KEY token and insert it into the queue.
+ token := yaml_token_t{
+ typ: yaml_KEY_TOKEN,
+ start_mark: simple_key.mark,
+ end_mark: simple_key.mark,
+ }
+ yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token)
+
+ // In the block context, we may need to add the BLOCK-MAPPING-START token.
+ if !yaml_parser_roll_indent(parser, simple_key.mark.column,
+ simple_key.token_number,
+ yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) {
+ return false
+ }
+
+ // Remove the simple key.
+ simple_key.possible = false
+ delete(parser.simple_keys_by_tok, simple_key.token_number)
+
+ // A simple key cannot follow another simple key.
+ parser.simple_key_allowed = false
+
+ } else {
+ // The ':' indicator follows a complex key.
+
+ // In the block context, extra checks are required.
+ if parser.flow_level == 0 {
+
+ // Check if we are allowed to start a complex value.
+ if !parser.simple_key_allowed {
+ return yaml_parser_set_scanner_error(parser, "", parser.mark,
+ "mapping values are not allowed in this context")
+ }
+
+ // Add the BLOCK-MAPPING-START token if needed.
+ if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) {
+ return false
+ }
+ }
+
+ // Simple keys after ':' are allowed in the block context.
+ parser.simple_key_allowed = parser.flow_level == 0
+ }
+
+ // Consume the token.
+ start_mark := parser.mark
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create the VALUE token and append it to the queue.
+ token := yaml_token_t{
+ typ: yaml_VALUE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the ALIAS or ANCHOR token.
+func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool {
+ // An anchor or an alias could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow an anchor or an alias.
+ parser.simple_key_allowed = false
+
+ // Create the ALIAS or ANCHOR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_anchor(parser, &token, typ) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the TAG token.
+func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
+ // A tag could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a tag.
+ parser.simple_key_allowed = false
+
+ // Create the TAG token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_tag(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
+func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool {
+ // Remove any potential simple keys.
+ if !yaml_parser_remove_simple_key(parser) {
+ return false
+ }
+
+ // A simple key may follow a block scalar.
+ parser.simple_key_allowed = true
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_block_scalar(parser, &token, literal) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
+func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_flow_scalar(parser, &token, single) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Produce the SCALAR(...,plain) token.
+func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
+ // A plain scalar could be a simple key.
+ if !yaml_parser_save_simple_key(parser) {
+ return false
+ }
+
+ // A simple key cannot follow a flow scalar.
+ parser.simple_key_allowed = false
+
+ // Create the SCALAR token and append it to the queue.
+ var token yaml_token_t
+ if !yaml_parser_scan_plain_scalar(parser, &token) {
+ return false
+ }
+ yaml_insert_token(parser, -1, &token)
+ return true
+}
+
+// Eat whitespaces and comments until the next token is found.
+func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
+
+ scan_mark := parser.mark
+
+ // Until the next token is not found.
+ for {
+ // Allow the BOM mark to start a line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ }
+
+ // Eat whitespaces.
+ // Tabs are allowed:
+ // - in the flow context
+ // - in the block context, but not at the beginning of the line or
+ // after '-', '?', or ':' (complex value).
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if we just had a line comment under a sequence entry that
+ // looks more like a header to the following content. Similar to this:
+ //
+ // - # The comment
+ // - Some data
+ //
+ // If so, transform the line comment to a head comment and reposition.
+ if len(parser.comments) > 0 && len(parser.tokens) > 1 {
+ tokenA := parser.tokens[len(parser.tokens)-2]
+ tokenB := parser.tokens[len(parser.tokens)-1]
+ comment := &parser.comments[len(parser.comments)-1]
+ if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) {
+ // If it was in the prior line, reposition so it becomes a
+ // header of the follow up token. Otherwise, keep it in place
+ // so it becomes a header of the former.
+ comment.head = comment.line
+ comment.line = nil
+ if comment.start_mark.line == parser.mark.line-1 {
+ comment.token_mark = parser.mark
+ }
+ }
+ }
+
+ // Eat a comment until a line break.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ if !yaml_parser_scan_comments(parser, scan_mark) {
+ return false
+ }
+ }
+
+ // If it is a line break, eat it.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+
+ // In the block context, a new line may start a simple key.
+ if parser.flow_level == 0 {
+ parser.simple_key_allowed = true
+ }
+ } else {
+ break // We have found a token.
+ }
+ }
+
+ return true
+}
+
+// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool {
+ // Eat '%'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the directive name.
+ var name []byte
+ if !yaml_parser_scan_directive_name(parser, start_mark, &name) {
+ return false
+ }
+
+ // Is it a YAML directive?
+ if bytes.Equal(name, []byte("YAML")) {
+ // Scan the VERSION directive value.
+ var major, minor int8
+ if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a VERSION-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_VERSION_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ major: major,
+ minor: minor,
+ }
+
+ // Is it a TAG directive?
+ } else if bytes.Equal(name, []byte("TAG")) {
+ // Scan the TAG directive value.
+ var handle, prefix []byte
+ if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) {
+ return false
+ }
+ end_mark := parser.mark
+
+ // Create a TAG-DIRECTIVE token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_DIRECTIVE_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ prefix: prefix,
+ }
+
+ // Unknown directive.
+ } else {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unknown directive name")
+ return false
+ }
+
+ // Eat the rest of the line including any comments.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ if parser.buffer[parser.buffer_pos] == '#' {
+ // [Go] Discard this inline comment for the time being.
+ //if !yaml_parser_scan_line_comment(parser, start_mark) {
+ // return false
+ //}
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ return true
+}
+
+// Scan the directive name.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^
+//
+func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool {
+ // Consume the directive name.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ var s []byte
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the name is empty.
+ if len(s) == 0 {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "could not find expected directive name")
+ return false
+ }
+
+ // Check for an blank character after the name.
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a directive",
+ start_mark, "found unexpected non-alphabetical character")
+ return false
+ }
+ *name = s
+ return true
+}
+
+// Scan the value of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^^^^^^
+func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool {
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the major version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, major) {
+ return false
+ }
+
+ // Eat '.'.
+ if parser.buffer[parser.buffer_pos] != '.' {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected digit or '.' character")
+ }
+
+ skip(parser)
+
+ // Consume the minor version number.
+ if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) {
+ return false
+ }
+ return true
+}
+
+const max_number_length = 2
+
+// Scan the version number of VERSION-DIRECTIVE.
+//
+// Scope:
+// %YAML 1.1 # a comment \n
+// ^
+// %YAML 1.1 # a comment \n
+// ^
+func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool {
+
+ // Repeat while the next character is digit.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var value, length int8
+ for is_digit(parser.buffer, parser.buffer_pos) {
+ // Check if the number is too long.
+ length++
+ if length > max_number_length {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "found extremely long version number")
+ }
+ value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos))
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the number was present.
+ if length == 0 {
+ return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
+ start_mark, "did not find expected version number")
+ }
+ *number = value
+ return true
+}
+
+// Scan the value of a TAG-DIRECTIVE token.
+//
+// Scope:
+// %TAG !yaml! tag:yaml.org,2002: \n
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool {
+ var handle_value, prefix_value []byte
+
+ // Eat whitespaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) {
+ return false
+ }
+
+ // Expect a whitespace.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blank(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace")
+ return false
+ }
+
+ // Eat whitespaces.
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Scan a prefix.
+ if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) {
+ return false
+ }
+
+ // Expect a whitespace or line break.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ *handle = handle_value
+ *prefix = prefix_value
+ return true
+}
+
+func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool {
+ var s []byte
+
+ // Eat the indicator character.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the value.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ end_mark := parser.mark
+
+ /*
+ * Check if length of the anchor is greater than 0 and it is followed by
+ * a whitespace character or one of the indicators:
+ *
+ * '?', ':', ',', ']', '}', '%', '@', '`'.
+ */
+
+ if len(s) == 0 ||
+ !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' ||
+ parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '`') {
+ context := "while scanning an alias"
+ if typ == yaml_ANCHOR_TOKEN {
+ context = "while scanning an anchor"
+ }
+ yaml_parser_set_scanner_error(parser, context, start_mark,
+ "did not find expected alphabetic or numeric character")
+ return false
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: typ,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ }
+
+ return true
+}
+
+/*
+ * Scan a TAG token.
+ */
+
+func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool {
+ var handle, suffix []byte
+
+ start_mark := parser.mark
+
+ // Check if the tag is in the canonical form.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ if parser.buffer[parser.buffer_pos+1] == '<' {
+ // Keep the handle as ''
+
+ // Eat '!<'
+ skip(parser)
+ skip(parser)
+
+ // Consume the tag value.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+
+ // Check for '>' and eat it.
+ if parser.buffer[parser.buffer_pos] != '>' {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find the expected '>'")
+ return false
+ }
+
+ skip(parser)
+ } else {
+ // The tag has either the '!suffix' or the '!handle!suffix' form.
+
+ // First, try to scan a handle.
+ if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) {
+ return false
+ }
+
+ // Check if it is, indeed, handle.
+ if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' {
+ // Scan the suffix now.
+ if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) {
+ return false
+ }
+ } else {
+ // It wasn't a handle after all. Scan the rest of the tag.
+ if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) {
+ return false
+ }
+
+ // Set the handle to '!'.
+ handle = []byte{'!'}
+
+ // A special case: the '!' tag. Set the handle to '' and the
+ // suffix to '!'.
+ if len(suffix) == 0 {
+ handle, suffix = suffix, handle
+ }
+ }
+ }
+
+ // Check the character which ends the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if !is_blankz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find expected whitespace or line break")
+ return false
+ }
+
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_TAG_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: handle,
+ suffix: suffix,
+ }
+ return true
+}
+
+// Scan a tag handle.
+func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool {
+ // Check the initial '!' character.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] != '!' {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+
+ var s []byte
+
+ // Copy the '!' character.
+ s = read(parser, s)
+
+ // Copy all subsequent alphabetical and numerical characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_alpha(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check if the trailing character is '!' and copy it.
+ if parser.buffer[parser.buffer_pos] == '!' {
+ s = read(parser, s)
+ } else {
+ // It's either the '!' tag or not really a tag handle. If it's a %TAG
+ // directive, it's an error. If it's a tag token, it must be a part of URI.
+ if directive && string(s) != "!" {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected '!'")
+ return false
+ }
+ }
+
+ *handle = s
+ return true
+}
+
+// Scan a tag.
+func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool {
+ //size_t length = head ? strlen((char *)head) : 0
+ var s []byte
+ hasTag := len(head) > 0
+
+ // Copy the head if needed.
+ //
+ // Note that we don't copy the leading '!' character.
+ if len(head) > 1 {
+ s = append(s, head[1:]...)
+ }
+
+ // Scan the tag.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // The set of characters that may appear in URI is as follows:
+ //
+ // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
+ // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
+ // '%'.
+ // [Go] TODO Convert this into more reasonable logic.
+ for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' ||
+ parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' ||
+ parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' ||
+ parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' ||
+ parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' ||
+ parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' ||
+ parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' ||
+ parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' ||
+ parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' ||
+ parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' ||
+ parser.buffer[parser.buffer_pos] == '%' {
+ // Check if it is a URI-escape sequence.
+ if parser.buffer[parser.buffer_pos] == '%' {
+ if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) {
+ return false
+ }
+ } else {
+ s = read(parser, s)
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ hasTag = true
+ }
+
+ if !hasTag {
+ yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find expected tag URI")
+ return false
+ }
+ *uri = s
+ return true
+}
+
+// Decode an URI-escape sequence corresponding to a single UTF-8 character.
+func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool {
+
+ // Decode the required number of characters.
+ w := 1024
+ for w > 0 {
+ // Check for a URI-escaped octet.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+
+ if !(parser.buffer[parser.buffer_pos] == '%' &&
+ is_hex(parser.buffer, parser.buffer_pos+1) &&
+ is_hex(parser.buffer, parser.buffer_pos+2)) {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "did not find URI escaped octet")
+ }
+
+ // Get the octet.
+ octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2))
+
+ // If it is the leading octet, determine the length of the UTF-8 sequence.
+ if w == 1024 {
+ w = width(octet)
+ if w == 0 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect leading UTF-8 octet")
+ }
+ } else {
+ // Check if the trailing octet is correct.
+ if octet&0xC0 != 0x80 {
+ return yaml_parser_set_scanner_tag_error(parser, directive,
+ start_mark, "found an incorrect trailing UTF-8 octet")
+ }
+ }
+
+ // Copy the octet and move the pointers.
+ *s = append(*s, octet)
+ skip(parser)
+ skip(parser)
+ skip(parser)
+ w--
+ }
+ return true
+}
+
+// Scan a block scalar.
+func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool {
+ // Eat the indicator '|' or '>'.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Scan the additional block scalar indicators.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check for a chomping indicator.
+ var chomping, increment int
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ // Set the chomping method and eat the indicator.
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+
+ // Check for an indentation indicator.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_digit(parser.buffer, parser.buffer_pos) {
+ // Check that the indentation is greater than 0.
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+
+ // Get the indentation level and eat the indicator.
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+ }
+
+ } else if is_digit(parser.buffer, parser.buffer_pos) {
+ // Do the same as above, but in the opposite order.
+
+ if parser.buffer[parser.buffer_pos] == '0' {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found an indentation indicator equal to 0")
+ return false
+ }
+ increment = as_digit(parser.buffer, parser.buffer_pos)
+ skip(parser)
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' {
+ if parser.buffer[parser.buffer_pos] == '+' {
+ chomping = +1
+ } else {
+ chomping = -1
+ }
+ skip(parser)
+ }
+ }
+
+ // Eat whitespaces and comments to the end of the line.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for is_blank(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.buffer[parser.buffer_pos] == '#' {
+ if !yaml_parser_scan_line_comment(parser, start_mark) {
+ return false
+ }
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ }
+
+ // Check if we are at the end of the line.
+ if !is_breakz(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "did not find expected comment or line break")
+ return false
+ }
+
+ // Eat a line break.
+ if is_break(parser.buffer, parser.buffer_pos) {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ }
+
+ end_mark := parser.mark
+
+ // Set the indentation level if it was specified.
+ var indent int
+ if increment > 0 {
+ if parser.indent >= 0 {
+ indent = parser.indent + increment
+ } else {
+ indent = increment
+ }
+ }
+
+ // Scan the leading line breaks and determine the indentation level if needed.
+ var s, leading_break, trailing_breaks []byte
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+
+ // Scan the block scalar content.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ var leading_blank, trailing_blank bool
+ for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) {
+ // We are at the beginning of a non-empty line.
+
+ // Is it a trailing whitespace?
+ trailing_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Check if we need to fold the leading line break.
+ if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' {
+ // Do we need to join the lines by space?
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ }
+ } else {
+ s = append(s, leading_break...)
+ }
+ leading_break = leading_break[:0]
+
+ // Append the remaining line breaks.
+ s = append(s, trailing_breaks...)
+ trailing_breaks = trailing_breaks[:0]
+
+ // Is it a leading whitespace?
+ leading_blank = is_blank(parser.buffer, parser.buffer_pos)
+
+ // Consume the current line.
+ for !is_breakz(parser.buffer, parser.buffer_pos) {
+ s = read(parser, s)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ leading_break = read_line(parser, leading_break)
+
+ // Eat the following indentation spaces and line breaks.
+ if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) {
+ return false
+ }
+ }
+
+ // Chomp the tail.
+ if chomping != -1 {
+ s = append(s, leading_break...)
+ }
+ if chomping == 1 {
+ s = append(s, trailing_breaks...)
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_LITERAL_SCALAR_STYLE,
+ }
+ if !literal {
+ token.style = yaml_FOLDED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan indentation spaces and line breaks for a block scalar. Determine the
+// indentation level if needed.
+func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool {
+ *end_mark = parser.mark
+
+ // Eat the indentation spaces and line breaks.
+ max_indent := 0
+ for {
+ // Eat the indentation spaces.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) {
+ skip(parser)
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+ if parser.mark.column > max_indent {
+ max_indent = parser.mark.column
+ }
+
+ // Check for a tab character messing the indentation.
+ if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) {
+ return yaml_parser_set_scanner_error(parser, "while scanning a block scalar",
+ start_mark, "found a tab character where an indentation space is expected")
+ }
+
+ // Have we found a non-empty line?
+ if !is_break(parser.buffer, parser.buffer_pos) {
+ break
+ }
+
+ // Consume the line break.
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ // [Go] Should really be returning breaks instead.
+ *breaks = read_line(parser, *breaks)
+ *end_mark = parser.mark
+ }
+
+ // Determine the indentation level if needed.
+ if *indent == 0 {
+ *indent = max_indent
+ if *indent < parser.indent+1 {
+ *indent = parser.indent + 1
+ }
+ if *indent < 1 {
+ *indent = 1
+ }
+ }
+ return true
+}
+
+// Scan a quoted scalar.
+func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool {
+ // Eat the left quote.
+ start_mark := parser.mark
+ skip(parser)
+
+ // Consume the content of the quoted scalar.
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ for {
+ // Check that there are no document indicators at the beginning of the line.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected document indicator")
+ return false
+ }
+
+ // Check for EOF.
+ if is_z(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar",
+ start_mark, "found unexpected end of stream")
+ return false
+ }
+
+ // Consume non-blank characters.
+ leading_blanks := false
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+ if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' {
+ // Is is an escaped single quote.
+ s = append(s, '\'')
+ skip(parser)
+ skip(parser)
+
+ } else if single && parser.buffer[parser.buffer_pos] == '\'' {
+ // It is a right single quote.
+ break
+ } else if !single && parser.buffer[parser.buffer_pos] == '"' {
+ // It is a right double quote.
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) {
+ // It is an escaped line break.
+ if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) {
+ return false
+ }
+ skip(parser)
+ skip_line(parser)
+ leading_blanks = true
+ break
+
+ } else if !single && parser.buffer[parser.buffer_pos] == '\\' {
+ // It is an escape sequence.
+ code_length := 0
+
+ // Check the escape character.
+ switch parser.buffer[parser.buffer_pos+1] {
+ case '0':
+ s = append(s, 0)
+ case 'a':
+ s = append(s, '\x07')
+ case 'b':
+ s = append(s, '\x08')
+ case 't', '\t':
+ s = append(s, '\x09')
+ case 'n':
+ s = append(s, '\x0A')
+ case 'v':
+ s = append(s, '\x0B')
+ case 'f':
+ s = append(s, '\x0C')
+ case 'r':
+ s = append(s, '\x0D')
+ case 'e':
+ s = append(s, '\x1B')
+ case ' ':
+ s = append(s, '\x20')
+ case '"':
+ s = append(s, '"')
+ case '\'':
+ s = append(s, '\'')
+ case '\\':
+ s = append(s, '\\')
+ case 'N': // NEL (#x85)
+ s = append(s, '\xC2')
+ s = append(s, '\x85')
+ case '_': // #xA0
+ s = append(s, '\xC2')
+ s = append(s, '\xA0')
+ case 'L': // LS (#x2028)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA8')
+ case 'P': // PS (#x2029)
+ s = append(s, '\xE2')
+ s = append(s, '\x80')
+ s = append(s, '\xA9')
+ case 'x':
+ code_length = 2
+ case 'u':
+ code_length = 4
+ case 'U':
+ code_length = 8
+ default:
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found unknown escape character")
+ return false
+ }
+
+ skip(parser)
+ skip(parser)
+
+ // Consume an arbitrary escape code.
+ if code_length > 0 {
+ var value int
+
+ // Scan the character value.
+ if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) {
+ return false
+ }
+ for k := 0; k < code_length; k++ {
+ if !is_hex(parser.buffer, parser.buffer_pos+k) {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "did not find expected hexdecimal number")
+ return false
+ }
+ value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k)
+ }
+
+ // Check the value and write the character.
+ if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF {
+ yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar",
+ start_mark, "found invalid Unicode character escape code")
+ return false
+ }
+ if value <= 0x7F {
+ s = append(s, byte(value))
+ } else if value <= 0x7FF {
+ s = append(s, byte(0xC0+(value>>6)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else if value <= 0xFFFF {
+ s = append(s, byte(0xE0+(value>>12)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ } else {
+ s = append(s, byte(0xF0+(value>>18)))
+ s = append(s, byte(0x80+((value>>12)&0x3F)))
+ s = append(s, byte(0x80+((value>>6)&0x3F)))
+ s = append(s, byte(0x80+(value&0x3F)))
+ }
+
+ // Advance the pointer.
+ for k := 0; k < code_length; k++ {
+ skip(parser)
+ }
+ }
+ } else {
+ // It is a non-escaped non-blank character.
+ s = read(parser, s)
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ // Check if we are at the end of the scalar.
+ if single {
+ if parser.buffer[parser.buffer_pos] == '\'' {
+ break
+ }
+ } else {
+ if parser.buffer[parser.buffer_pos] == '"' {
+ break
+ }
+ }
+
+ // Consume blank characters.
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Join the whitespaces or fold line breaks.
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if len(leading_break) > 0 && leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Eat the right quote.
+ skip(parser)
+ end_mark := parser.mark
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_SINGLE_QUOTED_SCALAR_STYLE,
+ }
+ if !single {
+ token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ return true
+}
+
+// Scan a plain scalar.
+func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool {
+
+ var s, leading_break, trailing_breaks, whitespaces []byte
+ var leading_blanks bool
+ var indent = parser.indent + 1
+
+ start_mark := parser.mark
+ end_mark := parser.mark
+
+ // Consume the content of the plain scalar.
+ for {
+ // Check for a document indicator.
+ if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) {
+ return false
+ }
+ if parser.mark.column == 0 &&
+ ((parser.buffer[parser.buffer_pos+0] == '-' &&
+ parser.buffer[parser.buffer_pos+1] == '-' &&
+ parser.buffer[parser.buffer_pos+2] == '-') ||
+ (parser.buffer[parser.buffer_pos+0] == '.' &&
+ parser.buffer[parser.buffer_pos+1] == '.' &&
+ parser.buffer[parser.buffer_pos+2] == '.')) &&
+ is_blankz(parser.buffer, parser.buffer_pos+3) {
+ break
+ }
+
+ // Check for a comment.
+ if parser.buffer[parser.buffer_pos] == '#' {
+ break
+ }
+
+ // Consume non-blank characters.
+ for !is_blankz(parser.buffer, parser.buffer_pos) {
+
+ // Check for indicators that may end a plain scalar.
+ if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
+ (parser.flow_level > 0 &&
+ (parser.buffer[parser.buffer_pos] == ',' ||
+ parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
+ parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
+ parser.buffer[parser.buffer_pos] == '}')) {
+ break
+ }
+
+ // Check if we need to join whitespaces and breaks.
+ if leading_blanks || len(whitespaces) > 0 {
+ if leading_blanks {
+ // Do we need to fold line breaks?
+ if leading_break[0] == '\n' {
+ if len(trailing_breaks) == 0 {
+ s = append(s, ' ')
+ } else {
+ s = append(s, trailing_breaks...)
+ }
+ } else {
+ s = append(s, leading_break...)
+ s = append(s, trailing_breaks...)
+ }
+ trailing_breaks = trailing_breaks[:0]
+ leading_break = leading_break[:0]
+ leading_blanks = false
+ } else {
+ s = append(s, whitespaces...)
+ whitespaces = whitespaces[:0]
+ }
+ }
+
+ // Copy the character.
+ s = read(parser, s)
+
+ end_mark = parser.mark
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ }
+
+ // Is it the end?
+ if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) {
+ break
+ }
+
+ // Consume blank characters.
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
+ for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
+ if is_blank(parser.buffer, parser.buffer_pos) {
+
+ // Check for tab characters that abuse indentation.
+ if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
+ yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
+ start_mark, "found a tab character that violates indentation")
+ return false
+ }
+
+ // Consume a space or a tab character.
+ if !leading_blanks {
+ whitespaces = read(parser, whitespaces)
+ } else {
+ skip(parser)
+ }
+ } else {
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+
+ // Check if it is a first line break.
+ if !leading_blanks {
+ whitespaces = whitespaces[:0]
+ leading_break = read_line(parser, leading_break)
+ leading_blanks = true
+ } else {
+ trailing_breaks = read_line(parser, trailing_breaks)
+ }
+ }
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ }
+
+ // Check indentation level.
+ if parser.flow_level == 0 && parser.mark.column < indent {
+ break
+ }
+ }
+
+ // Create a token.
+ *token = yaml_token_t{
+ typ: yaml_SCALAR_TOKEN,
+ start_mark: start_mark,
+ end_mark: end_mark,
+ value: s,
+ style: yaml_PLAIN_SCALAR_STYLE,
+ }
+
+ // Note that we change the 'simple_key_allowed' flag.
+ if leading_blanks {
+ parser.simple_key_allowed = true
+ }
+ return true
+}
+
+func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool {
+ if parser.newlines > 0 {
+ return true
+ }
+
+ var start_mark yaml_mark_t
+ var text []byte
+
+ for peek := 0; peek < 512; peek++ {
+ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+ break
+ }
+ if is_blank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ if parser.buffer[parser.buffer_pos+peek] == '#' {
+ seen := parser.mark.index+peek
+ for {
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_breakz(parser.buffer, parser.buffer_pos) {
+ if parser.mark.index >= seen {
+ break
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ } else if parser.mark.index >= seen {
+ if len(text) == 0 {
+ start_mark = parser.mark
+ }
+ text = read(parser, text)
+ } else {
+ skip(parser)
+ }
+ }
+ }
+ break
+ }
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, yaml_comment_t{
+ token_mark: token_mark,
+ start_mark: start_mark,
+ line: text,
+ })
+ }
+ return true
+}
+
+func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool {
+ token := parser.tokens[len(parser.tokens)-1]
+
+ if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 {
+ token = parser.tokens[len(parser.tokens)-2]
+ }
+
+ var token_mark = token.start_mark
+ var start_mark yaml_mark_t
+ var next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+
+ var recent_empty = false
+ var first_empty = parser.newlines <= 1
+
+ var line = parser.mark.line
+ var column = parser.mark.column
+
+ var text []byte
+
+ // The foot line is the place where a comment must start to
+ // still be considered as a foot of the prior content.
+ // If there's some content in the currently parsed line, then
+ // the foot is the line below it.
+ var foot_line = -1
+ if scan_mark.line > 0 {
+ foot_line = parser.mark.line-parser.newlines+1
+ if parser.newlines == 0 && parser.mark.column > 1 {
+ foot_line++
+ }
+ }
+
+ var peek = 0
+ for ; peek < 512; peek++ {
+ if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) {
+ break
+ }
+ column++
+ if is_blank(parser.buffer, parser.buffer_pos+peek) {
+ continue
+ }
+ c := parser.buffer[parser.buffer_pos+peek]
+ var close_flow = parser.flow_level > 0 && (c == ']' || c == '}')
+ if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) {
+ // Got line break or terminator.
+ if close_flow || !recent_empty {
+ if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) {
+ // This is the first empty line and there were no empty lines before,
+ // so this initial part of the comment is a foot of the prior token
+ // instead of being a head for the following one. Split it up.
+ // Alternatively, this might also be the last comment inside a flow
+ // scope, so it must be a footer.
+ if len(text) > 0 {
+ if start_mark.column-1 < next_indent {
+ // If dedented it's unrelated to the prior token.
+ token_mark = start_mark
+ }
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: token_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
+ foot: text,
+ })
+ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+ } else {
+ if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 {
+ text = append(text, '\n')
+ }
+ }
+ }
+ if !is_break(parser.buffer, parser.buffer_pos+peek) {
+ break
+ }
+ first_empty = false
+ recent_empty = true
+ column = 0
+ line++
+ continue
+ }
+
+ if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) {
+ // The comment at the different indentation is a foot of the
+ // preceding data rather than a head of the upcoming one.
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: token_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek, line, column},
+ foot: text,
+ })
+ scan_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ token_mark = scan_mark
+ text = nil
+ }
+
+ if parser.buffer[parser.buffer_pos+peek] != '#' {
+ break
+ }
+
+ if len(text) == 0 {
+ start_mark = yaml_mark_t{parser.mark.index + peek, line, column}
+ } else {
+ text = append(text, '\n')
+ }
+
+ recent_empty = false
+
+ // Consume until after the consumed comment line.
+ seen := parser.mark.index+peek
+ for {
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+ if is_breakz(parser.buffer, parser.buffer_pos) {
+ if parser.mark.index >= seen {
+ break
+ }
+ if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) {
+ return false
+ }
+ skip_line(parser)
+ } else if parser.mark.index >= seen {
+ text = read(parser, text)
+ } else {
+ skip(parser)
+ }
+ }
+
+ peek = 0
+ column = 0
+ line = parser.mark.line
+ next_indent = parser.indent
+ if next_indent < 0 {
+ next_indent = 0
+ }
+ }
+
+ if len(text) > 0 {
+ parser.comments = append(parser.comments, yaml_comment_t{
+ scan_mark: scan_mark,
+ token_mark: start_mark,
+ start_mark: start_mark,
+ end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column},
+ head: text,
+ })
+ }
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/sorter.go b/vendor/gopkg.in/yaml.v3/sorter.go
new file mode 100644
index 0000000..9210ece
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/sorter.go
@@ -0,0 +1,134 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "reflect"
+ "unicode"
+)
+
+type keyList []reflect.Value
+
+func (l keyList) Len() int { return len(l) }
+func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l keyList) Less(i, j int) bool {
+ a := l[i]
+ b := l[j]
+ ak := a.Kind()
+ bk := b.Kind()
+ for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
+ a = a.Elem()
+ ak = a.Kind()
+ }
+ for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
+ b = b.Elem()
+ bk = b.Kind()
+ }
+ af, aok := keyFloat(a)
+ bf, bok := keyFloat(b)
+ if aok && bok {
+ if af != bf {
+ return af < bf
+ }
+ if ak != bk {
+ return ak < bk
+ }
+ return numLess(a, b)
+ }
+ if ak != reflect.String || bk != reflect.String {
+ return ak < bk
+ }
+ ar, br := []rune(a.String()), []rune(b.String())
+ digits := false
+ for i := 0; i < len(ar) && i < len(br); i++ {
+ if ar[i] == br[i] {
+ digits = unicode.IsDigit(ar[i])
+ continue
+ }
+ al := unicode.IsLetter(ar[i])
+ bl := unicode.IsLetter(br[i])
+ if al && bl {
+ return ar[i] < br[i]
+ }
+ if al || bl {
+ if digits {
+ return al
+ } else {
+ return bl
+ }
+ }
+ var ai, bi int
+ var an, bn int64
+ if ar[i] == '0' || br[i] == '0' {
+ for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ if ar[j] != '0' {
+ an = 1
+ bn = 1
+ break
+ }
+ }
+ }
+ for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
+ an = an*10 + int64(ar[ai]-'0')
+ }
+ for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
+ bn = bn*10 + int64(br[bi]-'0')
+ }
+ if an != bn {
+ return an < bn
+ }
+ if ai != bi {
+ return ai < bi
+ }
+ return ar[i] < br[i]
+ }
+ return len(ar) < len(br)
+}
+
+// keyFloat returns a float value for v if it is a number/bool
+// and whether it is a number/bool or not.
+func keyFloat(v reflect.Value) (f float64, ok bool) {
+ switch v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return float64(v.Int()), true
+ case reflect.Float32, reflect.Float64:
+ return v.Float(), true
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return float64(v.Uint()), true
+ case reflect.Bool:
+ if v.Bool() {
+ return 1, true
+ }
+ return 0, true
+ }
+ return 0, false
+}
+
+// numLess returns whether a < b.
+// a and b must necessarily have the same kind.
+func numLess(a, b reflect.Value) bool {
+ switch a.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return a.Int() < b.Int()
+ case reflect.Float32, reflect.Float64:
+ return a.Float() < b.Float()
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return a.Uint() < b.Uint()
+ case reflect.Bool:
+ return !a.Bool() && b.Bool()
+ }
+ panic("not a number")
+}
diff --git a/vendor/gopkg.in/yaml.v3/writerc.go b/vendor/gopkg.in/yaml.v3/writerc.go
new file mode 100644
index 0000000..b8a116b
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/writerc.go
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+// Set the writer error and return false.
+func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_WRITER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Flush the output buffer.
+func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
+ if emitter.write_handler == nil {
+ panic("write handler not set")
+ }
+
+ // Check if the buffer is empty.
+ if emitter.buffer_pos == 0 {
+ return true
+ }
+
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
+ return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
+ }
+ emitter.buffer_pos = 0
+ return true
+}
diff --git a/vendor/gopkg.in/yaml.v3/yaml.go b/vendor/gopkg.in/yaml.v3/yaml.go
new file mode 100644
index 0000000..8cec6da
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yaml.go
@@ -0,0 +1,698 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package yaml implements YAML support for the Go language.
+//
+// Source code and other details for the project are available at GitHub:
+//
+// https://github.com/go-yaml/yaml
+//
+package yaml
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "sync"
+ "unicode/utf8"
+)
+
+// The Unmarshaler interface may be implemented by types to customize their
+// behavior when being unmarshaled from a YAML document.
+type Unmarshaler interface {
+ UnmarshalYAML(value *Node) error
+}
+
+type obsoleteUnmarshaler interface {
+ UnmarshalYAML(unmarshal func(interface{}) error) error
+}
+
+// The Marshaler interface may be implemented by types to customize their
+// behavior when being marshaled into a YAML document. The returned value
+// is marshaled in place of the original value implementing Marshaler.
+//
+// If an error is returned by MarshalYAML, the marshaling procedure stops
+// and returns with the provided error.
+type Marshaler interface {
+ MarshalYAML() (interface{}, error)
+}
+
+// Unmarshal decodes the first document found within the in byte slice
+// and assigns decoded values into the out value.
+//
+// Maps and pointers (to a struct, string, int, etc) are accepted as out
+// values. If an internal pointer within a struct is not initialized,
+// the yaml package will initialize it if necessary for unmarshalling
+// the provided data. The out parameter must not be nil.
+//
+// The type of the decoded values should be compatible with the respective
+// values in out. If one or more values cannot be decoded due to a type
+// mismatches, decoding continues partially until the end of the YAML
+// content, and a *yaml.TypeError is returned with details for all
+// missed values.
+//
+// Struct fields are only unmarshalled if they are exported (have an
+// upper case first letter), and are unmarshalled using the field name
+// lowercased as the default key. Custom keys may be defined via the
+// "yaml" name in the field tag: the content preceding the first comma
+// is used as the key, and the following comma-separated options are
+// used to tweak the marshalling process (see Marshal).
+// Conflicting names result in a runtime error.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// var t T
+// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
+//
+// See the documentation of Marshal for the format of tags and a list of
+// supported tag options.
+//
+func Unmarshal(in []byte, out interface{}) (err error) {
+ return unmarshal(in, out, false)
+}
+
+// A Decoder reads and decodes YAML values from an input stream.
+type Decoder struct {
+ parser *parser
+ knownFields bool
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ parser: newParserFromReader(r),
+ }
+}
+
+// KnownFields ensures that the keys in decoded mappings to
+// exist as fields in the struct being decoded into.
+func (dec *Decoder) KnownFields(enable bool) {
+ dec.knownFields = enable
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+ d := newDecoder()
+ d.knownFields = dec.knownFields
+ defer handleErr(&err)
+ node := dec.parser.parse()
+ if node == nil {
+ return io.EOF
+ }
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(node, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+// Decode decodes the node and stores its data into the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (n *Node) Decode(v interface{}) (err error) {
+ d := newDecoder()
+ defer handleErr(&err)
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(n, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+ defer handleErr(&err)
+ d := newDecoder()
+ p := newParser(in)
+ defer p.destroy()
+ node := p.parse()
+ if node != nil {
+ v := reflect.ValueOf(out)
+ if v.Kind() == reflect.Ptr && !v.IsNil() {
+ v = v.Elem()
+ }
+ d.unmarshal(node, v)
+ }
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
+// Marshal serializes the value provided into a YAML document. The structure
+// of the generated document will reflect the structure of the value itself.
+// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
+//
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
+// default key. Custom keys may be defined via the "yaml" name in the field
+// tag: the content preceding the first comma is used as the key, and the
+// following comma-separated options are used to tweak the marshalling process.
+// Conflicting names result in a runtime error.
+//
+// The field tag format accepted is:
+//
+// `(...) yaml:"[][,[,]]" (...)`
+//
+// The following flags are currently supported:
+//
+// omitempty Only include the field if it's not set to the zero
+// value for the type or to empty slices or maps.
+// Zero valued structs will be omitted if all their public
+// fields are zero, unless they implement an IsZero
+// method (see the IsZeroer interface type), in which
+// case the field will be excluded if IsZero returns true.
+//
+// flow Marshal using a flow style (useful for structs,
+// sequences and maps).
+//
+// inline Inline the field, which must be a struct or a map,
+// causing all of its fields or keys to be processed as if
+// they were part of the outer struct. For maps, keys must
+// not conflict with the yaml keys of other struct fields.
+//
+// In addition, if the key is "-", the field is ignored.
+//
+// For example:
+//
+// type T struct {
+// F int `yaml:"a,omitempty"`
+// B int
+// }
+// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
+// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
+//
+func Marshal(in interface{}) (out []byte, err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(in))
+ e.finish()
+ out = e.out
+ return
+}
+
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+ encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ encoder: newEncoderWithWriter(w),
+ }
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e.encoder.marshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// Encode encodes value v and stores its representation in n.
+//
+// See the documentation for Marshal for details about the
+// conversion of Go values into YAML.
+func (n *Node) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e := newEncoder()
+ defer e.destroy()
+ e.marshalDoc("", reflect.ValueOf(v))
+ e.finish()
+ p := newParser(e.out)
+ p.textless = true
+ defer p.destroy()
+ doc := p.parse()
+ *n = *doc.Content[0]
+ return nil
+}
+
+// SetIndent changes the used indentation used when encoding.
+func (e *Encoder) SetIndent(spaces int) {
+ if spaces < 0 {
+ panic("yaml: cannot indent to a negative number of spaces")
+ }
+ e.encoder.indent = spaces
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+ defer handleErr(&err)
+ e.encoder.finish()
+ return nil
+}
+
+func handleErr(err *error) {
+ if v := recover(); v != nil {
+ if e, ok := v.(yamlError); ok {
+ *err = e.err
+ } else {
+ panic(v)
+ }
+ }
+}
+
+type yamlError struct {
+ err error
+}
+
+func fail(err error) {
+ panic(yamlError{err})
+}
+
+func failf(format string, args ...interface{}) {
+ panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+}
+
+// A TypeError is returned by Unmarshal when one or more fields in
+// the YAML document cannot be properly decoded into the requested
+// types. When this error is returned, the value is still
+// unmarshaled partially.
+type TypeError struct {
+ Errors []string
+}
+
+func (e *TypeError) Error() string {
+ return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
+}
+
+type Kind uint32
+
+const (
+ DocumentNode Kind = 1 << iota
+ SequenceNode
+ MappingNode
+ ScalarNode
+ AliasNode
+)
+
+type Style uint32
+
+const (
+ TaggedStyle Style = 1 << iota
+ DoubleQuotedStyle
+ SingleQuotedStyle
+ LiteralStyle
+ FoldedStyle
+ FlowStyle
+)
+
+// Node represents an element in the YAML document hierarchy. While documents
+// are typically encoded and decoded into higher level types, such as structs
+// and maps, Node is an intermediate representation that allows detailed
+// control over the content being decoded or encoded.
+//
+// It's worth noting that although Node offers access into details such as
+// line numbers, colums, and comments, the content when re-encoded will not
+// have its original textual representation preserved. An effort is made to
+// render the data plesantly, and to preserve comments near the data they
+// describe, though.
+//
+// Values that make use of the Node type interact with the yaml package in the
+// same way any other type would do, by encoding and decoding yaml data
+// directly or indirectly into them.
+//
+// For example:
+//
+// var person struct {
+// Name string
+// Address yaml.Node
+// }
+// err := yaml.Unmarshal(data, &person)
+//
+// Or by itself:
+//
+// var person Node
+// err := yaml.Unmarshal(data, &person)
+//
+type Node struct {
+ // Kind defines whether the node is a document, a mapping, a sequence,
+ // a scalar value, or an alias to another node. The specific data type of
+ // scalar nodes may be obtained via the ShortTag and LongTag methods.
+ Kind Kind
+
+ // Style allows customizing the apperance of the node in the tree.
+ Style Style
+
+ // Tag holds the YAML tag defining the data type for the value.
+ // When decoding, this field will always be set to the resolved tag,
+ // even when it wasn't explicitly provided in the YAML content.
+ // When encoding, if this field is unset the value type will be
+ // implied from the node properties, and if it is set, it will only
+ // be serialized into the representation if TaggedStyle is used or
+ // the implicit tag diverges from the provided one.
+ Tag string
+
+ // Value holds the unescaped and unquoted represenation of the value.
+ Value string
+
+ // Anchor holds the anchor name for this node, which allows aliases to point to it.
+ Anchor string
+
+ // Alias holds the node that this alias points to. Only valid when Kind is AliasNode.
+ Alias *Node
+
+ // Content holds contained nodes for documents, mappings, and sequences.
+ Content []*Node
+
+ // HeadComment holds any comments in the lines preceding the node and
+ // not separated by an empty line.
+ HeadComment string
+
+ // LineComment holds any comments at the end of the line where the node is in.
+ LineComment string
+
+ // FootComment holds any comments following the node and before empty lines.
+ FootComment string
+
+ // Line and Column hold the node position in the decoded YAML text.
+ // These fields are not respected when encoding the node.
+ Line int
+ Column int
+}
+
+// IsZero returns whether the node has all of its fields unset.
+func (n *Node) IsZero() bool {
+ return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil &&
+ n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0
+}
+
+
+// LongTag returns the long form of the tag that indicates the data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) LongTag() string {
+ return longTag(n.ShortTag())
+}
+
+// ShortTag returns the short form of the YAML tag that indicates data type for
+// the node. If the Tag field isn't explicitly defined, one will be computed
+// based on the node properties.
+func (n *Node) ShortTag() string {
+ if n.indicatedString() {
+ return strTag
+ }
+ if n.Tag == "" || n.Tag == "!" {
+ switch n.Kind {
+ case MappingNode:
+ return mapTag
+ case SequenceNode:
+ return seqTag
+ case AliasNode:
+ if n.Alias != nil {
+ return n.Alias.ShortTag()
+ }
+ case ScalarNode:
+ tag, _ := resolve("", n.Value)
+ return tag
+ case 0:
+ // Special case to make the zero value convenient.
+ if n.IsZero() {
+ return nullTag
+ }
+ }
+ return ""
+ }
+ return shortTag(n.Tag)
+}
+
+func (n *Node) indicatedString() bool {
+ return n.Kind == ScalarNode &&
+ (shortTag(n.Tag) == strTag ||
+ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
+}
+
+// SetString is a convenience function that sets the node to a string value
+// and defines its style in a pleasant way depending on its content.
+func (n *Node) SetString(s string) {
+ n.Kind = ScalarNode
+ if utf8.ValidString(s) {
+ n.Value = s
+ n.Tag = strTag
+ } else {
+ n.Value = encodeBase64(s)
+ n.Tag = binaryTag
+ }
+ if strings.Contains(n.Value, "\n") {
+ n.Style = LiteralStyle
+ }
+}
+
+// --------------------------------------------------------------------------
+// Maintain a mapping of keys to structure field indexes
+
+// The code in this section was copied from mgo/bson.
+
+// structInfo holds details for the serialization of fields of
+// a given struct.
+type structInfo struct {
+ FieldsMap map[string]fieldInfo
+ FieldsList []fieldInfo
+
+ // InlineMap is the number of the field in the struct that
+ // contains an ,inline map, or -1 if there's none.
+ InlineMap int
+
+ // InlineUnmarshalers holds indexes to inlined fields that
+ // contain unmarshaler values.
+ InlineUnmarshalers [][]int
+}
+
+type fieldInfo struct {
+ Key string
+ Num int
+ OmitEmpty bool
+ Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
+
+ // Inline holds the field index if the field is part of an inlined struct.
+ Inline []int
+}
+
+var structMap = make(map[reflect.Type]*structInfo)
+var fieldMapMutex sync.RWMutex
+var unmarshalerType reflect.Type
+
+func init() {
+ var v Unmarshaler
+ unmarshalerType = reflect.ValueOf(&v).Elem().Type()
+}
+
+func getStructInfo(st reflect.Type) (*structInfo, error) {
+ fieldMapMutex.RLock()
+ sinfo, found := structMap[st]
+ fieldMapMutex.RUnlock()
+ if found {
+ return sinfo, nil
+ }
+
+ n := st.NumField()
+ fieldsMap := make(map[string]fieldInfo)
+ fieldsList := make([]fieldInfo, 0, n)
+ inlineMap := -1
+ inlineUnmarshalers := [][]int(nil)
+ for i := 0; i != n; i++ {
+ field := st.Field(i)
+ if field.PkgPath != "" && !field.Anonymous {
+ continue // Private field
+ }
+
+ info := fieldInfo{Num: i}
+
+ tag := field.Tag.Get("yaml")
+ if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
+ tag = string(field.Tag)
+ }
+ if tag == "-" {
+ continue
+ }
+
+ inline := false
+ fields := strings.Split(tag, ",")
+ if len(fields) > 1 {
+ for _, flag := range fields[1:] {
+ switch flag {
+ case "omitempty":
+ info.OmitEmpty = true
+ case "flow":
+ info.Flow = true
+ case "inline":
+ inline = true
+ default:
+ return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st))
+ }
+ }
+ tag = fields[0]
+ }
+
+ if inline {
+ switch field.Type.Kind() {
+ case reflect.Map:
+ if inlineMap >= 0 {
+ return nil, errors.New("multiple ,inline maps in struct " + st.String())
+ }
+ if field.Type.Key() != reflect.TypeOf("") {
+ return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String())
+ }
+ inlineMap = info.Num
+ case reflect.Struct, reflect.Ptr:
+ ftype := field.Type
+ for ftype.Kind() == reflect.Ptr {
+ ftype = ftype.Elem()
+ }
+ if ftype.Kind() != reflect.Struct {
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ if reflect.PtrTo(ftype).Implements(unmarshalerType) {
+ inlineUnmarshalers = append(inlineUnmarshalers, []int{i})
+ } else {
+ sinfo, err := getStructInfo(ftype)
+ if err != nil {
+ return nil, err
+ }
+ for _, index := range sinfo.InlineUnmarshalers {
+ inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...))
+ }
+ for _, finfo := range sinfo.FieldsList {
+ if _, found := fieldsMap[finfo.Key]; found {
+ msg := "duplicated key '" + finfo.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+ if finfo.Inline == nil {
+ finfo.Inline = []int{i, finfo.Num}
+ } else {
+ finfo.Inline = append([]int{i}, finfo.Inline...)
+ }
+ finfo.Id = len(fieldsList)
+ fieldsMap[finfo.Key] = finfo
+ fieldsList = append(fieldsList, finfo)
+ }
+ }
+ default:
+ return nil, errors.New("option ,inline may only be used on a struct or map field")
+ }
+ continue
+ }
+
+ if tag != "" {
+ info.Key = tag
+ } else {
+ info.Key = strings.ToLower(field.Name)
+ }
+
+ if _, found = fieldsMap[info.Key]; found {
+ msg := "duplicated key '" + info.Key + "' in struct " + st.String()
+ return nil, errors.New(msg)
+ }
+
+ info.Id = len(fieldsList)
+ fieldsList = append(fieldsList, info)
+ fieldsMap[info.Key] = info
+ }
+
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ InlineUnmarshalers: inlineUnmarshalers,
+ }
+
+ fieldMapMutex.Lock()
+ structMap[st] = sinfo
+ fieldMapMutex.Unlock()
+ return sinfo, nil
+}
+
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+ IsZero() bool
+}
+
+func isZero(v reflect.Value) bool {
+ kind := v.Kind()
+ if z, ok := v.Interface().(IsZeroer); ok {
+ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+ return true
+ }
+ return z.IsZero()
+ }
+ switch kind {
+ case reflect.String:
+ return len(v.String()) == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ case reflect.Slice:
+ return v.Len() == 0
+ case reflect.Map:
+ return v.Len() == 0
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Struct:
+ vt := v.Type()
+ for i := v.NumField() - 1; i >= 0; i-- {
+ if vt.Field(i).PkgPath != "" {
+ continue // Private field
+ }
+ if !isZero(v.Field(i)) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
diff --git a/vendor/gopkg.in/yaml.v3/yamlh.go b/vendor/gopkg.in/yaml.v3/yamlh.go
new file mode 100644
index 0000000..7c6d007
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yamlh.go
@@ -0,0 +1,807 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "fmt"
+ "io"
+)
+
+// The version directive data.
+type yaml_version_directive_t struct {
+ major int8 // The major version number.
+ minor int8 // The minor version number.
+}
+
+// The tag directive data.
+type yaml_tag_directive_t struct {
+ handle []byte // The tag handle.
+ prefix []byte // The tag prefix.
+}
+
+type yaml_encoding_t int
+
+// The stream encoding.
+const (
+ // Let the parser choose the encoding.
+ yaml_ANY_ENCODING yaml_encoding_t = iota
+
+ yaml_UTF8_ENCODING // The default UTF-8 encoding.
+ yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
+ yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
+)
+
+type yaml_break_t int
+
+// Line break types.
+const (
+ // Let the parser choose the break type.
+ yaml_ANY_BREAK yaml_break_t = iota
+
+ yaml_CR_BREAK // Use CR for line breaks (Mac style).
+ yaml_LN_BREAK // Use LN for line breaks (Unix style).
+ yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
+)
+
+type yaml_error_type_t int
+
+// Many bad things could happen with the parser and emitter.
+const (
+ // No error is produced.
+ yaml_NO_ERROR yaml_error_type_t = iota
+
+ yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
+ yaml_READER_ERROR // Cannot read or decode the input stream.
+ yaml_SCANNER_ERROR // Cannot scan the input stream.
+ yaml_PARSER_ERROR // Cannot parse the input stream.
+ yaml_COMPOSER_ERROR // Cannot compose a YAML document.
+ yaml_WRITER_ERROR // Cannot write to the output stream.
+ yaml_EMITTER_ERROR // Cannot emit a YAML stream.
+)
+
+// The pointer position.
+type yaml_mark_t struct {
+ index int // The position index.
+ line int // The position line.
+ column int // The position column.
+}
+
+// Node Styles
+
+type yaml_style_t int8
+
+type yaml_scalar_style_t yaml_style_t
+
+// Scalar styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0
+
+ yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style.
+ yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
+ yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
+ yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
+ yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
+)
+
+type yaml_sequence_style_t yaml_style_t
+
+// Sequence styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
+
+ yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
+ yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
+)
+
+type yaml_mapping_style_t yaml_style_t
+
+// Mapping styles.
+const (
+ // Let the emitter choose the style.
+ yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
+
+ yaml_BLOCK_MAPPING_STYLE // The block mapping style.
+ yaml_FLOW_MAPPING_STYLE // The flow mapping style.
+)
+
+// Tokens
+
+type yaml_token_type_t int
+
+// Token types.
+const (
+ // An empty token.
+ yaml_NO_TOKEN yaml_token_type_t = iota
+
+ yaml_STREAM_START_TOKEN // A STREAM-START token.
+ yaml_STREAM_END_TOKEN // A STREAM-END token.
+
+ yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
+ yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
+ yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
+ yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
+
+ yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
+ yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
+ yaml_BLOCK_END_TOKEN // A BLOCK-END token.
+
+ yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
+ yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
+ yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
+ yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
+
+ yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
+ yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
+ yaml_KEY_TOKEN // A KEY token.
+ yaml_VALUE_TOKEN // A VALUE token.
+
+ yaml_ALIAS_TOKEN // An ALIAS token.
+ yaml_ANCHOR_TOKEN // An ANCHOR token.
+ yaml_TAG_TOKEN // A TAG token.
+ yaml_SCALAR_TOKEN // A SCALAR token.
+)
+
+func (tt yaml_token_type_t) String() string {
+ switch tt {
+ case yaml_NO_TOKEN:
+ return "yaml_NO_TOKEN"
+ case yaml_STREAM_START_TOKEN:
+ return "yaml_STREAM_START_TOKEN"
+ case yaml_STREAM_END_TOKEN:
+ return "yaml_STREAM_END_TOKEN"
+ case yaml_VERSION_DIRECTIVE_TOKEN:
+ return "yaml_VERSION_DIRECTIVE_TOKEN"
+ case yaml_TAG_DIRECTIVE_TOKEN:
+ return "yaml_TAG_DIRECTIVE_TOKEN"
+ case yaml_DOCUMENT_START_TOKEN:
+ return "yaml_DOCUMENT_START_TOKEN"
+ case yaml_DOCUMENT_END_TOKEN:
+ return "yaml_DOCUMENT_END_TOKEN"
+ case yaml_BLOCK_SEQUENCE_START_TOKEN:
+ return "yaml_BLOCK_SEQUENCE_START_TOKEN"
+ case yaml_BLOCK_MAPPING_START_TOKEN:
+ return "yaml_BLOCK_MAPPING_START_TOKEN"
+ case yaml_BLOCK_END_TOKEN:
+ return "yaml_BLOCK_END_TOKEN"
+ case yaml_FLOW_SEQUENCE_START_TOKEN:
+ return "yaml_FLOW_SEQUENCE_START_TOKEN"
+ case yaml_FLOW_SEQUENCE_END_TOKEN:
+ return "yaml_FLOW_SEQUENCE_END_TOKEN"
+ case yaml_FLOW_MAPPING_START_TOKEN:
+ return "yaml_FLOW_MAPPING_START_TOKEN"
+ case yaml_FLOW_MAPPING_END_TOKEN:
+ return "yaml_FLOW_MAPPING_END_TOKEN"
+ case yaml_BLOCK_ENTRY_TOKEN:
+ return "yaml_BLOCK_ENTRY_TOKEN"
+ case yaml_FLOW_ENTRY_TOKEN:
+ return "yaml_FLOW_ENTRY_TOKEN"
+ case yaml_KEY_TOKEN:
+ return "yaml_KEY_TOKEN"
+ case yaml_VALUE_TOKEN:
+ return "yaml_VALUE_TOKEN"
+ case yaml_ALIAS_TOKEN:
+ return "yaml_ALIAS_TOKEN"
+ case yaml_ANCHOR_TOKEN:
+ return "yaml_ANCHOR_TOKEN"
+ case yaml_TAG_TOKEN:
+ return "yaml_TAG_TOKEN"
+ case yaml_SCALAR_TOKEN:
+ return "yaml_SCALAR_TOKEN"
+ }
+ return ""
+}
+
+// The token structure.
+type yaml_token_t struct {
+ // The token type.
+ typ yaml_token_type_t
+
+ // The start/end of the token.
+ start_mark, end_mark yaml_mark_t
+
+ // The stream encoding (for yaml_STREAM_START_TOKEN).
+ encoding yaml_encoding_t
+
+ // The alias/anchor/scalar value or tag/tag directive handle
+ // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
+ value []byte
+
+ // The tag suffix (for yaml_TAG_TOKEN).
+ suffix []byte
+
+ // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
+ prefix []byte
+
+ // The scalar style (for yaml_SCALAR_TOKEN).
+ style yaml_scalar_style_t
+
+ // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
+ major, minor int8
+}
+
+// Events
+
+type yaml_event_type_t int8
+
+// Event types.
+const (
+ // An empty event.
+ yaml_NO_EVENT yaml_event_type_t = iota
+
+ yaml_STREAM_START_EVENT // A STREAM-START event.
+ yaml_STREAM_END_EVENT // A STREAM-END event.
+ yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
+ yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
+ yaml_ALIAS_EVENT // An ALIAS event.
+ yaml_SCALAR_EVENT // A SCALAR event.
+ yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
+ yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
+ yaml_MAPPING_START_EVENT // A MAPPING-START event.
+ yaml_MAPPING_END_EVENT // A MAPPING-END event.
+ yaml_TAIL_COMMENT_EVENT
+)
+
+var eventStrings = []string{
+ yaml_NO_EVENT: "none",
+ yaml_STREAM_START_EVENT: "stream start",
+ yaml_STREAM_END_EVENT: "stream end",
+ yaml_DOCUMENT_START_EVENT: "document start",
+ yaml_DOCUMENT_END_EVENT: "document end",
+ yaml_ALIAS_EVENT: "alias",
+ yaml_SCALAR_EVENT: "scalar",
+ yaml_SEQUENCE_START_EVENT: "sequence start",
+ yaml_SEQUENCE_END_EVENT: "sequence end",
+ yaml_MAPPING_START_EVENT: "mapping start",
+ yaml_MAPPING_END_EVENT: "mapping end",
+ yaml_TAIL_COMMENT_EVENT: "tail comment",
+}
+
+func (e yaml_event_type_t) String() string {
+ if e < 0 || int(e) >= len(eventStrings) {
+ return fmt.Sprintf("unknown event %d", e)
+ }
+ return eventStrings[e]
+}
+
+// The event structure.
+type yaml_event_t struct {
+
+ // The event type.
+ typ yaml_event_type_t
+
+ // The start and end of the event.
+ start_mark, end_mark yaml_mark_t
+
+ // The document encoding (for yaml_STREAM_START_EVENT).
+ encoding yaml_encoding_t
+
+ // The version directive (for yaml_DOCUMENT_START_EVENT).
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives (for yaml_DOCUMENT_START_EVENT).
+ tag_directives []yaml_tag_directive_t
+
+ // The comments
+ head_comment []byte
+ line_comment []byte
+ foot_comment []byte
+ tail_comment []byte
+
+ // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
+ anchor []byte
+
+ // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ tag []byte
+
+ // The scalar value (for yaml_SCALAR_EVENT).
+ value []byte
+
+ // Is the document start/end indicator implicit, or the tag optional?
+ // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
+ implicit bool
+
+ // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
+ quoted_implicit bool
+
+ // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
+ style yaml_style_t
+}
+
+func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
+func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
+func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
+
+// Nodes
+
+const (
+ yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
+ yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
+ yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
+ yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
+ yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
+ yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
+
+ yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
+ yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
+
+ // Not in original libyaml.
+ yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
+ yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
+
+ yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
+ yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
+ yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
+)
+
+type yaml_node_type_t int
+
+// Node types.
+const (
+ // An empty node.
+ yaml_NO_NODE yaml_node_type_t = iota
+
+ yaml_SCALAR_NODE // A scalar node.
+ yaml_SEQUENCE_NODE // A sequence node.
+ yaml_MAPPING_NODE // A mapping node.
+)
+
+// An element of a sequence node.
+type yaml_node_item_t int
+
+// An element of a mapping node.
+type yaml_node_pair_t struct {
+ key int // The key of the element.
+ value int // The value of the element.
+}
+
+// The node structure.
+type yaml_node_t struct {
+ typ yaml_node_type_t // The node type.
+ tag []byte // The node tag.
+
+ // The node data.
+
+ // The scalar parameters (for yaml_SCALAR_NODE).
+ scalar struct {
+ value []byte // The scalar value.
+ length int // The length of the scalar value.
+ style yaml_scalar_style_t // The scalar style.
+ }
+
+ // The sequence parameters (for YAML_SEQUENCE_NODE).
+ sequence struct {
+ items_data []yaml_node_item_t // The stack of sequence items.
+ style yaml_sequence_style_t // The sequence style.
+ }
+
+ // The mapping parameters (for yaml_MAPPING_NODE).
+ mapping struct {
+ pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
+ pairs_start *yaml_node_pair_t // The beginning of the stack.
+ pairs_end *yaml_node_pair_t // The end of the stack.
+ pairs_top *yaml_node_pair_t // The top of the stack.
+ style yaml_mapping_style_t // The mapping style.
+ }
+
+ start_mark yaml_mark_t // The beginning of the node.
+ end_mark yaml_mark_t // The end of the node.
+
+}
+
+// The document structure.
+type yaml_document_t struct {
+
+ // The document nodes.
+ nodes []yaml_node_t
+
+ // The version directive.
+ version_directive *yaml_version_directive_t
+
+ // The list of tag directives.
+ tag_directives_data []yaml_tag_directive_t
+ tag_directives_start int // The beginning of the tag directives list.
+ tag_directives_end int // The end of the tag directives list.
+
+ start_implicit int // Is the document start indicator implicit?
+ end_implicit int // Is the document end indicator implicit?
+
+ // The start/end of the document.
+ start_mark, end_mark yaml_mark_t
+}
+
+// The prototype of a read handler.
+//
+// The read handler is called when the parser needs to read more bytes from the
+// source. The handler should write not more than size bytes to the buffer.
+// The number of written bytes should be set to the size_read variable.
+//
+// [in,out] data A pointer to an application data specified by
+// yaml_parser_set_input().
+// [out] buffer The buffer to write the data from the source.
+// [in] size The size of the buffer.
+// [out] size_read The actual number of bytes read from the source.
+//
+// On success, the handler should return 1. If the handler failed,
+// the returned value should be 0. On EOF, the handler should set the
+// size_read to 0 and return 1.
+type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
+
+// This structure holds information about a potential simple key.
+type yaml_simple_key_t struct {
+ possible bool // Is a simple key possible?
+ required bool // Is a simple key required?
+ token_number int // The number of the token.
+ mark yaml_mark_t // The position mark.
+}
+
+// The states of the parser.
+type yaml_parser_state_t int
+
+const (
+ yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
+
+ yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
+ yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
+ yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
+ yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
+ yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
+ yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
+ yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
+ yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
+ yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
+ yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
+ yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
+ yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
+ yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
+ yaml_PARSE_END_STATE // Expect nothing.
+)
+
+func (ps yaml_parser_state_t) String() string {
+ switch ps {
+ case yaml_PARSE_STREAM_START_STATE:
+ return "yaml_PARSE_STREAM_START_STATE"
+ case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
+ return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_START_STATE:
+ return "yaml_PARSE_DOCUMENT_START_STATE"
+ case yaml_PARSE_DOCUMENT_CONTENT_STATE:
+ return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
+ case yaml_PARSE_DOCUMENT_END_STATE:
+ return "yaml_PARSE_DOCUMENT_END_STATE"
+ case yaml_PARSE_BLOCK_NODE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_STATE"
+ case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
+ return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
+ case yaml_PARSE_FLOW_NODE_STATE:
+ return "yaml_PARSE_FLOW_NODE_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
+ case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
+ return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
+ case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
+ case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
+ case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
+ return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
+ case yaml_PARSE_END_STATE:
+ return "yaml_PARSE_END_STATE"
+ }
+ return ""
+}
+
+// This structure holds aliases data.
+type yaml_alias_data_t struct {
+ anchor []byte // The anchor.
+ index int // The node id.
+ mark yaml_mark_t // The anchor mark.
+}
+
+// The parser structure.
+//
+// All members are internal. Manage the structure using the
+// yaml_parser_ family of functions.
+type yaml_parser_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+
+ problem string // Error description.
+
+ // The byte about which the problem occurred.
+ problem_offset int
+ problem_value int
+ problem_mark yaml_mark_t
+
+ // The error context.
+ context string
+ context_mark yaml_mark_t
+
+ // Reader stuff
+
+ read_handler yaml_read_handler_t // Read handler.
+
+ input_reader io.Reader // File input data.
+ input []byte // String input data.
+ input_pos int
+
+ eof bool // EOF flag
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ unread int // The number of unread characters in the buffer.
+
+ newlines int // The number of line breaks since last non-break/non-blank character
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The input encoding.
+
+ offset int // The offset of the current position (in bytes).
+ mark yaml_mark_t // The mark of the current position.
+
+ // Comments
+
+ head_comment []byte // The current head comments
+ line_comment []byte // The current line comments
+ foot_comment []byte // The current foot comments
+ tail_comment []byte // Foot comment that happens at the end of a block.
+ stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc)
+
+ comments []yaml_comment_t // The folded comments for all parsed tokens
+ comments_head int
+
+ // Scanner stuff
+
+ stream_start_produced bool // Have we started to scan the input stream?
+ stream_end_produced bool // Have we reached the end of the input stream?
+
+ flow_level int // The number of unclosed '[' and '{' indicators.
+
+ tokens []yaml_token_t // The tokens queue.
+ tokens_head int // The head of the tokens queue.
+ tokens_parsed int // The number of tokens fetched from the queue.
+ token_available bool // Does the tokens queue contain a token ready for dequeueing.
+
+ indent int // The current indentation level.
+ indents []int // The indentation levels stack.
+
+ simple_key_allowed bool // May a simple key occur at the current position?
+ simple_keys []yaml_simple_key_t // The stack of simple keys.
+ simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
+
+ // Parser stuff
+
+ state yaml_parser_state_t // The current parser state.
+ states []yaml_parser_state_t // The parser states stack.
+ marks []yaml_mark_t // The stack of marks.
+ tag_directives []yaml_tag_directive_t // The list of TAG directives.
+
+ // Dumper stuff
+
+ aliases []yaml_alias_data_t // The alias data.
+
+ document *yaml_document_t // The currently parsed document.
+}
+
+type yaml_comment_t struct {
+
+ scan_mark yaml_mark_t // Position where scanning for comments started
+ token_mark yaml_mark_t // Position after which tokens will be associated with this comment
+ start_mark yaml_mark_t // Position of '#' comment mark
+ end_mark yaml_mark_t // Position where comment terminated
+
+ head []byte
+ line []byte
+ foot []byte
+}
+
+// Emitter Definitions
+
+// The prototype of a write handler.
+//
+// The write handler is called when the emitter needs to flush the accumulated
+// characters to the output. The handler should write @a size bytes of the
+// @a buffer to the output.
+//
+// @param[in,out] data A pointer to an application data specified by
+// yaml_emitter_set_output().
+// @param[in] buffer The buffer with bytes to be written.
+// @param[in] size The size of the buffer.
+//
+// @returns On success, the handler should return @c 1. If the handler failed,
+// the returned value should be @c 0.
+//
+type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
+
+type yaml_emitter_state_t int
+
+// The emitter states.
+const (
+ // Expect STREAM-START.
+ yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
+
+ yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
+ yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
+ yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
+ yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
+ yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out
+ yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
+ yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out
+ yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
+ yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
+ yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
+ yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
+ yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
+ yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
+ yaml_EMIT_END_STATE // Expect nothing.
+)
+
+// The emitter structure.
+//
+// All members are internal. Manage the structure using the @c yaml_emitter_
+// family of functions.
+type yaml_emitter_t struct {
+
+ // Error handling
+
+ error yaml_error_type_t // Error type.
+ problem string // Error description.
+
+ // Writer stuff
+
+ write_handler yaml_write_handler_t // Write handler.
+
+ output_buffer *[]byte // String output data.
+ output_writer io.Writer // File output data.
+
+ buffer []byte // The working buffer.
+ buffer_pos int // The current position of the buffer.
+
+ raw_buffer []byte // The raw buffer.
+ raw_buffer_pos int // The current position of the buffer.
+
+ encoding yaml_encoding_t // The stream encoding.
+
+ // Emitter stuff
+
+ canonical bool // If the output is in the canonical style?
+ best_indent int // The number of indentation spaces.
+ best_width int // The preferred width of the output lines.
+ unicode bool // Allow unescaped non-ASCII characters?
+ line_break yaml_break_t // The preferred line break.
+
+ state yaml_emitter_state_t // The current emitter state.
+ states []yaml_emitter_state_t // The stack of states.
+
+ events []yaml_event_t // The event queue.
+ events_head int // The head of the event queue.
+
+ indents []int // The stack of indentation levels.
+
+ tag_directives []yaml_tag_directive_t // The list of tag directives.
+
+ indent int // The current indentation level.
+
+ flow_level int // The current flow level.
+
+ root_context bool // Is it the document root context?
+ sequence_context bool // Is it a sequence context?
+ mapping_context bool // Is it a mapping context?
+ simple_key_context bool // Is it a simple mapping key context?
+
+ line int // The current line.
+ column int // The current column.
+ whitespace bool // If the last character was a whitespace?
+ indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
+ open_ended bool // If an explicit document end is required?
+
+ space_above bool // Is there's an empty line above?
+ foot_indent int // The indent used to write the foot comment above, or -1 if none.
+
+ // Anchor analysis.
+ anchor_data struct {
+ anchor []byte // The anchor value.
+ alias bool // Is it an alias?
+ }
+
+ // Tag analysis.
+ tag_data struct {
+ handle []byte // The tag handle.
+ suffix []byte // The tag suffix.
+ }
+
+ // Scalar analysis.
+ scalar_data struct {
+ value []byte // The scalar value.
+ multiline bool // Does the scalar contain line breaks?
+ flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
+ block_plain_allowed bool // Can the scalar be expressed in the block plain style?
+ single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
+ block_allowed bool // Can the scalar be expressed in the literal or folded styles?
+ style yaml_scalar_style_t // The output style.
+ }
+
+ // Comments
+ head_comment []byte
+ line_comment []byte
+ foot_comment []byte
+ tail_comment []byte
+
+ key_line_comment []byte
+
+ // Dumper stuff
+
+ opened bool // If the stream was already opened?
+ closed bool // If the stream was already closed?
+
+ // The information associated with the document nodes.
+ anchors *struct {
+ references int // The number of references.
+ anchor int // The anchor id.
+ serialized bool // If the node has been emitted?
+ }
+
+ last_anchor_id int // The last assigned anchor id.
+
+ document *yaml_document_t // The currently emitted document.
+}
diff --git a/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
new file mode 100644
index 0000000..e88f9c5
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v3/yamlprivateh.go
@@ -0,0 +1,198 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+const (
+ // The size of the input raw buffer.
+ input_raw_buffer_size = 512
+
+ // The size of the input buffer.
+ // It should be possible to decode the whole raw buffer.
+ input_buffer_size = input_raw_buffer_size * 3
+
+ // The size of the output buffer.
+ output_buffer_size = 128
+
+ // The size of the output raw buffer.
+ // It should be possible to encode the whole output buffer.
+ output_raw_buffer_size = (output_buffer_size*2 + 2)
+
+ // The size of other stacks and queues.
+ initial_stack_size = 16
+ initial_queue_size = 16
+ initial_string_size = 16
+)
+
+// Check if the character at the specified position is an alphabetical
+// character, a digit, '_', or '-'.
+func is_alpha(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
+}
+
+// Check if the character at the specified position is a digit.
+func is_digit(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9'
+}
+
+// Get the value of a digit.
+func as_digit(b []byte, i int) int {
+ return int(b[i]) - '0'
+}
+
+// Check if the character at the specified position is a hex-digit.
+func is_hex(b []byte, i int) bool {
+ return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
+}
+
+// Get the value of a hex-digit.
+func as_hex(b []byte, i int) int {
+ bi := b[i]
+ if bi >= 'A' && bi <= 'F' {
+ return int(bi) - 'A' + 10
+ }
+ if bi >= 'a' && bi <= 'f' {
+ return int(bi) - 'a' + 10
+ }
+ return int(bi) - '0'
+}
+
+// Check if the character is ASCII.
+func is_ascii(b []byte, i int) bool {
+ return b[i] <= 0x7F
+}
+
+// Check if the character at the start of the buffer can be printed unescaped.
+func is_printable(b []byte, i int) bool {
+ return ((b[i] == 0x0A) || // . == #x0A
+ (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
+ (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
+ (b[i] > 0xC2 && b[i] < 0xED) ||
+ (b[i] == 0xED && b[i+1] < 0xA0) ||
+ (b[i] == 0xEE) ||
+ (b[i] == 0xEF && // #xE000 <= . <= #xFFFD
+ !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
+ !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
+}
+
+// Check if the character at the specified position is NUL.
+func is_z(b []byte, i int) bool {
+ return b[i] == 0x00
+}
+
+// Check if the beginning of the buffer is a BOM.
+func is_bom(b []byte, i int) bool {
+ return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
+}
+
+// Check if the character at the specified position is space.
+func is_space(b []byte, i int) bool {
+ return b[i] == ' '
+}
+
+// Check if the character at the specified position is tab.
+func is_tab(b []byte, i int) bool {
+ return b[i] == '\t'
+}
+
+// Check if the character at the specified position is blank (space or tab).
+func is_blank(b []byte, i int) bool {
+ //return is_space(b, i) || is_tab(b, i)
+ return b[i] == ' ' || b[i] == '\t'
+}
+
+// Check if the character at the specified position is a line break.
+func is_break(b []byte, i int) bool {
+ return (b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
+}
+
+func is_crlf(b []byte, i int) bool {
+ return b[i] == '\r' && b[i+1] == '\n'
+}
+
+// Check if the character is a line break or NUL.
+func is_breakz(b []byte, i int) bool {
+ //return is_break(b, i) || is_z(b, i)
+ return (
+ // is_break:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ // is_z:
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, or NUL.
+func is_spacez(b []byte, i int) bool {
+ //return is_space(b, i) || is_breakz(b, i)
+ return (
+ // is_space:
+ b[i] == ' ' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Check if the character is a line break, space, tab, or NUL.
+func is_blankz(b []byte, i int) bool {
+ //return is_blank(b, i) || is_breakz(b, i)
+ return (
+ // is_blank:
+ b[i] == ' ' || b[i] == '\t' ||
+ // is_breakz:
+ b[i] == '\r' || // CR (#xD)
+ b[i] == '\n' || // LF (#xA)
+ b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
+ b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
+ b[i] == 0)
+}
+
+// Determine the width of the character.
+func width(b byte) int {
+ // Don't replace these by a switch without first
+ // confirming that it is being inlined.
+ if b&0x80 == 0x00 {
+ return 1
+ }
+ if b&0xE0 == 0xC0 {
+ return 2
+ }
+ if b&0xF0 == 0xE0 {
+ return 3
+ }
+ if b&0xF8 == 0xF0 {
+ return 4
+ }
+ return 0
+
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
new file mode 100644
index 0000000..0bef97d
--- /dev/null
+++ b/vendor/modules.txt
@@ -0,0 +1,23 @@
+# github.com/yuin/goldmark v1.4.12
+## explicit; go 1.18
+github.com/yuin/goldmark
+github.com/yuin/goldmark/ast
+github.com/yuin/goldmark/extension
+github.com/yuin/goldmark/extension/ast
+github.com/yuin/goldmark/parser
+github.com/yuin/goldmark/renderer
+github.com/yuin/goldmark/renderer/html
+github.com/yuin/goldmark/text
+github.com/yuin/goldmark/util
+# github.com/yuin/goldmark-meta v1.1.0
+## explicit; go 1.17
+github.com/yuin/goldmark-meta
+# gopkg.in/yaml.v2 v2.3.0
+## explicit
+gopkg.in/yaml.v2
+# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
+## explicit
+gopkg.in/yaml.v3
+# mvdan.cc/xurls/v2 v2.4.0
+## explicit; go 1.16
+mvdan.cc/xurls/v2
diff --git a/vendor/mvdan.cc/xurls/v2/.gitattributes b/vendor/mvdan.cc/xurls/v2/.gitattributes
new file mode 100644
index 0000000..6f95229
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/.gitattributes
@@ -0,0 +1,2 @@
+# To prevent CRLF breakages on Windows for fragile files, like testdata.
+* -text
diff --git a/vendor/mvdan.cc/xurls/v2/.gitignore b/vendor/mvdan.cc/xurls/v2/.gitignore
new file mode 100644
index 0000000..663c8cb
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/.gitignore
@@ -0,0 +1,3 @@
+cmd/xurls/xurls
+generate/tldsgen/tldsgen
+generate/regexgen/regexgen
diff --git a/vendor/mvdan.cc/xurls/v2/LICENSE b/vendor/mvdan.cc/xurls/v2/LICENSE
new file mode 100644
index 0000000..7d71d51
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2015, Daniel Martí. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of the copyright holder nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/mvdan.cc/xurls/v2/README.md b/vendor/mvdan.cc/xurls/v2/README.md
new file mode 100644
index 0000000..40b0cdc
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/README.md
@@ -0,0 +1,37 @@
+# xurls
+
+[![Go Reference](https://pkg.go.dev/badge/mvdan.cc/xurls/v2.svg)](https://pkg.go.dev/mvdan.cc/xurls/v2)
+
+Extract urls from text using regular expressions. Requires Go 1.16 or later.
+
+```go
+import "mvdan.cc/xurls/v2"
+
+func main() {
+ rxRelaxed := xurls.Relaxed()
+ rxRelaxed.FindString("Do gophers live in golang.org?") // "golang.org"
+ rxRelaxed.FindString("This string does not have a URL") // ""
+
+ rxStrict := xurls.Strict()
+ rxStrict.FindAllString("must have scheme: http://foo.com/.", -1) // []string{"http://foo.com/"}
+ rxStrict.FindAllString("no scheme, no match: foo.com", -1) // []string{}
+}
+```
+
+Since API is centered around [regexp.Regexp](https://golang.org/pkg/regexp/#Regexp),
+many other methods are available, such as finding the [byte indexes](https://golang.org/pkg/regexp/#Regexp.FindAllIndex)
+for all matches.
+
+The regular expressions are compiled when the API is first called.
+Any subsequent calls will use the same regular expression pointers.
+
+#### cmd/xurls
+
+To install the tool globally:
+
+ go install mvdan.cc/xurls/v2/cmd/xurls@latest
+
+```shell
+$ echo "Do gophers live in http://golang.org?" | xurls
+http://golang.org
+```
diff --git a/vendor/mvdan.cc/xurls/v2/schemes.go b/vendor/mvdan.cc/xurls/v2/schemes.go
new file mode 100644
index 0000000..bff9862
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/schemes.go
@@ -0,0 +1,360 @@
+// Generated by schemesgen
+
+package xurls
+
+// Schemes is a sorted list of all IANA assigned schemes.
+//
+// Source:
+// https://www.iana.org/assignments/uri-schemes/uri-schemes-1.csv
+var Schemes = []string{
+ `aaa`,
+ `aaas`,
+ `about`,
+ `acap`,
+ `acct`,
+ `acd`,
+ `acr`,
+ `adiumxtra`,
+ `adt`,
+ `afp`,
+ `afs`,
+ `aim`,
+ `amss`,
+ `android`,
+ `appdata`,
+ `apt`,
+ `ar`,
+ `ark`,
+ `attachment`,
+ `aw`,
+ `barion`,
+ `beshare`,
+ `bitcoin`,
+ `bitcoincash`,
+ `blob`,
+ `bolo`,
+ `browserext`,
+ `cabal`,
+ `calculator`,
+ `callto`,
+ `cap`,
+ `cast`,
+ `casts`,
+ `chrome`,
+ `chrome-extension`,
+ `cid`,
+ `coap`,
+ `coap+tcp`,
+ `coap+ws`,
+ `coaps`,
+ `coaps+tcp`,
+ `coaps+ws`,
+ `com-eventbrite-attendee`,
+ `content`,
+ `content-type`,
+ `crid`,
+ `cvs`,
+ `dab`,
+ `dat`,
+ `data`,
+ `dav`,
+ `diaspora`,
+ `dict`,
+ `did`,
+ `dis`,
+ `dlna-playcontainer`,
+ `dlna-playsingle`,
+ `dns`,
+ `dntp`,
+ `doi`,
+ `dpp`,
+ `drm`,
+ `drop`,
+ `dtmi`,
+ `dtn`,
+ `dvb`,
+ `dvx`,
+ `dweb`,
+ `ed2k`,
+ `elsi`,
+ `embedded`,
+ `ens`,
+ `ethereum`,
+ `example`,
+ `facetime`,
+ `fax`,
+ `feed`,
+ `feedready`,
+ `fido`,
+ `file`,
+ `filesystem`,
+ `finger`,
+ `first-run-pen-experience`,
+ `fish`,
+ `fm`,
+ `ftp`,
+ `fuchsia-pkg`,
+ `geo`,
+ `gg`,
+ `git`,
+ `gizmoproject`,
+ `go`,
+ `gopher`,
+ `graph`,
+ `gtalk`,
+ `h323`,
+ `ham`,
+ `hcap`,
+ `hcp`,
+ `http`,
+ `https`,
+ `hxxp`,
+ `hxxps`,
+ `hydrazone`,
+ `hyper`,
+ `iax`,
+ `icap`,
+ `icon`,
+ `im`,
+ `imap`,
+ `info`,
+ `iotdisco`,
+ `ipfs`,
+ `ipn`,
+ `ipns`,
+ `ipp`,
+ `ipps`,
+ `irc`,
+ `irc6`,
+ `ircs`,
+ `iris`,
+ `iris.beep`,
+ `iris.lwz`,
+ `iris.xpc`,
+ `iris.xpcs`,
+ `isostore`,
+ `itms`,
+ `jabber`,
+ `jar`,
+ `jms`,
+ `keyparc`,
+ `lastfm`,
+ `lbry`,
+ `ldap`,
+ `ldaps`,
+ `leaptofrogans`,
+ `lorawan`,
+ `lvlt`,
+ `magnet`,
+ `mailserver`,
+ `mailto`,
+ `maps`,
+ `market`,
+ `matrix`,
+ `message`,
+ `microsoft.windows.camera`,
+ `microsoft.windows.camera.multipicker`,
+ `microsoft.windows.camera.picker`,
+ `mid`,
+ `mms`,
+ `modem`,
+ `mongodb`,
+ `moz`,
+ `ms-access`,
+ `ms-browser-extension`,
+ `ms-calculator`,
+ `ms-drive-to`,
+ `ms-enrollment`,
+ `ms-excel`,
+ `ms-eyecontrolspeech`,
+ `ms-gamebarservices`,
+ `ms-gamingoverlay`,
+ `ms-getoffice`,
+ `ms-help`,
+ `ms-infopath`,
+ `ms-inputapp`,
+ `ms-lockscreencomponent-config`,
+ `ms-media-stream-id`,
+ `ms-meetnow`,
+ `ms-mixedrealitycapture`,
+ `ms-mobileplans`,
+ `ms-officeapp`,
+ `ms-people`,
+ `ms-project`,
+ `ms-powerpoint`,
+ `ms-publisher`,
+ `ms-restoretabcompanion`,
+ `ms-screenclip`,
+ `ms-screensketch`,
+ `ms-search`,
+ `ms-search-repair`,
+ `ms-secondary-screen-controller`,
+ `ms-secondary-screen-setup`,
+ `ms-settings`,
+ `ms-settings-airplanemode`,
+ `ms-settings-bluetooth`,
+ `ms-settings-camera`,
+ `ms-settings-cellular`,
+ `ms-settings-cloudstorage`,
+ `ms-settings-connectabledevices`,
+ `ms-settings-displays-topology`,
+ `ms-settings-emailandaccounts`,
+ `ms-settings-language`,
+ `ms-settings-location`,
+ `ms-settings-lock`,
+ `ms-settings-nfctransactions`,
+ `ms-settings-notifications`,
+ `ms-settings-power`,
+ `ms-settings-privacy`,
+ `ms-settings-proximity`,
+ `ms-settings-screenrotation`,
+ `ms-settings-wifi`,
+ `ms-settings-workplace`,
+ `ms-spd`,
+ `ms-stickers`,
+ `ms-sttoverlay`,
+ `ms-transit-to`,
+ `ms-useractivityset`,
+ `ms-virtualtouchpad`,
+ `ms-visio`,
+ `ms-walk-to`,
+ `ms-whiteboard`,
+ `ms-whiteboard-cmd`,
+ `ms-word`,
+ `msnim`,
+ `msrp`,
+ `msrps`,
+ `mss`,
+ `mt`,
+ `mtqp`,
+ `mumble`,
+ `mupdate`,
+ `mvn`,
+ `news`,
+ `nfs`,
+ `ni`,
+ `nih`,
+ `nntp`,
+ `notes`,
+ `num`,
+ `ocf`,
+ `oid`,
+ `onenote`,
+ `onenote-cmd`,
+ `opaquelocktoken`,
+ `openpgp4fpr`,
+ `otpauth`,
+ `pack`,
+ `palm`,
+ `paparazzi`,
+ `payment`,
+ `payto`,
+ `pkcs11`,
+ `platform`,
+ `pop`,
+ `pres`,
+ `prospero`,
+ `proxy`,
+ `pwid`,
+ `psyc`,
+ `pttp`,
+ `qb`,
+ `query`,
+ `quic-transport`,
+ `redis`,
+ `rediss`,
+ `reload`,
+ `res`,
+ `resource`,
+ `rmi`,
+ `rsync`,
+ `rtmfp`,
+ `rtmp`,
+ `rtsp`,
+ `rtsps`,
+ `rtspu`,
+ `sarif`,
+ `secondlife`,
+ `secret-token`,
+ `service`,
+ `session`,
+ `sftp`,
+ `sgn`,
+ `shc`,
+ `sieve`,
+ `simpleledger`,
+ `simplex`,
+ `sip`,
+ `sips`,
+ `skype`,
+ `smb`,
+ `smp`,
+ `sms`,
+ `smtp`,
+ `snews`,
+ `snmp`,
+ `soap.beep`,
+ `soap.beeps`,
+ `soldat`,
+ `spiffe`,
+ `spotify`,
+ `ssb`,
+ `ssh`,
+ `steam`,
+ `stun`,
+ `stuns`,
+ `submit`,
+ `svn`,
+ `swh`,
+ `swid`,
+ `swidpath`,
+ `tag`,
+ `teamspeak`,
+ `tel`,
+ `teliaeid`,
+ `telnet`,
+ `tftp`,
+ `things`,
+ `thismessage`,
+ `tip`,
+ `tn3270`,
+ `tool`,
+ `turn`,
+ `turns`,
+ `tv`,
+ `udp`,
+ `unreal`,
+ `urn`,
+ `ut2004`,
+ `uuid-in-package`,
+ `v-event`,
+ `vemmi`,
+ `ventrilo`,
+ `ves`,
+ `videotex`,
+ `vnc`,
+ `view-source`,
+ `vscode`,
+ `vscode-insiders`,
+ `vsls`,
+ `wais`,
+ `wcr`,
+ `webcal`,
+ `wifi`,
+ `wpid`,
+ `ws`,
+ `wss`,
+ `wtai`,
+ `wyciwyg`,
+ `xcon`,
+ `xcon-userid`,
+ `xfire`,
+ `xmlrpc.beep`,
+ `xmlrpc.beeps`,
+ `xmpp`,
+ `xri`,
+ `ymsgr`,
+ `z39.50`,
+ `z39.50r`,
+ `z39.50s`,
+}
diff --git a/vendor/mvdan.cc/xurls/v2/tlds.go b/vendor/mvdan.cc/xurls/v2/tlds.go
new file mode 100644
index 0000000..eb87f27
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/tlds.go
@@ -0,0 +1,1507 @@
+// Generated by tldsgen
+
+package xurls
+
+// TLDs is a sorted list of all public top-level domains.
+//
+// Sources:
+// * https://data.iana.org/TLD/tlds-alpha-by-domain.txt
+// * https://publicsuffix.org/list/effective_tld_names.dat
+var TLDs = []string{
+ `aaa`,
+ `aarp`,
+ `abarth`,
+ `abb`,
+ `abbott`,
+ `abbvie`,
+ `abc`,
+ `able`,
+ `abogado`,
+ `abudhabi`,
+ `ac`,
+ `academy`,
+ `accenture`,
+ `accountant`,
+ `accountants`,
+ `aco`,
+ `actor`,
+ `ad`,
+ `adac`,
+ `ads`,
+ `adult`,
+ `ae`,
+ `aeg`,
+ `aero`,
+ `aetna`,
+ `af`,
+ `afl`,
+ `africa`,
+ `ag`,
+ `agakhan`,
+ `agency`,
+ `ai`,
+ `aig`,
+ `airbus`,
+ `airforce`,
+ `airtel`,
+ `akdn`,
+ `al`,
+ `alfaromeo`,
+ `alibaba`,
+ `alipay`,
+ `allfinanz`,
+ `allstate`,
+ `ally`,
+ `alsace`,
+ `alstom`,
+ `am`,
+ `amazon`,
+ `americanexpress`,
+ `americanfamily`,
+ `amex`,
+ `amfam`,
+ `amica`,
+ `amsterdam`,
+ `analytics`,
+ `android`,
+ `anquan`,
+ `anz`,
+ `ao`,
+ `aol`,
+ `apartments`,
+ `app`,
+ `apple`,
+ `aq`,
+ `aquarelle`,
+ `ar`,
+ `arab`,
+ `aramco`,
+ `archi`,
+ `army`,
+ `arpa`,
+ `art`,
+ `arte`,
+ `as`,
+ `asda`,
+ `asia`,
+ `associates`,
+ `at`,
+ `athleta`,
+ `attorney`,
+ `au`,
+ `auction`,
+ `audi`,
+ `audible`,
+ `audio`,
+ `auspost`,
+ `author`,
+ `auto`,
+ `autos`,
+ `avianca`,
+ `aw`,
+ `aws`,
+ `ax`,
+ `axa`,
+ `az`,
+ `azure`,
+ `ba`,
+ `baby`,
+ `baidu`,
+ `banamex`,
+ `bananarepublic`,
+ `band`,
+ `bank`,
+ `bar`,
+ `barcelona`,
+ `barclaycard`,
+ `barclays`,
+ `barefoot`,
+ `bargains`,
+ `baseball`,
+ `basketball`,
+ `bauhaus`,
+ `bayern`,
+ `bb`,
+ `bbc`,
+ `bbt`,
+ `bbva`,
+ `bcg`,
+ `bcn`,
+ `bd`,
+ `be`,
+ `beats`,
+ `beauty`,
+ `beer`,
+ `bentley`,
+ `berlin`,
+ `best`,
+ `bestbuy`,
+ `bet`,
+ `bf`,
+ `bg`,
+ `bh`,
+ `bharti`,
+ `bi`,
+ `bible`,
+ `bid`,
+ `bike`,
+ `bing`,
+ `bingo`,
+ `bio`,
+ `biz`,
+ `bj`,
+ `black`,
+ `blackfriday`,
+ `blockbuster`,
+ `blog`,
+ `bloomberg`,
+ `blue`,
+ `bm`,
+ `bms`,
+ `bmw`,
+ `bn`,
+ `bnpparibas`,
+ `bo`,
+ `boats`,
+ `boehringer`,
+ `bofa`,
+ `bom`,
+ `bond`,
+ `boo`,
+ `book`,
+ `booking`,
+ `bosch`,
+ `bostik`,
+ `boston`,
+ `bot`,
+ `boutique`,
+ `box`,
+ `br`,
+ `bradesco`,
+ `bridgestone`,
+ `broadway`,
+ `broker`,
+ `brother`,
+ `brussels`,
+ `bs`,
+ `bt`,
+ `bugatti`,
+ `build`,
+ `builders`,
+ `business`,
+ `buy`,
+ `buzz`,
+ `bv`,
+ `bw`,
+ `by`,
+ `bz`,
+ `bzh`,
+ `ca`,
+ `cab`,
+ `cafe`,
+ `cal`,
+ `call`,
+ `calvinklein`,
+ `cam`,
+ `camera`,
+ `camp`,
+ `cancerresearch`,
+ `canon`,
+ `capetown`,
+ `capital`,
+ `capitalone`,
+ `car`,
+ `caravan`,
+ `cards`,
+ `care`,
+ `career`,
+ `careers`,
+ `cars`,
+ `casa`,
+ `case`,
+ `cash`,
+ `casino`,
+ `cat`,
+ `catering`,
+ `catholic`,
+ `cba`,
+ `cbn`,
+ `cbre`,
+ `cbs`,
+ `cc`,
+ `cd`,
+ `center`,
+ `ceo`,
+ `cern`,
+ `cf`,
+ `cfa`,
+ `cfd`,
+ `cg`,
+ `ch`,
+ `chanel`,
+ `channel`,
+ `charity`,
+ `chase`,
+ `chat`,
+ `cheap`,
+ `chintai`,
+ `christmas`,
+ `chrome`,
+ `church`,
+ `ci`,
+ `cipriani`,
+ `circle`,
+ `cisco`,
+ `citadel`,
+ `citi`,
+ `citic`,
+ `city`,
+ `cityeats`,
+ `ck`,
+ `cl`,
+ `claims`,
+ `cleaning`,
+ `click`,
+ `clinic`,
+ `clinique`,
+ `clothing`,
+ `cloud`,
+ `club`,
+ `clubmed`,
+ `cm`,
+ `cn`,
+ `co`,
+ `coach`,
+ `codes`,
+ `coffee`,
+ `college`,
+ `cologne`,
+ `com`,
+ `comcast`,
+ `commbank`,
+ `community`,
+ `company`,
+ `compare`,
+ `computer`,
+ `comsec`,
+ `condos`,
+ `construction`,
+ `consulting`,
+ `contact`,
+ `contractors`,
+ `cooking`,
+ `cookingchannel`,
+ `cool`,
+ `coop`,
+ `corsica`,
+ `country`,
+ `coupon`,
+ `coupons`,
+ `courses`,
+ `cpa`,
+ `cr`,
+ `credit`,
+ `creditcard`,
+ `creditunion`,
+ `cricket`,
+ `crown`,
+ `crs`,
+ `cruise`,
+ `cruises`,
+ `cu`,
+ `cuisinella`,
+ `cv`,
+ `cw`,
+ `cx`,
+ `cy`,
+ `cymru`,
+ `cyou`,
+ `cz`,
+ `dabur`,
+ `dad`,
+ `dance`,
+ `data`,
+ `date`,
+ `dating`,
+ `datsun`,
+ `day`,
+ `dclk`,
+ `dds`,
+ `de`,
+ `deal`,
+ `dealer`,
+ `deals`,
+ `degree`,
+ `delivery`,
+ `dell`,
+ `deloitte`,
+ `delta`,
+ `democrat`,
+ `dental`,
+ `dentist`,
+ `desi`,
+ `design`,
+ `dev`,
+ `dhl`,
+ `diamonds`,
+ `diet`,
+ `digital`,
+ `direct`,
+ `directory`,
+ `discount`,
+ `discover`,
+ `dish`,
+ `diy`,
+ `dj`,
+ `dk`,
+ `dm`,
+ `dnp`,
+ `do`,
+ `docs`,
+ `doctor`,
+ `dog`,
+ `domains`,
+ `dot`,
+ `download`,
+ `drive`,
+ `dtv`,
+ `dubai`,
+ `dunlop`,
+ `dupont`,
+ `durban`,
+ `dvag`,
+ `dvr`,
+ `dz`,
+ `earth`,
+ `eat`,
+ `ec`,
+ `eco`,
+ `edeka`,
+ `edu`,
+ `education`,
+ `ee`,
+ `eg`,
+ `email`,
+ `emerck`,
+ `energy`,
+ `engineer`,
+ `engineering`,
+ `enterprises`,
+ `epson`,
+ `equipment`,
+ `er`,
+ `ericsson`,
+ `erni`,
+ `es`,
+ `esq`,
+ `estate`,
+ `et`,
+ `etisalat`,
+ `eu`,
+ `eurovision`,
+ `eus`,
+ `events`,
+ `exchange`,
+ `expert`,
+ `exposed`,
+ `express`,
+ `extraspace`,
+ `fage`,
+ `fail`,
+ `fairwinds`,
+ `faith`,
+ `family`,
+ `fan`,
+ `fans`,
+ `farm`,
+ `farmers`,
+ `fashion`,
+ `fast`,
+ `fedex`,
+ `feedback`,
+ `ferrari`,
+ `ferrero`,
+ `fi`,
+ `fiat`,
+ `fidelity`,
+ `fido`,
+ `film`,
+ `final`,
+ `finance`,
+ `financial`,
+ `fire`,
+ `firestone`,
+ `firmdale`,
+ `fish`,
+ `fishing`,
+ `fit`,
+ `fitness`,
+ `fj`,
+ `fk`,
+ `flickr`,
+ `flights`,
+ `flir`,
+ `florist`,
+ `flowers`,
+ `fly`,
+ `fm`,
+ `fo`,
+ `foo`,
+ `food`,
+ `foodnetwork`,
+ `football`,
+ `ford`,
+ `forex`,
+ `forsale`,
+ `forum`,
+ `foundation`,
+ `fox`,
+ `fr`,
+ `free`,
+ `fresenius`,
+ `frl`,
+ `frogans`,
+ `frontdoor`,
+ `frontier`,
+ `ftr`,
+ `fujitsu`,
+ `fun`,
+ `fund`,
+ `furniture`,
+ `futbol`,
+ `fyi`,
+ `ga`,
+ `gal`,
+ `gallery`,
+ `gallo`,
+ `gallup`,
+ `game`,
+ `games`,
+ `gap`,
+ `garden`,
+ `gay`,
+ `gb`,
+ `gbiz`,
+ `gd`,
+ `gdn`,
+ `ge`,
+ `gea`,
+ `gent`,
+ `genting`,
+ `george`,
+ `gf`,
+ `gg`,
+ `ggee`,
+ `gh`,
+ `gi`,
+ `gift`,
+ `gifts`,
+ `gives`,
+ `giving`,
+ `gl`,
+ `glass`,
+ `gle`,
+ `global`,
+ `globo`,
+ `gm`,
+ `gmail`,
+ `gmbh`,
+ `gmo`,
+ `gmx`,
+ `gn`,
+ `godaddy`,
+ `gold`,
+ `goldpoint`,
+ `golf`,
+ `goo`,
+ `goodyear`,
+ `goog`,
+ `google`,
+ `gop`,
+ `got`,
+ `gov`,
+ `gp`,
+ `gq`,
+ `gr`,
+ `grainger`,
+ `graphics`,
+ `gratis`,
+ `green`,
+ `gripe`,
+ `grocery`,
+ `group`,
+ `gs`,
+ `gt`,
+ `gu`,
+ `guardian`,
+ `gucci`,
+ `guge`,
+ `guide`,
+ `guitars`,
+ `guru`,
+ `gw`,
+ `gy`,
+ `hair`,
+ `hamburg`,
+ `hangout`,
+ `haus`,
+ `hbo`,
+ `hdfc`,
+ `hdfcbank`,
+ `health`,
+ `healthcare`,
+ `help`,
+ `helsinki`,
+ `here`,
+ `hermes`,
+ `hgtv`,
+ `hiphop`,
+ `hisamitsu`,
+ `hitachi`,
+ `hiv`,
+ `hk`,
+ `hkt`,
+ `hm`,
+ `hn`,
+ `hockey`,
+ `holdings`,
+ `holiday`,
+ `homedepot`,
+ `homegoods`,
+ `homes`,
+ `homesense`,
+ `honda`,
+ `horse`,
+ `hospital`,
+ `host`,
+ `hosting`,
+ `hot`,
+ `hoteles`,
+ `hotels`,
+ `hotmail`,
+ `house`,
+ `how`,
+ `hr`,
+ `hsbc`,
+ `ht`,
+ `hu`,
+ `hughes`,
+ `hyatt`,
+ `hyundai`,
+ `ibm`,
+ `icbc`,
+ `ice`,
+ `icu`,
+ `id`,
+ `ie`,
+ `ieee`,
+ `ifm`,
+ `ikano`,
+ `il`,
+ `im`,
+ `imamat`,
+ `imdb`,
+ `immo`,
+ `immobilien`,
+ `in`,
+ `inc`,
+ `industries`,
+ `infiniti`,
+ `info`,
+ `ing`,
+ `ink`,
+ `institute`,
+ `insurance`,
+ `insure`,
+ `int`,
+ `international`,
+ `intuit`,
+ `investments`,
+ `io`,
+ `ipiranga`,
+ `iq`,
+ `ir`,
+ `irish`,
+ `is`,
+ `ismaili`,
+ `ist`,
+ `istanbul`,
+ `it`,
+ `itau`,
+ `itv`,
+ `jaguar`,
+ `java`,
+ `jcb`,
+ `je`,
+ `jeep`,
+ `jetzt`,
+ `jewelry`,
+ `jio`,
+ `jll`,
+ `jm`,
+ `jmp`,
+ `jnj`,
+ `jo`,
+ `jobs`,
+ `joburg`,
+ `jot`,
+ `joy`,
+ `jp`,
+ `jpmorgan`,
+ `jprs`,
+ `juegos`,
+ `juniper`,
+ `kaufen`,
+ `kddi`,
+ `ke`,
+ `kerryhotels`,
+ `kerrylogistics`,
+ `kerryproperties`,
+ `kfh`,
+ `kg`,
+ `kh`,
+ `ki`,
+ `kia`,
+ `kids`,
+ `kim`,
+ `kinder`,
+ `kindle`,
+ `kitchen`,
+ `kiwi`,
+ `km`,
+ `kn`,
+ `koeln`,
+ `komatsu`,
+ `kosher`,
+ `kp`,
+ `kpmg`,
+ `kpn`,
+ `kr`,
+ `krd`,
+ `kred`,
+ `kuokgroup`,
+ `kw`,
+ `ky`,
+ `kyoto`,
+ `kz`,
+ `la`,
+ `lacaixa`,
+ `lamborghini`,
+ `lamer`,
+ `lancaster`,
+ `lancia`,
+ `land`,
+ `landrover`,
+ `lanxess`,
+ `lasalle`,
+ `lat`,
+ `latino`,
+ `latrobe`,
+ `law`,
+ `lawyer`,
+ `lb`,
+ `lc`,
+ `lds`,
+ `lease`,
+ `leclerc`,
+ `lefrak`,
+ `legal`,
+ `lego`,
+ `lexus`,
+ `lgbt`,
+ `li`,
+ `lidl`,
+ `life`,
+ `lifeinsurance`,
+ `lifestyle`,
+ `lighting`,
+ `like`,
+ `lilly`,
+ `limited`,
+ `limo`,
+ `lincoln`,
+ `linde`,
+ `link`,
+ `lipsy`,
+ `live`,
+ `living`,
+ `lk`,
+ `llc`,
+ `llp`,
+ `loan`,
+ `loans`,
+ `locker`,
+ `locus`,
+ `loft`,
+ `lol`,
+ `london`,
+ `lotte`,
+ `lotto`,
+ `love`,
+ `lpl`,
+ `lplfinancial`,
+ `lr`,
+ `ls`,
+ `lt`,
+ `ltd`,
+ `ltda`,
+ `lu`,
+ `lundbeck`,
+ `luxe`,
+ `luxury`,
+ `lv`,
+ `ly`,
+ `ma`,
+ `macys`,
+ `madrid`,
+ `maif`,
+ `maison`,
+ `makeup`,
+ `man`,
+ `management`,
+ `mango`,
+ `map`,
+ `market`,
+ `marketing`,
+ `markets`,
+ `marriott`,
+ `marshalls`,
+ `maserati`,
+ `mattel`,
+ `mba`,
+ `mc`,
+ `mckinsey`,
+ `md`,
+ `me`,
+ `med`,
+ `media`,
+ `meet`,
+ `melbourne`,
+ `meme`,
+ `memorial`,
+ `men`,
+ `menu`,
+ `merckmsd`,
+ `mg`,
+ `mh`,
+ `miami`,
+ `microsoft`,
+ `mil`,
+ `mini`,
+ `mint`,
+ `mit`,
+ `mitsubishi`,
+ `mk`,
+ `ml`,
+ `mlb`,
+ `mls`,
+ `mm`,
+ `mma`,
+ `mn`,
+ `mo`,
+ `mobi`,
+ `mobile`,
+ `moda`,
+ `moe`,
+ `moi`,
+ `mom`,
+ `monash`,
+ `money`,
+ `monster`,
+ `mormon`,
+ `mortgage`,
+ `moscow`,
+ `moto`,
+ `motorcycles`,
+ `mov`,
+ `movie`,
+ `mp`,
+ `mq`,
+ `mr`,
+ `ms`,
+ `msd`,
+ `mt`,
+ `mtn`,
+ `mtr`,
+ `mu`,
+ `museum`,
+ `music`,
+ `mutual`,
+ `mv`,
+ `mw`,
+ `mx`,
+ `my`,
+ `mz`,
+ `na`,
+ `nab`,
+ `nagoya`,
+ `name`,
+ `natura`,
+ `navy`,
+ `nba`,
+ `nc`,
+ `ne`,
+ `nec`,
+ `net`,
+ `netbank`,
+ `netflix`,
+ `network`,
+ `neustar`,
+ `new`,
+ `news`,
+ `next`,
+ `nextdirect`,
+ `nexus`,
+ `nf`,
+ `nfl`,
+ `ng`,
+ `ngo`,
+ `nhk`,
+ `ni`,
+ `nico`,
+ `nike`,
+ `nikon`,
+ `ninja`,
+ `nissan`,
+ `nissay`,
+ `nl`,
+ `no`,
+ `nokia`,
+ `northwesternmutual`,
+ `norton`,
+ `now`,
+ `nowruz`,
+ `nowtv`,
+ `np`,
+ `nr`,
+ `nra`,
+ `nrw`,
+ `ntt`,
+ `nu`,
+ `nyc`,
+ `nz`,
+ `obi`,
+ `observer`,
+ `office`,
+ `okinawa`,
+ `olayan`,
+ `olayangroup`,
+ `oldnavy`,
+ `ollo`,
+ `om`,
+ `omega`,
+ `one`,
+ `ong`,
+ `onion`,
+ `onl`,
+ `online`,
+ `ooo`,
+ `open`,
+ `oracle`,
+ `orange`,
+ `org`,
+ `organic`,
+ `origins`,
+ `osaka`,
+ `otsuka`,
+ `ott`,
+ `ovh`,
+ `pa`,
+ `page`,
+ `panasonic`,
+ `paris`,
+ `pars`,
+ `partners`,
+ `parts`,
+ `party`,
+ `passagens`,
+ `pay`,
+ `pccw`,
+ `pe`,
+ `pet`,
+ `pf`,
+ `pfizer`,
+ `pg`,
+ `ph`,
+ `pharmacy`,
+ `phd`,
+ `philips`,
+ `phone`,
+ `photo`,
+ `photography`,
+ `photos`,
+ `physio`,
+ `pics`,
+ `pictet`,
+ `pictures`,
+ `pid`,
+ `pin`,
+ `ping`,
+ `pink`,
+ `pioneer`,
+ `pizza`,
+ `pk`,
+ `pl`,
+ `place`,
+ `play`,
+ `playstation`,
+ `plumbing`,
+ `plus`,
+ `pm`,
+ `pn`,
+ `pnc`,
+ `pohl`,
+ `poker`,
+ `politie`,
+ `porn`,
+ `post`,
+ `pr`,
+ `pramerica`,
+ `praxi`,
+ `press`,
+ `prime`,
+ `pro`,
+ `prod`,
+ `productions`,
+ `prof`,
+ `progressive`,
+ `promo`,
+ `properties`,
+ `property`,
+ `protection`,
+ `pru`,
+ `prudential`,
+ `ps`,
+ `pt`,
+ `pub`,
+ `pw`,
+ `pwc`,
+ `py`,
+ `qa`,
+ `qpon`,
+ `quebec`,
+ `quest`,
+ `racing`,
+ `radio`,
+ `re`,
+ `read`,
+ `realestate`,
+ `realtor`,
+ `realty`,
+ `recipes`,
+ `red`,
+ `redstone`,
+ `redumbrella`,
+ `rehab`,
+ `reise`,
+ `reisen`,
+ `reit`,
+ `reliance`,
+ `ren`,
+ `rent`,
+ `rentals`,
+ `repair`,
+ `report`,
+ `republican`,
+ `rest`,
+ `restaurant`,
+ `review`,
+ `reviews`,
+ `rexroth`,
+ `rich`,
+ `richardli`,
+ `ricoh`,
+ `ril`,
+ `rio`,
+ `rip`,
+ `ro`,
+ `rocher`,
+ `rocks`,
+ `rodeo`,
+ `rogers`,
+ `room`,
+ `rs`,
+ `rsvp`,
+ `ru`,
+ `rugby`,
+ `ruhr`,
+ `run`,
+ `rw`,
+ `rwe`,
+ `ryukyu`,
+ `sa`,
+ `saarland`,
+ `safe`,
+ `safety`,
+ `sakura`,
+ `sale`,
+ `salon`,
+ `samsclub`,
+ `samsung`,
+ `sandvik`,
+ `sandvikcoromant`,
+ `sanofi`,
+ `sap`,
+ `sarl`,
+ `sas`,
+ `save`,
+ `saxo`,
+ `sb`,
+ `sbi`,
+ `sbs`,
+ `sc`,
+ `sca`,
+ `scb`,
+ `schaeffler`,
+ `schmidt`,
+ `scholarships`,
+ `school`,
+ `schule`,
+ `schwarz`,
+ `science`,
+ `scot`,
+ `sd`,
+ `se`,
+ `search`,
+ `seat`,
+ `secure`,
+ `security`,
+ `seek`,
+ `select`,
+ `sener`,
+ `services`,
+ `ses`,
+ `seven`,
+ `sew`,
+ `sex`,
+ `sexy`,
+ `sfr`,
+ `sg`,
+ `sh`,
+ `shangrila`,
+ `sharp`,
+ `shaw`,
+ `shell`,
+ `shia`,
+ `shiksha`,
+ `shoes`,
+ `shop`,
+ `shopping`,
+ `shouji`,
+ `show`,
+ `showtime`,
+ `si`,
+ `silk`,
+ `sina`,
+ `singles`,
+ `site`,
+ `sj`,
+ `sk`,
+ `ski`,
+ `skin`,
+ `sky`,
+ `skype`,
+ `sl`,
+ `sling`,
+ `sm`,
+ `smart`,
+ `smile`,
+ `sn`,
+ `sncf`,
+ `so`,
+ `soccer`,
+ `social`,
+ `softbank`,
+ `software`,
+ `sohu`,
+ `solar`,
+ `solutions`,
+ `song`,
+ `sony`,
+ `soy`,
+ `spa`,
+ `space`,
+ `sport`,
+ `spot`,
+ `sr`,
+ `srl`,
+ `ss`,
+ `st`,
+ `stada`,
+ `staples`,
+ `star`,
+ `statebank`,
+ `statefarm`,
+ `stc`,
+ `stcgroup`,
+ `stockholm`,
+ `storage`,
+ `store`,
+ `stream`,
+ `studio`,
+ `study`,
+ `style`,
+ `su`,
+ `sucks`,
+ `supplies`,
+ `supply`,
+ `support`,
+ `surf`,
+ `surgery`,
+ `suzuki`,
+ `sv`,
+ `swatch`,
+ `swiss`,
+ `sx`,
+ `sy`,
+ `sydney`,
+ `systems`,
+ `sz`,
+ `tab`,
+ `taipei`,
+ `talk`,
+ `taobao`,
+ `target`,
+ `tatamotors`,
+ `tatar`,
+ `tattoo`,
+ `tax`,
+ `taxi`,
+ `tc`,
+ `tci`,
+ `td`,
+ `tdk`,
+ `team`,
+ `tech`,
+ `technology`,
+ `tel`,
+ `temasek`,
+ `tennis`,
+ `teva`,
+ `tf`,
+ `tg`,
+ `th`,
+ `thd`,
+ `theater`,
+ `theatre`,
+ `tiaa`,
+ `tickets`,
+ `tienda`,
+ `tiffany`,
+ `tips`,
+ `tires`,
+ `tirol`,
+ `tj`,
+ `tjmaxx`,
+ `tjx`,
+ `tk`,
+ `tkmaxx`,
+ `tl`,
+ `tm`,
+ `tmall`,
+ `tn`,
+ `to`,
+ `today`,
+ `tokyo`,
+ `tools`,
+ `top`,
+ `toray`,
+ `toshiba`,
+ `total`,
+ `tours`,
+ `town`,
+ `toyota`,
+ `toys`,
+ `tr`,
+ `trade`,
+ `trading`,
+ `training`,
+ `travel`,
+ `travelchannel`,
+ `travelers`,
+ `travelersinsurance`,
+ `trust`,
+ `trv`,
+ `tt`,
+ `tube`,
+ `tui`,
+ `tunes`,
+ `tushu`,
+ `tv`,
+ `tvs`,
+ `tw`,
+ `tz`,
+ `ua`,
+ `ubank`,
+ `ubs`,
+ `ug`,
+ `uk`,
+ `unicom`,
+ `university`,
+ `uno`,
+ `uol`,
+ `ups`,
+ `us`,
+ `uy`,
+ `uz`,
+ `va`,
+ `vacations`,
+ `vana`,
+ `vanguard`,
+ `vc`,
+ `ve`,
+ `vegas`,
+ `ventures`,
+ `verisign`,
+ `vermögensberater`,
+ `vermögensberatung`,
+ `versicherung`,
+ `vet`,
+ `vg`,
+ `vi`,
+ `viajes`,
+ `video`,
+ `vig`,
+ `viking`,
+ `villas`,
+ `vin`,
+ `vip`,
+ `virgin`,
+ `visa`,
+ `vision`,
+ `viva`,
+ `vivo`,
+ `vlaanderen`,
+ `vn`,
+ `vodka`,
+ `volkswagen`,
+ `volvo`,
+ `vote`,
+ `voting`,
+ `voto`,
+ `voyage`,
+ `vu`,
+ `vuelos`,
+ `wales`,
+ `walmart`,
+ `walter`,
+ `wang`,
+ `wanggou`,
+ `watch`,
+ `watches`,
+ `weather`,
+ `weatherchannel`,
+ `webcam`,
+ `weber`,
+ `website`,
+ `wed`,
+ `wedding`,
+ `weibo`,
+ `weir`,
+ `wf`,
+ `whoswho`,
+ `wien`,
+ `wiki`,
+ `williamhill`,
+ `win`,
+ `windows`,
+ `wine`,
+ `winners`,
+ `wme`,
+ `wolterskluwer`,
+ `woodside`,
+ `work`,
+ `works`,
+ `world`,
+ `wow`,
+ `ws`,
+ `wtc`,
+ `wtf`,
+ `xbox`,
+ `xerox`,
+ `xfinity`,
+ `xihuan`,
+ `xin`,
+ `xxx`,
+ `xyz`,
+ `yachts`,
+ `yahoo`,
+ `yamaxun`,
+ `yandex`,
+ `ye`,
+ `yodobashi`,
+ `yoga`,
+ `yokohama`,
+ `you`,
+ `youtube`,
+ `yt`,
+ `yun`,
+ `za`,
+ `zappos`,
+ `zara`,
+ `zero`,
+ `zip`,
+ `zm`,
+ `zone`,
+ `zuerich`,
+ `zw`,
+ `ελ`,
+ `ευ`,
+ `бг`,
+ `бел`,
+ `дети`,
+ `ею`,
+ `католик`,
+ `ком`,
+ `мкд`,
+ `мон`,
+ `москва`,
+ `онлайн`,
+ `орг`,
+ `рус`,
+ `рф`,
+ `сайт`,
+ `срб`,
+ `укр`,
+ `қаз`,
+ `հայ`,
+ `קום`,
+ `ابوظبي`,
+ `اتصالات`,
+ `ارامكو`,
+ `الاردن`,
+ `البحرين`,
+ `الجزائر`,
+ `السعودية`,
+ `السعوديه`,
+ `السعودیة`,
+ `السعودیۃ`,
+ `العليان`,
+ `المغرب`,
+ `اليمن`,
+ `امارات`,
+ `ايران`,
+ `ایران`,
+ `بارت`,
+ `بازار`,
+ `بيتك`,
+ `بھارت`,
+ `تونس`,
+ `سودان`,
+ `سوريا`,
+ `سورية`,
+ `شبكة`,
+ `عراق`,
+ `عرب`,
+ `عمان`,
+ `فلسطين`,
+ `قطر`,
+ `كاثوليك`,
+ `كوم`,
+ `مصر`,
+ `مليسيا`,
+ `موريتانيا`,
+ `موقع`,
+ `همراه`,
+ `پاكستان`,
+ `پاکستان`,
+ `ڀارت`,
+ `कॉम`,
+ `नेट`,
+ `भारत`,
+ `भारतम्`,
+ `भारोत`,
+ `संगठन`,
+ `বাংলা`,
+ `ভারত`,
+ `ভাৰত`,
+ `ਭਾਰਤ`,
+ `ભારત`,
+ `ଭାରତ`,
+ `இந்தியா`,
+ `இலங்கை`,
+ `சிங்கப்பூர்`,
+ `భారత్`,
+ `ಭಾರತ`,
+ `ഭാരതം`,
+ `ලංකා`,
+ `คอม`,
+ `ไทย`,
+ `ລາວ`,
+ `გე`,
+ `みんな`,
+ `アマゾン`,
+ `クラウド`,
+ `グーグル`,
+ `コム`,
+ `ストア`,
+ `セール`,
+ `ファッション`,
+ `ポイント`,
+ `世界`,
+ `中信`,
+ `中国`,
+ `中國`,
+ `中文网`,
+ `亚马逊`,
+ `企业`,
+ `佛山`,
+ `信息`,
+ `健康`,
+ `八卦`,
+ `公司`,
+ `公益`,
+ `台湾`,
+ `台灣`,
+ `商城`,
+ `商店`,
+ `商标`,
+ `嘉里`,
+ `嘉里大酒店`,
+ `在线`,
+ `大拿`,
+ `天主教`,
+ `娱乐`,
+ `家電`,
+ `广东`,
+ `微博`,
+ `慈善`,
+ `我爱你`,
+ `手机`,
+ `招聘`,
+ `政务`,
+ `政府`,
+ `新加坡`,
+ `新闻`,
+ `时尚`,
+ `書籍`,
+ `机构`,
+ `淡马锡`,
+ `游戏`,
+ `澳門`,
+ `澳门`,
+ `点看`,
+ `移动`,
+ `组织机构`,
+ `网址`,
+ `网店`,
+ `网站`,
+ `网络`,
+ `联通`,
+ `臺灣`,
+ `诺基亚`,
+ `谷歌`,
+ `购物`,
+ `通販`,
+ `集团`,
+ `電訊盈科`,
+ `飞利浦`,
+ `食品`,
+ `餐厅`,
+ `香格里拉`,
+ `香港`,
+ `닷넷`,
+ `닷컴`,
+ `삼성`,
+ `한국`,
+}
diff --git a/vendor/mvdan.cc/xurls/v2/tlds_pseudo.go b/vendor/mvdan.cc/xurls/v2/tlds_pseudo.go
new file mode 100644
index 0000000..94c67d1
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/tlds_pseudo.go
@@ -0,0 +1,24 @@
+// Copyright (c) 2015, Daniel Martí
+// See LICENSE for licensing information
+
+package xurls
+
+// PseudoTLDs is a sorted list of some widely used unofficial TLDs.
+//
+// Sources:
+// * https://en.wikipedia.org/wiki/Pseudo-top-level_domain
+// * https://en.wikipedia.org/wiki/Category:Pseudo-top-level_domains
+// * https://tools.ietf.org/html/draft-grothoff-iesg-special-use-p2p-names-00
+// * https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
+var PseudoTLDs = []string{
+ `bit`, // Namecoin
+ `example`, // Example domain
+ `exit`, // Tor exit node
+ `gnu`, // GNS by public key
+ `i2p`, // I2P network
+ `invalid`, // Invalid domain
+ `local`, // Local network
+ `localhost`, // Local network
+ `test`, // Test domain
+ `zkey`, // GNS domain name
+}
diff --git a/vendor/mvdan.cc/xurls/v2/unicode.go b/vendor/mvdan.cc/xurls/v2/unicode.go
new file mode 100644
index 0000000..90dedba
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/unicode.go
@@ -0,0 +1,7 @@
+// Generated by unicodegen
+
+package xurls
+
+const allowedUcsChar = "¡-ᙿᚁ-\u1fff\u200b-‧\u202a-\u202e‰-⁞\u2060-\u2fff、-\ud7ff豈-\ufdcfﷰ-\uffef𐀀-\U0001fffd𠀀-\U0002fffd𰀀-\U0003fffd\U00040000-\U0004fffd\U00050000-\U0005fffd\U00060000-\U0006fffd\U00070000-\U0007fffd\U00080000-\U0008fffd\U00090000-\U0009fffd\U000a0000-\U000afffd\U000b0000-\U000bfffd\U000c0000-\U000cfffd\U000d0000-\U000dfffd\U000e1000-\U000efffd"
+
+const allowedUcsCharMinusPunc = "¢-¦¨-µ¸-¾À-ͽͿ-ΆΈ-ՙՠ-ֈ֊-ֿׁ-ׂׄ-ׇׅ-ײ\u05f5-؈؋؎-ؚ\u061c-\u061dؠ-٩ٮ-ۓە-ۿ\u070e-߶ߺ-\u082f\u083f-\u085d\u085f-ॣ०-९ॱ-ৼ৾-ੵ\u0a77-૯૱-\u0c76౸-ಃಅ-ෳ\u0df5-๎๐-๙\u0e5c-༃༓༕-྄྆-࿏࿕-࿘\u0fdb-၉ၐ-ჺჼ-፟፩-᙭ᙯ-ᙿᚁ-ᛪᛮ-᜴\u1737-៓ៗ៛-\u17ff᠆᠋-\u1943᥆-\u1a1dᨠ-\u1a9fᪧ\u1aae-᭙᭡-\u1bfbᰀ-\u1c3a᱀-ᱽᲀ-Ჿ\u1cc8-᳔᳒-\u1fff\u200b-―‘-‟\u202a-\u202e‹-›‿-⁀⁄-⁆⁒⁔\u2060-\u2cf8⳽ⴀ-ⵯ\u2d71-ⷿ⸂-⸅⸉-⸊⸌-⸍⸗⸚⸜-⸝⸠-⸩ⸯ⸺-⸻⹀⹂⹐-⹑\u2e53-\u2fff〄-〼〾-ヺー-ꓽꔀ-ꘌꘐ-꙲ꙴ-꙽ꙿ-꛱\ua6f8-ꡳ\ua878-\ua8cd꣐-ꣷꣻꣽ-꤭ꤰ-\ua95eꥠ-꧀\ua9ce-\ua9ddꧠ-\uaa5bꩠ-ꫝꫠ-ꫯꫲ-ꯪ꯬-\ud7ff豈-\ufdcfﷰ-️︗-︘\ufe1a-︯︱-﹄﹇-﹈﹍-﹏\ufe53﹘-﹞﹢-\ufe67﹩\ufe6c-\uff00$(-)+-0-9<->A-[]-⦆「-」ヲ-\uffef𐀀-\U000100ff\U00010103-\U0001039e𐎠-𐏏𐏑-\U0001056e\U00010570-\U00010856𐡘-\U0001091e𐤠-\U0001093e\U00010940-\U00010a4f\U00010a59-𐩾𐪀-𐫯\U00010af7-\U00010b38𐭀-\U00010b98\U00010b9d-𐽔\U00010f5a-𑁆\U0001104e-𑂺\U000110bd\U000110c2-𑄿𑅄-𑅳𑅶-𑇄𑇉-𑇌𑇎-𑇚𑇜\U000111e0-𑈷𑈾-𑊨\U000112aa-𑑊𑑐-𑑙\U0001145c𑑞-𑓅𑓇-𑗀𑗘-𑙀𑙄-\U0001165f\U0001166d-𑜻𑜿-𑠺\U0001183c-𑥃\U00011947-𑧡𑧣-𑨾𑩇-𑪙𑪝\U00011aa3-𑱀\U00011c46-\U00011c6f𑱲-𑻶\U00011ef9-\U00011ffe𒀀-\U0001246f\U00012475-\U00016a6d\U00016a70-𖫴\U00016af6-𖬶𖬼-𖭃𖭅-𖺖\U00016e9b-𖿡𖿣-𛲞\U0001bca0-𝪆\U0001da8c-\U0001e95d\U0001e960-\U0001fffd𠀀-\U0002fffd𰀀-\U0003fffd\U00040000-\U0004fffd\U00050000-\U0005fffd\U00060000-\U0006fffd\U00070000-\U0007fffd\U00080000-\U0008fffd\U00090000-\U0009fffd\U000a0000-\U000afffd\U000b0000-\U000bfffd\U000c0000-\U000cfffd\U000d0000-\U000dfffd\U000e1000-\U000efffd"
diff --git a/vendor/mvdan.cc/xurls/v2/xurls.go b/vendor/mvdan.cc/xurls/v2/xurls.go
new file mode 100644
index 0000000..4113b07
--- /dev/null
+++ b/vendor/mvdan.cc/xurls/v2/xurls.go
@@ -0,0 +1,200 @@
+// Copyright (c) 2015, Daniel Martí
+// See LICENSE for licensing information
+
+// Package xurls extracts urls from plain text using regular expressions.
+package xurls
+
+import (
+ "regexp"
+ "strings"
+ "sync"
+ "unicode/utf8"
+)
+
+//go:generate go run ./generate/tldsgen
+//go:generate go run ./generate/schemesgen
+//go:generate go run ./generate/unicodegen
+
+const (
+ // pathCont is based on https://www.rfc-editor.org/rfc/rfc3987#section-2.2
+ // but does not match separators anywhere or most puncutation in final position,
+ // to avoid creating asymmetries like
+ // `Did you know that **https://example.com/** is reserved for documentation?`
+ // from `Did you know that **https://example.com/** is reserved for documentation?`.
+ unreservedChar = `a-zA-Z0-9\-._~`
+ endUnreservedChar = `a-zA-Z0-9\-_~`
+ midSubDelimChar = `!$&'*+,;=`
+ endSubDelimChar = `$&+=`
+ midIPathSegmentChar = unreservedChar + `%` + midSubDelimChar + `:@` + allowedUcsChar
+ endIPathSegmentChar = endUnreservedChar + `%` + endSubDelimChar + allowedUcsCharMinusPunc
+ iPrivateChar = `\x{E000}-\x{F8FF}\x{F0000}-\x{FFFFD}\x{100000}-\x{10FFFD}`
+ midIChar = `/?#\\` + midIPathSegmentChar + iPrivateChar
+ endIChar = `/#` + endIPathSegmentChar + iPrivateChar
+ wellParen = `\((?:[` + midIChar + `]|\([` + midIChar + `]*\))*\)`
+ wellBrack = `\[(?:[` + midIChar + `]|\[[` + midIChar + `]*\])*\]`
+ wellBrace = `\{(?:[` + midIChar + `]|\{[` + midIChar + `]*\})*\}`
+ wellAll = wellParen + `|` + wellBrack + `|` + wellBrace
+ pathCont = `(?:[` + midIChar + `]*(?:` + wellAll + `|[` + endIChar + `]))+`
+
+ letter = `\p{L}`
+ mark = `\p{M}`
+ number = `\p{N}`
+ iriChar = letter + mark + number
+ iri = `[` + iriChar + `](?:[` + iriChar + `\-]*[` + iriChar + `])?`
+ subdomain = `(?:` + iri + `\.)+`
+ octet = `(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])`
+ ipv4Addr = octet + `\.` + octet + `\.` + octet + `\.` + octet
+
+ // ipv6Addr is based on https://datatracker.ietf.org/doc/html/rfc4291#section-2.2
+ // with a specific alternative for each valid count of leading 16-bit hexadecimal "chomps"
+ // that have not been replaced with a `::` elision.
+ h4 = `[0-9a-fA-F]{1,4}`
+ ipv6AddrMinusEmpty = `(?:` +
+ // 7 colon-terminated chomps, followed by a final chomp or the rest of an elision.
+ `(?:` + h4 + `:){7}(?:` + h4 + `|:)|` +
+ // 6 chomps, followed by an IPv4 address or elision with final chomp or final elision.
+ `(?:` + h4 + `:){6}(?:` + ipv4Addr + `|:` + h4 + `|:)|` +
+ // 5 chomps, followed by an elision with optional IPv4 or up to 2 final chomps.
+ `(?:` + h4 + `:){5}(?::` + ipv4Addr + `|(?::` + h4 + `){1,2}|:)|` +
+ // 4 chomps, followed by an elision with optional IPv4 (optionally preceded by a chomp) or
+ // up to 3 final chomps.
+ `(?:` + h4 + `:){4}(?:(?::` + h4 + `){0,1}:` + ipv4Addr + `|(?::` + h4 + `){1,3}|:)|` +
+ // 3 chomps, followed by an elision with optional IPv4 (preceded by up to 2 chomps) or
+ // up to 4 final chomps.
+ `(?:` + h4 + `:){3}(?:(?::` + h4 + `){0,2}:` + ipv4Addr + `|(?::` + h4 + `){1,4}|:)|` +
+ // 2 chomps, followed by an elision with optional IPv4 (preceded by up to 3 chomps) or
+ // up to 5 final chomps.
+ `(?:` + h4 + `:){2}(?:(?::` + h4 + `){0,3}:` + ipv4Addr + `|(?::` + h4 + `){1,5}|:)|` +
+ // 1 chomp, followed by an elision with optional IPv4 (preceded by up to 4 chomps) or
+ // up to 6 final chomps.
+ `(?:` + h4 + `:){1}(?:(?::` + h4 + `){0,4}:` + ipv4Addr + `|(?::` + h4 + `){1,6}|:)|` +
+ // elision, followed by optional IPv4 (preceded by up to 5 chomps) or
+ // up to 7 final chomps.
+ // `:` is an intentionally omitted alternative, to avoid matching `::`.
+ `:(?:(?::` + h4 + `){0,5}:` + ipv4Addr + `|(?::` + h4 + `){1,7})` +
+ `)`
+ ipv6Addr = `(?:` + ipv6AddrMinusEmpty + `|::)`
+ ipAddrMinusEmpty = `(?:` + ipv6AddrMinusEmpty + `|\b` + ipv4Addr + `\b)`
+ port = `(?::[0-9]*)?`
+)
+
+// AnyScheme can be passed to StrictMatchingScheme to match any possibly valid
+// scheme, and not just the known ones.
+var AnyScheme = `(?:[a-zA-Z][a-zA-Z.\-+]*://|` + anyOf(SchemesNoAuthority...) + `:)`
+
+// SchemesNoAuthority is a sorted list of some well-known url schemes that are
+// followed by ":" instead of "://". The list includes both officially
+// registered and unofficial schemes.
+var SchemesNoAuthority = []string{
+ `bitcoin`, // Bitcoin
+ `cid`, // Content-ID
+ `file`, // Files
+ `magnet`, // Torrent magnets
+ `mailto`, // Mail
+ `mid`, // Message-ID
+ `sms`, // SMS
+ `tel`, // Telephone
+ `xmpp`, // XMPP
+}
+
+// SchemesUnofficial is a sorted list of some well-known url schemes which
+// aren't officially registered just yet. They tend to correspond to software.
+//
+// Mostly collected from https://en.wikipedia.org/wiki/List_of_URI_schemes#Unofficial_but_common_URI_schemes.
+var SchemesUnofficial = []string{
+ `gemini`, // gemini
+ `jdbc`, // Java database Connectivity
+ `moz-extension`, // Firefox extension
+ `postgres`, // PostgreSQL (short form)
+ `postgresql`, // PostgreSQL
+ `slack`, // Slack
+ `zoommtg`, // Zoom (desktop)
+ `zoomus`, // Zoom (mobile)
+}
+
+// The regular expressions are compiled when the API is first called.
+// Any subsequent calls will use the same regular expression pointers.
+//
+// We do not need to make a copy of them for each API call,
+// as Copy is now only useful if one copy calls Longest but not another,
+// and we always call Longest after compiling the regular expression.
+var (
+ strictRe *regexp.Regexp
+ strictInit sync.Once
+
+ relaxedRe *regexp.Regexp
+ relaxedInit sync.Once
+)
+
+func anyOf(strs ...string) string {
+ var b strings.Builder
+ b.WriteString("(?:")
+ for i, s := range strs {
+ if i != 0 {
+ b.WriteByte('|')
+ }
+ b.WriteString(regexp.QuoteMeta(s))
+ }
+ b.WriteByte(')')
+ return b.String()
+}
+
+func strictExp() string {
+ schemes := `(?:(?i)(?:` + anyOf(Schemes...) + `|` + anyOf(SchemesUnofficial...) + `)://|` + anyOf(SchemesNoAuthority...) + `:)`
+ return schemes + pathCont
+}
+
+func relaxedExp() string {
+ var asciiTLDs, unicodeTLDs []string
+ for i, tld := range TLDs {
+ if tld[0] >= utf8.RuneSelf {
+ asciiTLDs = TLDs[:i:i]
+ unicodeTLDs = TLDs[i:]
+ break
+ }
+ }
+ punycode := `xn--[a-z0-9-]+`
+
+ // Use \b to make sure ASCII TLDs are immediately followed by a word break.
+ // We can't do that with unicode TLDs, as they don't see following
+ // whitespace as a word break.
+ tlds := `(?:(?i)` + punycode + `|` + anyOf(append(asciiTLDs, PseudoTLDs...)...) + `\b|` + anyOf(unicodeTLDs...) + `)`
+ domain := subdomain + tlds
+
+ hostName := `(?:` + domain + `|\[` + ipv6Addr + `\]|\b` + ipv4Addr + `\b)`
+ webURL := hostName + port + `(?:/` + pathCont + `|/)?`
+ email := `[a-zA-Z0-9._%\-+]+@` + domain
+ return strictExp() + `|` + webURL + `|` + email + `|` + ipv6AddrMinusEmpty
+}
+
+// Strict produces a regexp that matches any URL with a scheme in either the
+// Schemes or SchemesNoAuthority lists.
+func Strict() *regexp.Regexp {
+ strictInit.Do(func() {
+ strictRe = regexp.MustCompile(strictExp())
+ strictRe.Longest()
+ })
+ return strictRe
+}
+
+// Relaxed produces a regexp that matches any URL matched by Strict, plus any
+// URL with no scheme or email address.
+func Relaxed() *regexp.Regexp {
+ relaxedInit.Do(func() {
+ relaxedRe = regexp.MustCompile(relaxedExp())
+ relaxedRe.Longest()
+ })
+ return relaxedRe
+}
+
+// StrictMatchingScheme produces a regexp similar to Strict, but requiring that
+// the scheme match the given regular expression. See AnyScheme too.
+func StrictMatchingScheme(exp string) (*regexp.Regexp, error) {
+ strictMatching := `(?i)(?:` + exp + `)(?-i)` + pathCont
+ re, err := regexp.Compile(strictMatching)
+ if err != nil {
+ return nil, err
+ }
+ re.Longest()
+ return re, nil
+}