mirror of https://github.com/hashicorp/consul
Removes some unused vendored dependencies.
parent
4c54e68e14
commit
5dc9d92fe0
|
@ -1,573 +0,0 @@
|
||||||
package printer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
"github.com/hashicorp/hcl/hcl/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
blank = byte(' ')
|
|
||||||
newline = byte('\n')
|
|
||||||
tab = byte('\t')
|
|
||||||
infinity = 1 << 30 // offset or line
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
unindent = []byte("\uE123") // in the private use space
|
|
||||||
)
|
|
||||||
|
|
||||||
type printer struct {
|
|
||||||
cfg Config
|
|
||||||
prev token.Pos
|
|
||||||
|
|
||||||
comments []*ast.CommentGroup // may be nil, contains all comments
|
|
||||||
standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node)
|
|
||||||
|
|
||||||
enableTrace bool
|
|
||||||
indentTrace int
|
|
||||||
}
|
|
||||||
|
|
||||||
type ByPosition []*ast.CommentGroup
|
|
||||||
|
|
||||||
func (b ByPosition) Len() int { return len(b) }
|
|
||||||
func (b ByPosition) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
|
||||||
func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) }
|
|
||||||
|
|
||||||
// collectComments comments all standalone comments which are not lead or line
|
|
||||||
// comment
|
|
||||||
func (p *printer) collectComments(node ast.Node) {
|
|
||||||
// first collect all comments. This is already stored in
|
|
||||||
// ast.File.(comments)
|
|
||||||
ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
|
|
||||||
switch t := nn.(type) {
|
|
||||||
case *ast.File:
|
|
||||||
p.comments = t.Comments
|
|
||||||
return nn, false
|
|
||||||
}
|
|
||||||
return nn, true
|
|
||||||
})
|
|
||||||
|
|
||||||
standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0)
|
|
||||||
for _, c := range p.comments {
|
|
||||||
standaloneComments[c.Pos()] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
// next remove all lead and line comments from the overall comment map.
|
|
||||||
// This will give us comments which are standalone, comments which are not
|
|
||||||
// assigned to any kind of node.
|
|
||||||
ast.Walk(node, func(nn ast.Node) (ast.Node, bool) {
|
|
||||||
switch t := nn.(type) {
|
|
||||||
case *ast.LiteralType:
|
|
||||||
if t.LineComment != nil {
|
|
||||||
for _, comment := range t.LineComment.List {
|
|
||||||
if _, ok := standaloneComments[comment.Pos()]; ok {
|
|
||||||
delete(standaloneComments, comment.Pos())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *ast.ObjectItem:
|
|
||||||
if t.LeadComment != nil {
|
|
||||||
for _, comment := range t.LeadComment.List {
|
|
||||||
if _, ok := standaloneComments[comment.Pos()]; ok {
|
|
||||||
delete(standaloneComments, comment.Pos())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.LineComment != nil {
|
|
||||||
for _, comment := range t.LineComment.List {
|
|
||||||
if _, ok := standaloneComments[comment.Pos()]; ok {
|
|
||||||
delete(standaloneComments, comment.Pos())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nn, true
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, c := range standaloneComments {
|
|
||||||
p.standaloneComments = append(p.standaloneComments, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(ByPosition(p.standaloneComments))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// output prints creates b printable HCL output and returns it.
|
|
||||||
func (p *printer) output(n interface{}) []byte {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
switch t := n.(type) {
|
|
||||||
case *ast.File:
|
|
||||||
return p.output(t.Node)
|
|
||||||
case *ast.ObjectList:
|
|
||||||
var index int
|
|
||||||
var nextItem token.Pos
|
|
||||||
var commented bool
|
|
||||||
for {
|
|
||||||
// TODO(arslan): refactor below comment printing, we have the same in objectType
|
|
||||||
for _, c := range p.standaloneComments {
|
|
||||||
for _, comment := range c.List {
|
|
||||||
if index != len(t.Items) {
|
|
||||||
nextItem = t.Items[index].Pos()
|
|
||||||
} else {
|
|
||||||
nextItem = token.Pos{Offset: infinity, Line: infinity}
|
|
||||||
}
|
|
||||||
|
|
||||||
if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
|
|
||||||
// if we hit the end add newlines so we can print the comment
|
|
||||||
if index == len(t.Items) {
|
|
||||||
buf.Write([]byte{newline, newline})
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteString(comment.Text)
|
|
||||||
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
if index != len(t.Items) {
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if index == len(t.Items) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.Write(p.output(t.Items[index]))
|
|
||||||
if !commented && index != len(t.Items)-1 {
|
|
||||||
buf.Write([]byte{newline, newline})
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
case *ast.ObjectKey:
|
|
||||||
buf.WriteString(t.Token.Text)
|
|
||||||
case *ast.ObjectItem:
|
|
||||||
p.prev = t.Pos()
|
|
||||||
buf.Write(p.objectItem(t))
|
|
||||||
case *ast.LiteralType:
|
|
||||||
buf.Write(p.literalType(t))
|
|
||||||
case *ast.ListType:
|
|
||||||
buf.Write(p.list(t))
|
|
||||||
case *ast.ObjectType:
|
|
||||||
buf.Write(p.objectType(t))
|
|
||||||
default:
|
|
||||||
fmt.Printf(" unknown type: %T\n", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *printer) literalType(lit *ast.LiteralType) []byte {
|
|
||||||
result := []byte(lit.Token.Text)
|
|
||||||
if lit.Token.Type == token.HEREDOC {
|
|
||||||
// Clear the trailing newline from heredocs
|
|
||||||
if result[len(result)-1] == '\n' {
|
|
||||||
result = result[:len(result)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poison lines 2+ so that we don't indent them
|
|
||||||
result = p.heredocIndent(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectItem returns the printable HCL form of an object item. An object type
|
|
||||||
// starts with one/multiple keys and has a value. The value might be of any
|
|
||||||
// type.
|
|
||||||
func (p *printer) objectItem(o *ast.ObjectItem) []byte {
|
|
||||||
defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text)))
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
if o.LeadComment != nil {
|
|
||||||
for _, comment := range o.LeadComment.List {
|
|
||||||
buf.WriteString(comment.Text)
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, k := range o.Keys {
|
|
||||||
buf.WriteString(k.Token.Text)
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
|
|
||||||
// reach end of key
|
|
||||||
if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 {
|
|
||||||
buf.WriteString("=")
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.Write(p.output(o.Val))
|
|
||||||
|
|
||||||
if o.Val.Pos().Line == o.Keys[0].Pos().Line && o.LineComment != nil {
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
for _, comment := range o.LineComment.List {
|
|
||||||
buf.WriteString(comment.Text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// objectType returns the printable HCL form of an object type. An object type
|
|
||||||
// begins with a brace and ends with a brace.
|
|
||||||
func (p *printer) objectType(o *ast.ObjectType) []byte {
|
|
||||||
defer un(trace(p, "ObjectType"))
|
|
||||||
var buf bytes.Buffer
|
|
||||||
buf.WriteString("{")
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
|
|
||||||
var index int
|
|
||||||
var nextItem token.Pos
|
|
||||||
var commented bool
|
|
||||||
for {
|
|
||||||
// Print stand alone comments
|
|
||||||
for _, c := range p.standaloneComments {
|
|
||||||
for _, comment := range c.List {
|
|
||||||
// if we hit the end, last item should be the brace
|
|
||||||
if index != len(o.List.Items) {
|
|
||||||
nextItem = o.List.Items[index].Pos()
|
|
||||||
} else {
|
|
||||||
nextItem = o.Rbrace
|
|
||||||
}
|
|
||||||
|
|
||||||
if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) {
|
|
||||||
// add newline if it's between other printed nodes
|
|
||||||
if index > 0 {
|
|
||||||
commented = true
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.Write(p.indent([]byte(comment.Text)))
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
if index != len(o.List.Items) {
|
|
||||||
buf.WriteByte(newline) // do not print on the end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if index == len(o.List.Items) {
|
|
||||||
p.prev = o.Rbrace
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we have adjacent one liner items. If yes we'll going to align
|
|
||||||
// the comments.
|
|
||||||
var aligned []*ast.ObjectItem
|
|
||||||
for _, item := range o.List.Items[index:] {
|
|
||||||
// we don't group one line lists
|
|
||||||
if len(o.List.Items) == 1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// one means a oneliner with out any lead comment
|
|
||||||
// two means a oneliner with lead comment
|
|
||||||
// anything else might be something else
|
|
||||||
cur := lines(string(p.objectItem(item)))
|
|
||||||
if cur > 2 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
curPos := item.Pos()
|
|
||||||
|
|
||||||
nextPos := token.Pos{}
|
|
||||||
if index != len(o.List.Items)-1 {
|
|
||||||
nextPos = o.List.Items[index+1].Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
prevPos := token.Pos{}
|
|
||||||
if index != 0 {
|
|
||||||
prevPos = o.List.Items[index-1].Pos()
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmt.Println("DEBUG ----------------")
|
|
||||||
// fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos)
|
|
||||||
// fmt.Printf("cur = %+v curPos: %s\n", cur, curPos)
|
|
||||||
// fmt.Printf("next = %+v nextPos: %s\n", next, nextPos)
|
|
||||||
|
|
||||||
if curPos.Line+1 == nextPos.Line {
|
|
||||||
aligned = append(aligned, item)
|
|
||||||
index++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if curPos.Line-1 == prevPos.Line {
|
|
||||||
aligned = append(aligned, item)
|
|
||||||
index++
|
|
||||||
|
|
||||||
// finish if we have a new line or comment next. This happens
|
|
||||||
// if the next item is not adjacent
|
|
||||||
if curPos.Line+1 != nextPos.Line {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// put newlines if the items are between other non aligned items.
|
|
||||||
// newlines are also added if there is a standalone comment already, so
|
|
||||||
// check it too
|
|
||||||
if !commented && index != len(aligned) {
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(aligned) >= 1 {
|
|
||||||
p.prev = aligned[len(aligned)-1].Pos()
|
|
||||||
|
|
||||||
items := p.alignedItems(aligned)
|
|
||||||
buf.Write(p.indent(items))
|
|
||||||
} else {
|
|
||||||
p.prev = o.List.Items[index].Pos()
|
|
||||||
|
|
||||||
buf.Write(p.indent(p.objectItem(o.List.Items[index])))
|
|
||||||
index++
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteString("}")
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *printer) alignedItems(items []*ast.ObjectItem) []byte {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
// find the longest key and value length, needed for alignment
|
|
||||||
var longestKeyLen int // longest key length
|
|
||||||
var longestValLen int // longest value length
|
|
||||||
for _, item := range items {
|
|
||||||
key := len(item.Keys[0].Token.Text)
|
|
||||||
val := len(p.output(item.Val))
|
|
||||||
|
|
||||||
if key > longestKeyLen {
|
|
||||||
longestKeyLen = key
|
|
||||||
}
|
|
||||||
|
|
||||||
if val > longestValLen {
|
|
||||||
longestValLen = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, item := range items {
|
|
||||||
if item.LeadComment != nil {
|
|
||||||
for _, comment := range item.LeadComment.List {
|
|
||||||
buf.WriteString(comment.Text)
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, k := range item.Keys {
|
|
||||||
keyLen := len(k.Token.Text)
|
|
||||||
buf.WriteString(k.Token.Text)
|
|
||||||
for i := 0; i < longestKeyLen-keyLen+1; i++ {
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reach end of key
|
|
||||||
if i == len(item.Keys)-1 && len(item.Keys) == 1 {
|
|
||||||
buf.WriteString("=")
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val := p.output(item.Val)
|
|
||||||
valLen := len(val)
|
|
||||||
buf.Write(val)
|
|
||||||
|
|
||||||
if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil {
|
|
||||||
for i := 0; i < longestValLen-valLen+1; i++ {
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, comment := range item.LineComment.List {
|
|
||||||
buf.WriteString(comment.Text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not print for the last item
|
|
||||||
if i != len(items)-1 {
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// list returns the printable HCL form of an list type.
|
|
||||||
func (p *printer) list(l *ast.ListType) []byte {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
buf.WriteString("[")
|
|
||||||
|
|
||||||
var longestLine int
|
|
||||||
for _, item := range l.List {
|
|
||||||
// for now we assume that the list only contains literal types
|
|
||||||
if lit, ok := item.(*ast.LiteralType); ok {
|
|
||||||
lineLen := len(lit.Token.Text)
|
|
||||||
if lineLen > longestLine {
|
|
||||||
longestLine = lineLen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, item := range l.List {
|
|
||||||
if item.Pos().Line != l.Lbrack.Line {
|
|
||||||
// multiline list, add newline before we add each item
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
// also indent each line
|
|
||||||
val := p.output(item)
|
|
||||||
curLen := len(val)
|
|
||||||
buf.Write(p.indent(val))
|
|
||||||
buf.WriteString(",")
|
|
||||||
|
|
||||||
if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil {
|
|
||||||
// if the next item doesn't have any comments, do not align
|
|
||||||
buf.WriteByte(blank) // align one space
|
|
||||||
if i != len(l.List)-1 {
|
|
||||||
if lit, ok := l.List[i+1].(*ast.LiteralType); ok && lit.LineComment != nil {
|
|
||||||
for i := 0; i < longestLine-curLen; i++ {
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, comment := range lit.LineComment.List {
|
|
||||||
buf.WriteString(comment.Text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i == len(l.List)-1 {
|
|
||||||
buf.WriteByte(newline)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buf.Write(p.output(item))
|
|
||||||
if i != len(l.List)-1 {
|
|
||||||
buf.WriteString(",")
|
|
||||||
buf.WriteByte(blank)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.WriteString("]")
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// indent indents the lines of the given buffer for each non-empty line
|
|
||||||
func (p *printer) indent(buf []byte) []byte {
|
|
||||||
var prefix []byte
|
|
||||||
if p.cfg.SpacesWidth != 0 {
|
|
||||||
for i := 0; i < p.cfg.SpacesWidth; i++ {
|
|
||||||
prefix = append(prefix, blank)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
prefix = []byte{tab}
|
|
||||||
}
|
|
||||||
|
|
||||||
var res []byte
|
|
||||||
bol := true
|
|
||||||
for _, c := range buf {
|
|
||||||
if bol && c != '\n' {
|
|
||||||
res = append(res, prefix...)
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, c)
|
|
||||||
bol = c == '\n'
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// unindent removes all the indentation from the tombstoned lines
|
|
||||||
func (p *printer) unindent(buf []byte) []byte {
|
|
||||||
var res []byte
|
|
||||||
for i := 0; i < len(buf); i++ {
|
|
||||||
skip := len(buf)-i <= len(unindent)
|
|
||||||
if !skip {
|
|
||||||
skip = !bytes.Equal(unindent, buf[i:i+len(unindent)])
|
|
||||||
}
|
|
||||||
if skip {
|
|
||||||
res = append(res, buf[i])
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have a marker. we have to backtrace here and clean out
|
|
||||||
// any whitespace ahead of our tombstone up to a \n
|
|
||||||
for j := len(res) - 1; j >= 0; j-- {
|
|
||||||
if res[j] == '\n' {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
res = res[:j]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the entire unindent marker
|
|
||||||
i += len(unindent) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
// heredocIndent marks all the 2nd and further lines as unindentable
|
|
||||||
func (p *printer) heredocIndent(buf []byte) []byte {
|
|
||||||
var res []byte
|
|
||||||
bol := false
|
|
||||||
for _, c := range buf {
|
|
||||||
if bol && c != '\n' {
|
|
||||||
res = append(res, unindent...)
|
|
||||||
}
|
|
||||||
res = append(res, c)
|
|
||||||
bol = c == '\n'
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func lines(txt string) int {
|
|
||||||
endline := 1
|
|
||||||
for i := 0; i < len(txt); i++ {
|
|
||||||
if txt[i] == '\n' {
|
|
||||||
endline++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return endline
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Tracing support
|
|
||||||
|
|
||||||
func (p *printer) printTrace(a ...interface{}) {
|
|
||||||
if !p.enableTrace {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
|
|
||||||
const n = len(dots)
|
|
||||||
i := 2 * p.indentTrace
|
|
||||||
for i > n {
|
|
||||||
fmt.Print(dots)
|
|
||||||
i -= n
|
|
||||||
}
|
|
||||||
// i <= n
|
|
||||||
fmt.Print(dots[0:i])
|
|
||||||
fmt.Println(a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func trace(p *printer, msg string) *printer {
|
|
||||||
p.printTrace(msg, "(")
|
|
||||||
p.indentTrace++
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usage pattern: defer un(trace(p, "..."))
|
|
||||||
func un(p *printer) {
|
|
||||||
p.indentTrace--
|
|
||||||
p.printTrace(")")
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Package printer implements printing of AST nodes to HCL format.
|
|
||||||
package printer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/hcl/ast"
|
|
||||||
"github.com/hashicorp/hcl/hcl/parser"
|
|
||||||
)
|
|
||||||
|
|
||||||
var DefaultConfig = Config{
|
|
||||||
SpacesWidth: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Config node controls the output of Fprint.
|
|
||||||
type Config struct {
|
|
||||||
SpacesWidth int // if set, it will use spaces instead of tabs for alignment
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Fprint(output io.Writer, node ast.Node) error {
|
|
||||||
p := &printer{
|
|
||||||
cfg: *c,
|
|
||||||
comments: make([]*ast.CommentGroup, 0),
|
|
||||||
standaloneComments: make([]*ast.CommentGroup, 0),
|
|
||||||
// enableTrace: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
p.collectComments(node)
|
|
||||||
|
|
||||||
if _, err := output.Write(p.unindent(p.output(node))); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush tabwriter, if any
|
|
||||||
var err error
|
|
||||||
if tw, _ := output.(*tabwriter.Writer); tw != nil {
|
|
||||||
err = tw.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fprint "pretty-prints" an HCL node to output
|
|
||||||
// It calls Config.Fprint with default settings.
|
|
||||||
func Fprint(output io.Writer, node ast.Node) error {
|
|
||||||
return DefaultConfig.Fprint(output, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format formats src HCL and returns the result.
|
|
||||||
func Format(src []byte) ([]byte, error) {
|
|
||||||
node, err := parser.Parse(src)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := DefaultConfig.Fprint(&buf, node); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
package raftbench
|
|
||||||
|
|
||||||
// raftbench provides common benchmarking functions which can be used by
|
|
||||||
// anything which implements the raft.LogStore and raft.StableStore interfaces.
|
|
||||||
// All functions accept these interfaces and perform benchmarking. This
|
|
||||||
// makes comparing backend performance easier by sharing the tests.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/hashicorp/raft"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func FirstIndex(b *testing.B, store raft.LogStore) {
|
|
||||||
// Create some fake data
|
|
||||||
var logs []*raft.Log
|
|
||||||
for i := 1; i < 10; i++ {
|
|
||||||
logs = append(logs, &raft.Log{Index: uint64(i), Data: []byte("data")})
|
|
||||||
}
|
|
||||||
if err := store.StoreLogs(logs); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
// Run FirstIndex a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
store.FirstIndex()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func LastIndex(b *testing.B, store raft.LogStore) {
|
|
||||||
// Create some fake data
|
|
||||||
var logs []*raft.Log
|
|
||||||
for i := 1; i < 10; i++ {
|
|
||||||
logs = append(logs, &raft.Log{Index: uint64(i), Data: []byte("data")})
|
|
||||||
}
|
|
||||||
if err := store.StoreLogs(logs); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
// Run LastIndex a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
store.LastIndex()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetLog(b *testing.B, store raft.LogStore) {
|
|
||||||
// Create some fake data
|
|
||||||
var logs []*raft.Log
|
|
||||||
for i := 1; i < 10; i++ {
|
|
||||||
logs = append(logs, &raft.Log{Index: uint64(i), Data: []byte("data")})
|
|
||||||
}
|
|
||||||
if err := store.StoreLogs(logs); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
// Run GetLog a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
if err := store.GetLog(5, new(raft.Log)); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StoreLog(b *testing.B, store raft.LogStore) {
|
|
||||||
// Run StoreLog a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
log := &raft.Log{Index: uint64(n), Data: []byte("data")}
|
|
||||||
if err := store.StoreLog(log); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StoreLogs(b *testing.B, store raft.LogStore) {
|
|
||||||
// Run StoreLogs a number of times. We want to set multiple logs each
|
|
||||||
// run, so we create 3 logs with incrementing indexes for each iteration.
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
b.StopTimer()
|
|
||||||
offset := 3 * (n + 1)
|
|
||||||
logs := []*raft.Log{
|
|
||||||
&raft.Log{Index: uint64(offset - 2), Data: []byte("data")},
|
|
||||||
&raft.Log{Index: uint64(offset - 1), Data: []byte("data")},
|
|
||||||
&raft.Log{Index: uint64(offset), Data: []byte("data")},
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
if err := store.StoreLogs(logs); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteRange(b *testing.B, store raft.LogStore) {
|
|
||||||
// Create some fake data. In this case, we create 3 new log entries for each
|
|
||||||
// test case, and separate them by index in multiples of 10. This allows
|
|
||||||
// some room so that we can test deleting ranges with "extra" logs to
|
|
||||||
// to ensure we stop going to the database once our max index is hit.
|
|
||||||
var logs []*raft.Log
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
offset := 10 * n
|
|
||||||
for i := offset; i < offset+3; i++ {
|
|
||||||
logs = append(logs, &raft.Log{Index: uint64(i), Data: []byte("data")})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := store.StoreLogs(logs); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
// Delete a range of the data
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
offset := 10 * n
|
|
||||||
if err := store.DeleteRange(uint64(offset), uint64(offset+9)); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Set(b *testing.B, store raft.StableStore) {
|
|
||||||
// Run Set a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
if err := store.Set([]byte{byte(n)}, []byte("val")); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Get(b *testing.B, store raft.StableStore) {
|
|
||||||
// Create some fake data
|
|
||||||
for i := 1; i < 10; i++ {
|
|
||||||
if err := store.Set([]byte{byte(i)}, []byte("val")); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
// Run Get a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
if _, err := store.Get([]byte{0x05}); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetUint64(b *testing.B, store raft.StableStore) {
|
|
||||||
// Run SetUint64 a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
if err := store.SetUint64([]byte{byte(n)}, uint64(n)); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUint64(b *testing.B, store raft.StableStore) {
|
|
||||||
// Create some fake data
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
if err := store.SetUint64([]byte{byte(i)}, uint64(i)); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
// Run GetUint64 a number of times
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
if _, err := store.Get([]byte{0x05}); err != nil {
|
|
||||||
b.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,373 +0,0 @@
|
||||||
// Package idn implements encoding from and to punycode as speficied by RFC 3492.
|
|
||||||
package idn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Implementation idea from RFC itself and from from IDNA::Punycode created by
|
|
||||||
// Tatsuhiko Miyagawa <miyagawa@bulknews.net> and released under Perl Artistic
|
|
||||||
// License in 2002.
|
|
||||||
|
|
||||||
const (
|
|
||||||
_MIN rune = 1
|
|
||||||
_MAX rune = 26
|
|
||||||
_SKEW rune = 38
|
|
||||||
_BASE rune = 36
|
|
||||||
_BIAS rune = 72
|
|
||||||
_N rune = 128
|
|
||||||
_DAMP rune = 700
|
|
||||||
|
|
||||||
_DELIMITER = '-'
|
|
||||||
_PREFIX = "xn--"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ToPunycode converts unicode domain names to DNS-appropriate punycode names.
|
|
||||||
// This function will return an empty string result for domain names with
|
|
||||||
// invalid unicode strings. This function expects domain names in lowercase.
|
|
||||||
func ToPunycode(s string) string {
|
|
||||||
// Early check to see if encoding is needed.
|
|
||||||
// This will prevent making heap allocations when not needed.
|
|
||||||
if !needToPunycode(s) {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens := dns.SplitDomainName(s)
|
|
||||||
switch {
|
|
||||||
case s == "":
|
|
||||||
return ""
|
|
||||||
case tokens == nil: // s == .
|
|
||||||
return "."
|
|
||||||
case s[len(s)-1] == '.':
|
|
||||||
tokens = append(tokens, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range tokens {
|
|
||||||
t := encode([]byte(tokens[i]))
|
|
||||||
if t == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
tokens[i] = string(t)
|
|
||||||
}
|
|
||||||
return strings.Join(tokens, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromPunycode returns unicode domain name from provided punycode string.
|
|
||||||
// This function expects punycode strings in lowercase.
|
|
||||||
func FromPunycode(s string) string {
|
|
||||||
// Early check to see if decoding is needed.
|
|
||||||
// This will prevent making heap allocations when not needed.
|
|
||||||
if !needFromPunycode(s) {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens := dns.SplitDomainName(s)
|
|
||||||
switch {
|
|
||||||
case s == "":
|
|
||||||
return ""
|
|
||||||
case tokens == nil: // s == .
|
|
||||||
return "."
|
|
||||||
case s[len(s)-1] == '.':
|
|
||||||
tokens = append(tokens, "")
|
|
||||||
}
|
|
||||||
for i := range tokens {
|
|
||||||
tokens[i] = string(decode([]byte(tokens[i])))
|
|
||||||
}
|
|
||||||
return strings.Join(tokens, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
// digitval converts single byte into meaningful value that's used to calculate decoded unicode character.
|
|
||||||
const errdigit = 0xffff
|
|
||||||
|
|
||||||
func digitval(code rune) rune {
|
|
||||||
switch {
|
|
||||||
case code >= 'A' && code <= 'Z':
|
|
||||||
return code - 'A'
|
|
||||||
case code >= 'a' && code <= 'z':
|
|
||||||
return code - 'a'
|
|
||||||
case code >= '0' && code <= '9':
|
|
||||||
return code - '0' + 26
|
|
||||||
}
|
|
||||||
return errdigit
|
|
||||||
}
|
|
||||||
|
|
||||||
// lettercode finds BASE36 byte (a-z0-9) based on calculated number.
|
|
||||||
func lettercode(digit rune) rune {
|
|
||||||
switch {
|
|
||||||
case digit >= 0 && digit <= 25:
|
|
||||||
return digit + 'a'
|
|
||||||
case digit >= 26 && digit <= 36:
|
|
||||||
return digit - 26 + '0'
|
|
||||||
}
|
|
||||||
panic("dns: not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
// adapt calculates next bias to be used for next iteration delta.
|
|
||||||
func adapt(delta rune, numpoints int, firsttime bool) rune {
|
|
||||||
if firsttime {
|
|
||||||
delta /= _DAMP
|
|
||||||
} else {
|
|
||||||
delta /= 2
|
|
||||||
}
|
|
||||||
|
|
||||||
var k rune
|
|
||||||
for delta = delta + delta/rune(numpoints); delta > (_BASE-_MIN)*_MAX/2; k += _BASE {
|
|
||||||
delta /= _BASE - _MIN
|
|
||||||
}
|
|
||||||
|
|
||||||
return k + ((_BASE-_MIN+1)*delta)/(delta+_SKEW)
|
|
||||||
}
|
|
||||||
|
|
||||||
// next finds minimal rune (one with lowest codepoint value) that should be equal or above boundary.
|
|
||||||
func next(b []rune, boundary rune) rune {
|
|
||||||
if len(b) == 0 {
|
|
||||||
panic("dns: invalid set of runes to determine next one")
|
|
||||||
}
|
|
||||||
m := b[0]
|
|
||||||
for _, x := range b[1:] {
|
|
||||||
if x >= boundary && (m < boundary || x < m) {
|
|
||||||
m = x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// preprune converts unicode rune to lower case. At this time it's not
|
|
||||||
// supporting all things described in RFCs.
|
|
||||||
func preprune(r rune) rune {
|
|
||||||
if unicode.IsUpper(r) {
|
|
||||||
r = unicode.ToLower(r)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// tfunc is a function that helps calculate each character weight.
|
|
||||||
func tfunc(k, bias rune) rune {
|
|
||||||
switch {
|
|
||||||
case k <= bias:
|
|
||||||
return _MIN
|
|
||||||
case k >= bias+_MAX:
|
|
||||||
return _MAX
|
|
||||||
}
|
|
||||||
return k - bias
|
|
||||||
}
|
|
||||||
|
|
||||||
// needToPunycode returns true for strings that require punycode encoding
|
|
||||||
// (contain unicode characters).
|
|
||||||
func needToPunycode(s string) bool {
|
|
||||||
// This function is very similar to bytes.Runes. We don't use bytes.Runes
|
|
||||||
// because it makes a heap allocation that's not needed here.
|
|
||||||
for i := 0; len(s) > 0; i++ {
|
|
||||||
r, l := utf8.DecodeRuneInString(s)
|
|
||||||
if r > 0x7f {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
s = s[l:]
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// needFromPunycode returns true for strings that require punycode decoding.
|
|
||||||
func needFromPunycode(s string) bool {
|
|
||||||
if s == "." {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
off := 0
|
|
||||||
end := false
|
|
||||||
pl := len(_PREFIX)
|
|
||||||
sl := len(s)
|
|
||||||
|
|
||||||
// If s starts with _PREFIX.
|
|
||||||
if sl > pl && s[off:off+pl] == _PREFIX {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
// Find the part after the next ".".
|
|
||||||
off, end = dns.NextLabel(s, off)
|
|
||||||
if end {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// If this parts starts with _PREFIX.
|
|
||||||
if sl-off > pl && s[off:off+pl] == _PREFIX {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode transforms Unicode input bytes (that represent DNS label) into
|
|
||||||
// punycode bytestream. This function would return nil if there's an invalid
|
|
||||||
// character in the label.
|
|
||||||
func encode(input []byte) []byte {
|
|
||||||
n, bias := _N, _BIAS
|
|
||||||
|
|
||||||
b := bytes.Runes(input)
|
|
||||||
for i := range b {
|
|
||||||
if !isValidRune(b[i]) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
b[i] = preprune(b[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
basic := make([]byte, 0, len(b))
|
|
||||||
for _, ltr := range b {
|
|
||||||
if ltr <= 0x7f {
|
|
||||||
basic = append(basic, byte(ltr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
basiclen := len(basic)
|
|
||||||
fulllen := len(b)
|
|
||||||
if basiclen == fulllen {
|
|
||||||
return basic
|
|
||||||
}
|
|
||||||
|
|
||||||
var out bytes.Buffer
|
|
||||||
|
|
||||||
out.WriteString(_PREFIX)
|
|
||||||
if basiclen > 0 {
|
|
||||||
out.Write(basic)
|
|
||||||
out.WriteByte(_DELIMITER)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ltr, nextltr rune
|
|
||||||
delta, q rune // delta calculation (see rfc)
|
|
||||||
t, k, cp rune // weight and codepoint calculation
|
|
||||||
)
|
|
||||||
|
|
||||||
s := &bytes.Buffer{}
|
|
||||||
for h := basiclen; h < fulllen; n, delta = n+1, delta+1 {
|
|
||||||
nextltr = next(b, n)
|
|
||||||
s.Truncate(0)
|
|
||||||
s.WriteRune(nextltr)
|
|
||||||
delta, n = delta+(nextltr-n)*rune(h+1), nextltr
|
|
||||||
|
|
||||||
for _, ltr = range b {
|
|
||||||
if ltr < n {
|
|
||||||
delta++
|
|
||||||
}
|
|
||||||
if ltr == n {
|
|
||||||
q = delta
|
|
||||||
for k = _BASE; ; k += _BASE {
|
|
||||||
t = tfunc(k, bias)
|
|
||||||
if q < t {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
cp = t + ((q - t) % (_BASE - t))
|
|
||||||
out.WriteRune(lettercode(cp))
|
|
||||||
q = (q - t) / (_BASE - t)
|
|
||||||
}
|
|
||||||
|
|
||||||
out.WriteRune(lettercode(q))
|
|
||||||
|
|
||||||
bias = adapt(delta, h+1, h == basiclen)
|
|
||||||
h, delta = h+1, 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode transforms punycode input bytes (that represent DNS label) into Unicode bytestream.
|
|
||||||
func decode(b []byte) []byte {
|
|
||||||
src := b // b would move and we need to keep it
|
|
||||||
|
|
||||||
n, bias := _N, _BIAS
|
|
||||||
if !bytes.HasPrefix(b, []byte(_PREFIX)) {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
out := make([]rune, 0, len(b))
|
|
||||||
b = b[len(_PREFIX):]
|
|
||||||
for pos := len(b) - 1; pos >= 0; pos-- {
|
|
||||||
// only last delimiter is our interest
|
|
||||||
if b[pos] == _DELIMITER {
|
|
||||||
out = append(out, bytes.Runes(b[:pos])...)
|
|
||||||
b = b[pos+1:] // trim source string
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(b) == 0 {
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
i, oldi, w rune
|
|
||||||
ch byte
|
|
||||||
t, digit rune
|
|
||||||
ln int
|
|
||||||
)
|
|
||||||
|
|
||||||
for i = 0; len(b) > 0; i++ {
|
|
||||||
oldi, w = i, 1
|
|
||||||
for k := _BASE; len(b) > 0; k += _BASE {
|
|
||||||
ch, b = b[0], b[1:]
|
|
||||||
digit = digitval(rune(ch))
|
|
||||||
if digit == errdigit {
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
i += digit * w
|
|
||||||
if i < 0 {
|
|
||||||
// safety check for rune overflow
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
|
|
||||||
t = tfunc(k, bias)
|
|
||||||
if digit < t {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
w *= _BASE - t
|
|
||||||
}
|
|
||||||
ln = len(out) + 1
|
|
||||||
bias = adapt(i-oldi, ln, oldi == 0)
|
|
||||||
n += i / rune(ln)
|
|
||||||
i = i % rune(ln)
|
|
||||||
// insert
|
|
||||||
out = append(out, 0)
|
|
||||||
copy(out[i+1:], out[i:])
|
|
||||||
out[i] = n
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret bytes.Buffer
|
|
||||||
for _, r := range out {
|
|
||||||
ret.WriteRune(r)
|
|
||||||
}
|
|
||||||
return ret.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// isValidRune checks if the character is valid. We will look for the
|
|
||||||
// character property in the code points list. For now we aren't checking special
|
|
||||||
// rules in case of contextual property
|
|
||||||
func isValidRune(r rune) bool {
|
|
||||||
return findProperty(r) == propertyPVALID
|
|
||||||
}
|
|
||||||
|
|
||||||
// findProperty will try to check the code point property of the given
|
|
||||||
// character. It will use a binary search algorithm as we have a slice of
|
|
||||||
// ordered ranges (average case performance O(log n))
|
|
||||||
func findProperty(r rune) property {
|
|
||||||
imin, imax := 0, len(codePoints)
|
|
||||||
|
|
||||||
for imax >= imin {
|
|
||||||
imid := (imin + imax) / 2
|
|
||||||
|
|
||||||
codePoint := codePoints[imid]
|
|
||||||
if (codePoint.start == r && codePoint.end == 0) || (codePoint.start <= r && codePoint.end >= r) {
|
|
||||||
return codePoint.state
|
|
||||||
}
|
|
||||||
|
|
||||||
if (codePoint.end > 0 && codePoint.end < r) || (codePoint.end == 0 && codePoint.start < r) {
|
|
||||||
imin = imid + 1
|
|
||||||
} else {
|
|
||||||
imax = imid - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return propertyUnknown
|
|
||||||
}
|
|
|
@ -263,10 +263,6 @@
|
||||||
"path": "github.com/hashicorp/hcl/hcl/parser",
|
"path": "github.com/hashicorp/hcl/hcl/parser",
|
||||||
"revision": "578dd9746824a54637686b51a41bad457a56bcef"
|
"revision": "578dd9746824a54637686b51a41bad457a56bcef"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "github.com/hashicorp/hcl/hcl/printer",
|
|
||||||
"revision": "578dd9746824a54637686b51a41bad457a56bcef"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "github.com/hashicorp/hcl/hcl/scanner",
|
"path": "github.com/hashicorp/hcl/hcl/scanner",
|
||||||
"revision": "578dd9746824a54637686b51a41bad457a56bcef"
|
"revision": "578dd9746824a54637686b51a41bad457a56bcef"
|
||||||
|
@ -325,10 +321,6 @@
|
||||||
"path": "github.com/hashicorp/raft-boltdb",
|
"path": "github.com/hashicorp/raft-boltdb",
|
||||||
"revision": "057b893fd996696719e98b6c44649ea14968c811"
|
"revision": "057b893fd996696719e98b6c44649ea14968c811"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "github.com/hashicorp/raft/bench",
|
|
||||||
"revision": "057b893fd996696719e98b6c44649ea14968c811"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "github.com/hashicorp/scada-client",
|
"path": "github.com/hashicorp/scada-client",
|
||||||
"revision": "84989fd23ad4cc0e7ad44d6a871fd793eb9beb0a"
|
"revision": "84989fd23ad4cc0e7ad44d6a871fd793eb9beb0a"
|
||||||
|
@ -385,12 +377,6 @@
|
||||||
"revision": "db96a2b759cdef4f11a34506a42eb8d1290c598e",
|
"revision": "db96a2b759cdef4f11a34506a42eb8d1290c598e",
|
||||||
"revisionTime": "2016-07-26T03:20:27Z"
|
"revisionTime": "2016-07-26T03:20:27Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "K5U2WCS4hqdePy0rCadvDZHYE4w=",
|
|
||||||
"path": "github.com/miekg/dns/idn",
|
|
||||||
"revision": "db96a2b759cdef4f11a34506a42eb8d1290c598e",
|
|
||||||
"revisionTime": "2016-07-26T03:20:27Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "github.com/mitchellh/cli",
|
"path": "github.com/mitchellh/cli",
|
||||||
"revision": "cb6853d606ea4a12a15ac83cc43503df99fd28fb"
|
"revision": "cb6853d606ea4a12a15ac83cc43503df99fd28fb"
|
||||||
|
|
Loading…
Reference in New Issue