<commit_before>package parser

import (
	"fmt"
	"go/ast"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"io/ioutil"
)

// ParseFiles parses files at the same time
func ParseFiles(paths []string) ([]*GoFile, error) {
	files := make([]*ast.File, len(paths))
	fsets := make([]*token.FileSet, len(paths))
	for i, p := range paths {
		// File: A File node represents a Go source file: https://golang.org/pkg/go/ast/#File
		fset := token.NewFileSet()
		file, err := parser.ParseFile(fset, p, nil, 0)
		if err != nil {
			return nil, err
		}
		files[i] = file
		fsets[i] = fset
	}

	goFiles := make([]*GoFile, len(paths))
	for i, p := range paths {
		goFile, err := parseFile(p, files[i], fsets[i], files)
		if err != nil {
			return nil, err
		}
		goFiles[i] = goFile
	}
	return goFiles, nil
}

// ParseSingleFile parses a single file at the same time
func ParseSingleFile(path string) (*GoFile, error) {
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, path, nil, 0)
	if err != nil {
		return nil, err
	}
	return parseFile(path, file, fset, []*ast.File{file})
}

func parseFile(path string, file *ast.File, fset *token.FileSet, files []*ast.File) (*GoFile, error) {
	source, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	// To import sources from vendor, we use "source" compile
	// https://github.com/golang/go/issues/11415#issuecomment-283445198
	conf := importer.For("source", nil)
	info := &types.Info{
		Types: make(map[ast.Expr]types.TypeAndValue),
		Defs:  make(map[*ast.Ident]types.Object),
		Uses:  make(map[*ast.Ident]types.Object),
	}

	if _, err = conf.Check(file.Name.Name, fset, files, info); err != nil {
		return nil, err
	}

	goFile := &GoFile{
		Path:    path,
		Package: file.Name.Name,
		Structs: []*GoStruct{},
	}

	// File.Decls: A list of the declarations in the file: https://golang.org/pkg/go/ast/#Decl
	for _, decl := range file.Decls {
		switch declType := decl.(type) {

		// GenDecl: represents an import, constant, type or variable declaration: https://golang.org/pkg/go/ast/#GenDecl
		case *ast.GenDecl:
			genDecl := declType

			// Specs: the Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec: https://golang.org/pkg/go/ast/#Spec
			for _, genSpec := range genDecl.Specs {
				switch genSpecType := genSpec.(type) {

				// TypeSpec: A TypeSpec node represents a type declaration: https://golang.org/pkg/go/ast/#TypeSpec
				case *ast.TypeSpec:
					typeSpec := genSpecType

					// typeSpec.Type: an Expr (expression) node: https://golang.org/pkg/go/ast/#Expr
					switch typeSpecType := typeSpec.Type.(type) {

					// StructType: A StructType node represents a struct type: https://golang.org/pkg/go/ast/#StructType
					case (*ast.StructType):
						structType := typeSpecType
						goStruct := buildGoStruct(source, goFile, info, typeSpec, structType)
						goFile.Structs = append(goFile.Structs, goStruct)
					// InterfaceType: An InterfaceType node represents an interface type. https://golang.org/pkg/go/ast/#InterfaceType
					case (*ast.InterfaceType):
						interfaceType := typeSpecType
						goInterface := buildGoInterface(source, goFile, info, typeSpec, interfaceType)
						goFile.Interfaces = append(goFile.Interfaces, goInterface)
					default:
						// a not-implemented typeSpec.Type.(type), ignore
					}
					// ImportSpec: An ImportSpec node represents a single package import. https://golang.org/pkg/go/ast/#ImportSpec
				case *ast.ImportSpec:
					importSpec := genSpec.(*ast.ImportSpec)
					goImport := buildGoImport(importSpec, goFile)
					goFile.Imports = append(goFile.Imports, goImport)
				default:
					// a not-implemented genSpec.(type), ignore
				}
			}
		case *ast.FuncDecl:
			funcDecl := declType
			goStructMethod := buildStructMethod(info, funcDecl, source)
			goFile.StructMethods = append(goFile.StructMethods, goStructMethod)

		default:
			// a not-implemented decl.(type), ignore
		}
	}

	return goFile, nil
}

func buildGoImport(spec *ast.ImportSpec, file *GoFile) *GoImport {
	name := ""
	if spec.Name != nil {
		name = spec.Name.Name
	}

	path := ""
	if spec.Path != nil {
		path = spec.Path.Value
	}

	return &GoImport{
		Name: name,
		Path: path,
		File: file,
	}
}

func buildGoInterface(source []byte, file *GoFile, info *types.Info, typeSpec *ast.TypeSpec, interfaceType *ast.InterfaceType) *GoInterface {
	goInterface := &GoInterface{
		File:    file,
		Name:    typeSpec.Name.Name,
		Methods: buildMethodList(info, interfaceType.Methods.List, source),
	}

	return goInterface
}

func buildMethodList(info *types.Info, fieldList []*ast.Field, source []byte) []*GoMethod {
	methods := []*GoMethod{}

	for _, field := range fieldList {
		name := getNames(field)[0]

		fType, ok := field.Type.(*ast.FuncType)
		if !ok {
			// method was not a function
			continue
		}

		goMethod := &GoMethod{
			Name:    name,
			Params:  buildTypeList(info, fType.Params, source),
			Results: buildTypeList(info, fType.Results, source),
		}

		methods = append(methods, goMethod)
	}

	return methods
}

func buildStructMethod(info *types.Info, funcDecl *ast.FuncDecl, source []byte) *GoStructMethod {
	return &GoStructMethod{
		Receivers: buildReceiverList(info, funcDecl.Recv, source),
		GoMethod: GoMethod{
			Name:    funcDecl.Name.Name,
			Params:  buildTypeList(info, funcDecl.Type.Params, source),
			Results: buildTypeList(info, funcDecl.Type.Results, source),
		},
	}
}

func buildReceiverList(info *types.Info, fieldList *ast.FieldList, source []byte) []string {
	receivers := []string{}

	if fieldList != nil {
		for _, t := range fieldList.List {
			receivers = append(receivers, getTypeString(t.Type, source))
		}
	}

	return receivers
}

func buildTypeList(info *types.Info, fieldList *ast.FieldList, source []byte) []*GoType {
	types := []*GoType{}

	if fieldList != nil {
		for _, t := range fieldList.List {
			goType := buildType(info, t.Type, source)

			for _, n := range getNames(t) {
				copyType := copyType(goType)
				copyType.Name = n
				types = append(types, copyType)
			}
		}
	}

	return types
}

func getNames(field *ast.Field) []string {
	if field.Names == nil || len(field.Names) == 0 {
		return []string{""}
	}

	result := []string{}
	for _, name := range field.Names {
		result = append(result, name.String())
	}

	return result
}

func getTypeString(expr ast.Expr, source []byte) string {
	return string(source[expr.Pos()-1 : expr.End()-1])
}

func getUnderlyingTypeString(info *types.Info, expr ast.Expr) string {
	if typeInfo := info.TypeOf(expr); typeInfo != nil {
		if underlying := typeInfo.Underlying(); underlying != nil {
			return underlying.String()
		}
	}

	return ""
}

func copyType(goType *GoType) *GoType {
	return &GoType{
		Type:       goType.Type,
		Inner:      goType.Inner,
		Name:       goType.Name,
		Underlying: goType.Underlying,
	}
}

func buildType(info *types.Info, expr ast.Expr, source []byte) *GoType {
	innerTypes := []*GoType{}
	typeString := getTypeString(expr, source)
	underlyingString := getUnderlyingTypeString(info, expr)

	switch specType := expr.(type) {
	case *ast.FuncType:
		innerTypes = append(innerTypes, buildTypeList(info, specType.Params, source)...)
		innerTypes = append(innerTypes, buildTypeList(info, specType.Results, source)...)
	case *ast.ArrayType:
		innerTypes = append(innerTypes, buildType(info, specType.Elt, source))
	case *ast.StructType:
		innerTypes = append(innerTypes, buildTypeList(info, specType.Fields, source)...)
	case *ast.MapType:
		innerTypes = append(innerTypes, buildType(info, specType.Key, source))
		innerTypes = append(innerTypes, buildType(info, specType.Value, source))
	case *ast.ChanType:
		innerTypes = append(innerTypes, buildType(info, specType.Value, source))
	case *ast.StarExpr:
		innerTypes = append(innerTypes, buildType(info, specType.X, source))
	case *ast.Ellipsis:
		innerTypes = append(innerTypes, buildType(info, specType.Elt, source))
	case *ast.InterfaceType:
		methods := buildMethodList(info, specType.Methods.List, source)
		for _, m := range methods {
			innerTypes = append(innerTypes, m.Params...)
			innerTypes = append(innerTypes, m.Results...)
		}

	case *ast.Ident:
	case *ast.SelectorExpr:
	default:
		fmt.Printf("Unexpected field type: `%s`,\n %#v\n", typeString, specType)
	}

	return &GoType{
		Type:       typeString,
		Underlying: underlyingString,
		Inner:      innerTypes,
	}
}

func buildGoStruct(source []byte, file *GoFile, info *types.Info, typeSpec *ast.TypeSpec, structType *ast.StructType) *GoStruct {
	goStruct := &GoStruct{
		File:   file,
		Name:   typeSpec.Name.Name,
		Fields: []*GoField{},
	}

	// Field: A Field declaration list in a struct type, a method list in an interface type,
	// or a parameter/result declaration in a signature: https://golang.org/pkg/go/ast/#Field
	for _, field := range structType.Fields.List {
		for _, name := range field.Names {
			goField := &GoField{
				Struct: goStruct,
				Name:   name.String(),
				Type:   string(source[field.Type.Pos()-1 : field.Type.End()-1]),
			}

			if field.Tag != nil {
				goTag := &GoTag{
					Field: goField,
					Value: field.Tag.Value,
				}

				goField.Tag = goTag
			}

			goStruct.Fields = append(goStruct.Fields, goField)
		}
	}

	return goStruct
}
<commit_msg>Fix compile error<commit_after>package parser

import (
	"fmt"
	"go/ast"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"io/ioutil"
)

// ParseFiles parses files at the same time
func ParseFiles(paths []string) ([]*GoFile, error) {
	files := make([]*ast.File, len(paths))
	fsets := make([]*token.FileSet, len(paths))
	for i, p := range paths {
		// File: A File node represents a Go source file: https://golang.org/pkg/go/ast/#File
		fset := token.NewFileSet()
		file, err := parser.ParseFile(fset, p, nil, 0)
		if err != nil {
			return nil, err
		}
		files[i] = file
		fsets[i] = fset
	}

	goFiles := make([]*GoFile, len(paths))
	for i, p := range paths {
		goFile, err := parseFile(p, files[i], fsets[i], files)
		if err != nil {
			return nil, err
		}
		goFiles[i] = goFile
	}
	return goFiles, nil
}

// ParseSingleFile parses a single file at the same time
func ParseSingleFile(path string) (*GoFile, error) {
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, path, nil, 0)
	if err != nil {
		return nil, err
	}
	return parseFile(path, file, fset, []*ast.File{file})
}

func parseFile(path string, file *ast.File, fset *token.FileSet, files []*ast.File) (*GoFile, error) {
	source, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	// To import sources from vendor, we use "source" compile
	// https://github.com/golang/go/issues/11415#issuecomment-283445198
	conf := types.Config{Importer: importer.For("source", nil)}
	info := &types.Info{
		Types: make(map[ast.Expr]types.TypeAndValue),
		Defs:  make(map[*ast.Ident]types.Object),
		Uses:  make(map[*ast.Ident]types.Object),
	}

	if _, err = conf.Check(file.Name.Name, fset, files, info); err != nil {
		return nil, err
	}

	goFile := &GoFile{
		Path:    path,
		Package: file.Name.Name,
		Structs: []*GoStruct{},
	}

	// File.Decls: A list of the declarations in the file: https://golang.org/pkg/go/ast/#Decl
	for _, decl := range file.Decls {
		switch declType := decl.(type) {

		// GenDecl: represents an import, constant, type or variable declaration: https://golang.org/pkg/go/ast/#GenDecl
		case *ast.GenDecl:
			genDecl := declType

			// Specs: the Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec: https://golang.org/pkg/go/ast/#Spec
			for _, genSpec := range genDecl.Specs {
				switch genSpecType := genSpec.(type) {

				// TypeSpec: A TypeSpec node represents a type declaration: https://golang.org/pkg/go/ast/#TypeSpec
				case *ast.TypeSpec:
					typeSpec := genSpecType

					// typeSpec.Type: an Expr (expression) node: https://golang.org/pkg/go/ast/#Expr
					switch typeSpecType := typeSpec.Type.(type) {

					// StructType: A StructType node represents a struct type: https://golang.org/pkg/go/ast/#StructType
					case (*ast.StructType):
						structType := typeSpecType
						goStruct := buildGoStruct(source, goFile, info, typeSpec, structType)
						goFile.Structs = append(goFile.Structs, goStruct)
					// InterfaceType: An InterfaceType node represents an interface type. https://golang.org/pkg/go/ast/#InterfaceType
					case (*ast.InterfaceType):
						interfaceType := typeSpecType
						goInterface := buildGoInterface(source, goFile, info, typeSpec, interfaceType)
						goFile.Interfaces = append(goFile.Interfaces, goInterface)
					default:
						// a not-implemented typeSpec.Type.(type), ignore
					}
					// ImportSpec: An ImportSpec node represents a single package import. https://golang.org/pkg/go/ast/#ImportSpec
				case *ast.ImportSpec:
					importSpec := genSpec.(*ast.ImportSpec)
					goImport := buildGoImport(importSpec, goFile)
					goFile.Imports = append(goFile.Imports, goImport)
				default:
					// a not-implemented genSpec.(type), ignore
				}
			}
		case *ast.FuncDecl:
			funcDecl := declType
			goStructMethod := buildStructMethod(info, funcDecl, source)
			goFile.StructMethods = append(goFile.StructMethods, goStructMethod)

		default:
			// a not-implemented decl.(type), ignore
		}
	}

	return goFile, nil
}

func buildGoImport(spec *ast.ImportSpec, file *GoFile) *GoImport {
	name := ""
	if spec.Name != nil {
		name = spec.Name.Name
	}

	path := ""
	if spec.Path != nil {
		path = spec.Path.Value
	}

	return &GoImport{
		Name: name,
		Path: path,
		File: file,
	}
}

func buildGoInterface(source []byte, file *GoFile, info *types.Info, typeSpec *ast.TypeSpec, interfaceType *ast.InterfaceType) *GoInterface {
	goInterface := &GoInterface{
		File:    file,
		Name:    typeSpec.Name.Name,
		Methods: buildMethodList(info, interfaceType.Methods.List, source),
	}

	return goInterface
}

func buildMethodList(info *types.Info, fieldList []*ast.Field, source []byte) []*GoMethod {
	methods := []*GoMethod{}

	for _, field := range fieldList {
		name := getNames(field)[0]

		fType, ok := field.Type.(*ast.FuncType)
		if !ok {
			// method was not a function
			continue
		}

		goMethod := &GoMethod{
			Name:    name,
			Params:  buildTypeList(info, fType.Params, source),
			Results: buildTypeList(info, fType.Results, source),
		}

		methods = append(methods, goMethod)
	}

	return methods
}

func buildStructMethod(info *types.Info, funcDecl *ast.FuncDecl, source []byte) *GoStructMethod {
	return &GoStructMethod{
		Receivers: buildReceiverList(info, funcDecl.Recv, source),
		GoMethod: GoMethod{
			Name:    funcDecl.Name.Name,
			Params:  buildTypeList(info, funcDecl.Type.Params, source),
			Results: buildTypeList(info, funcDecl.Type.Results, source),
		},
	}
}

func buildReceiverList(info *types.Info, fieldList *ast.FieldList, source []byte) []string {
	receivers := []string{}

	if fieldList != nil {
		for _, t := range fieldList.List {
			receivers = append(receivers, getTypeString(t.Type, source))
		}
	}

	return receivers
}

func buildTypeList(info *types.Info, fieldList *ast.FieldList, source []byte) []*GoType {
	types := []*GoType{}

	if fieldList != nil {
		for _, t := range fieldList.List {
			goType := buildType(info, t.Type, source)

			for _, n := range getNames(t) {
				copyType := copyType(goType)
				copyType.Name = n
				types = append(types, copyType)
			}
		}
	}

	return types
}

func getNames(field *ast.Field) []string {
	if field.Names == nil || len(field.Names) == 0 {
		return []string{""}
	}

	result := []string{}
	for _, name := range field.Names {
		result = append(result, name.String())
	}

	return result
}

func getTypeString(expr ast.Expr, source []byte) string {
	return string(source[expr.Pos()-1 : expr.End()-1])
}

func getUnderlyingTypeString(info *types.Info, expr ast.Expr) string {
	if typeInfo := info.TypeOf(expr); typeInfo != nil {
		if underlying := typeInfo.Underlying(); underlying != nil {
			return underlying.String()
		}
	}

	return ""
}

func copyType(goType *GoType) *GoType {
	return &GoType{
		Type:       goType.Type,
		Inner:      goType.Inner,
		Name:       goType.Name,
		Underlying: goType.Underlying,
	}
}

func buildType(info *types.Info, expr ast.Expr, source []byte) *GoType {
	innerTypes := []*GoType{}
	typeString := getTypeString(expr, source)
	underlyingString := getUnderlyingTypeString(info, expr)

	switch specType := expr.(type) {
	case *ast.FuncType:
		innerTypes = append(innerTypes, buildTypeList(info, specType.Params, source)...)
		innerTypes = append(innerTypes, buildTypeList(info, specType.Results, source)...)
	case *ast.ArrayType:
		innerTypes = append(innerTypes, buildType(info, specType.Elt, source))
	case *ast.StructType:
		innerTypes = append(innerTypes, buildTypeList(info, specType.Fields, source)...)
	case *ast.MapType:
		innerTypes = append(innerTypes, buildType(info, specType.Key, source))
		innerTypes = append(innerTypes, buildType(info, specType.Value, source))
	case *ast.ChanType:
		innerTypes = append(innerTypes, buildType(info, specType.Value, source))
	case *ast.StarExpr:
		innerTypes = append(innerTypes, buildType(info, specType.X, source))
	case *ast.Ellipsis:
		innerTypes = append(innerTypes, buildType(info, specType.Elt, source))
	case *ast.InterfaceType:
		methods := buildMethodList(info, specType.Methods.List, source)
		for _, m := range methods {
			innerTypes = append(innerTypes, m.Params...)
			innerTypes = append(innerTypes, m.Results...)
		}

	case *ast.Ident:
	case *ast.SelectorExpr:
	default:
		fmt.Printf("Unexpected field type: `%s`,\n %#v\n", typeString, specType)
	}

	return &GoType{
		Type:       typeString,
		Underlying: underlyingString,
		Inner:      innerTypes,
	}
}

func buildGoStruct(source []byte, file *GoFile, info *types.Info, typeSpec *ast.TypeSpec, structType *ast.StructType) *GoStruct {
	goStruct := &GoStruct{
		File:   file,
		Name:   typeSpec.Name.Name,
		Fields: []*GoField{},
	}

	// Field: A Field declaration list in a struct type, a method list in an interface type,
	// or a parameter/result declaration in a signature: https://golang.org/pkg/go/ast/#Field
	for _, field := range structType.Fields.List {
		for _, name := range field.Names {
			goField := &GoField{
				Struct: goStruct,
				Name:   name.String(),
				Type:   string(source[field.Type.Pos()-1 : field.Type.End()-1]),
			}

			if field.Tag != nil {
				goTag := &GoTag{
					Field: goField,
					Value: field.Tag.Value,
				}

				goField.Tag = goTag
			}

			goStruct.Fields = append(goStruct.Fields, goField)
		}
	}

	return goStruct
}
<|endoftext|>


<commit_before>package css

import (
	"fmt"
	"log"

	"github.com/gorilla/css/scanner"
)

/*
	stylesheet  : [ CDO | CDC | S | statement ]*;
	statement   : ruleset | at-rule;
	at-rule     : ATKEYWORD S* any* [ block | ';' S* ];
	block       : '{' S* [ any | block | ATKEYWORD S* | ';' S* ]* '}' S*;
	ruleset     : selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
	selector    : any+;
	declaration : property S* ':' S* value;
	property    : IDENT;
	value       : [ any | block | ATKEYWORD S* ]+;
	any         : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
	              | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
	              | DASHMATCH | ':' | FUNCTION S* [any|unused]* ')'
	              | '(' S* [any|unused]* ')' | '[' S* [any|unused]* ']'
	              ] S*;
	unused      : block | ATKEYWORD S* | ';' S* | CDO S* | CDC S*;
*/

type State int

const (
	STATE_NONE State = iota
	STATE_SELECTOR
	STATE_PROPERTY
	STATE_VALUE
)

type parserContext struct {
	State             State
	NowSelector       []*scanner.Token
	NowRuleType       RuleType
	CurrentNestedRule *CSSRule
}

func (context *parserContext) resetContextStyleRule() {
	context.NowSelector = make([]*scanner.Token, 0)
	context.NowRuleType = STYLE_RULE
	context.State = STATE_NONE
}

func parseRule(context *parserContext, s *scanner.Scanner, css *CSSStyleSheet) {
	rule := NewRule(context.NowRuleType)
	selector := append(context.NowSelector, parseSelector(s)...)
	rule.Style.Selector = &CSSValue{Tokens: selector}
	rule.Style.Styles = parseBlock(s)
	if context.CurrentNestedRule != nil {
		context.CurrentNestedRule.Rules = append(context.CurrentNestedRule.Rules, rule)
	} else {
		css.CssRuleList = append(css.CssRuleList, rule)
	}
	context.resetContextStyleRule()
}

// Parse takes a string of valid css rules, stylesheet,
// and parses it. Be aware this function has poor error handling
// so you should have valid syntax in your css
func Parse(csstext string) *CSSStyleSheet {
	context := &parserContext{
		State:             STATE_NONE,
		NowSelector:       make([]*scanner.Token, 0),
		NowRuleType:       STYLE_RULE,
		CurrentNestedRule: nil,
	}

	css := &CSSStyleSheet{}
	css.CssRuleList = make([]*CSSRule, 0)
	s := scanner.New(csstext)

	for {
		token := s.Next()

		if token.Type == scanner.TokenEOF || token.Type == scanner.TokenError {
			break
		}

		switch token.Type {
		case scanner.TokenCDO:
			break
		case scanner.TokenCDC:
			break
		case scanner.TokenComment:
			break
		case scanner.TokenS:
			break
		case scanner.TokenAtKeyword:
			switch token.Value {
			case "@media":
				context.NowRuleType = MEDIA_RULE
			case "@font-face":
				// Parse as normal rule, would be nice to parse according to syntax
				// https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face
				context.NowRuleType = FONT_FACE_RULE
				parseRule(context, s, css)
			case "@import":
				// No validation
				// https://developer.mozilla.org/en-US/docs/Web/CSS/@import
				rule := parseAtNoBody(s, IMPORT_RULE)
				if rule != nil {
					css.CssRuleList = append(css.CssRuleList, rule)
				}
				context.resetContextStyleRule()
			case "@charset":
				// No validation
				// https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
				rule := parseAtNoBody(s, CHARSET_RULE)
				if rule != nil {
					css.CssRuleList = append(css.CssRuleList, rule)
				}
				context.resetContextStyleRule()

			case "@page":
				context.NowRuleType = PAGE_RULE
				parseRule(context, s, css)
			case "@keyframes":
				context.NowRuleType = KEYFRAMES_RULE
			case "@-webkit-keyframes":
				context.NowRuleType = WEBKIT_KEYFRAMES_RULE
			case "@counter-style":
				context.NowRuleType = COUNTER_STYLE_RULE
				parseRule(context, s, css)
			default:
				log.Println(fmt.Printf("Skip unsupported atrule: %s", token.Value))
				skipRules(s)
				context.resetContextStyleRule()
			}
		default:
			if context.State == STATE_NONE {
				if token.Value == "}" && context.CurrentNestedRule != nil {
					// close media/keyframe/… rule
					css.CssRuleList = append(css.CssRuleList, context.CurrentNestedRule)
					context.CurrentNestedRule = nil
					break
				}
			}

			if context.NowRuleType == MEDIA_RULE || context.NowRuleType == KEYFRAMES_RULE || context.NowRuleType == WEBKIT_KEYFRAMES_RULE {
				context.CurrentNestedRule = NewRule(context.NowRuleType)
				sel := append([]*scanner.Token{token}, parseSelector(s)...)
				context.CurrentNestedRule.Style.Selector = &CSSValue{Tokens: sel}
				context.resetContextStyleRule()
				break
			} else {
				context.NowSelector = append(context.NowSelector, token)
				parseRule(context, s, css)
				break
			}
		}
	}
	return css
}
<commit_msg>don't use fmt<commit_after>package css

import (
	"log"

	"github.com/gorilla/css/scanner"
)

/*
	stylesheet  : [ CDO | CDC | S | statement ]*;
	statement   : ruleset | at-rule;
	at-rule     : ATKEYWORD S* any* [ block | ';' S* ];
	block       : '{' S* [ any | block | ATKEYWORD S* | ';' S* ]* '}' S*;
	ruleset     : selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
	selector    : any+;
	declaration : property S* ':' S* value;
	property    : IDENT;
	value       : [ any | block | ATKEYWORD S* ]+;
	any         : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
	              | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
	              | DASHMATCH | ':' | FUNCTION S* [any|unused]* ')'
	              | '(' S* [any|unused]* ')' | '[' S* [any|unused]* ']'
	              ] S*;
	unused      : block | ATKEYWORD S* | ';' S* | CDO S* | CDC S*;
*/

type State int

const (
	STATE_NONE State = iota
	STATE_SELECTOR
	STATE_PROPERTY
	STATE_VALUE
)

type parserContext struct {
	State             State
	NowSelector       []*scanner.Token
	NowRuleType       RuleType
	CurrentNestedRule *CSSRule
}

func (context *parserContext) resetContextStyleRule() {
	context.NowSelector = make([]*scanner.Token, 0)
	context.NowRuleType = STYLE_RULE
	context.State = STATE_NONE
}

func parseRule(context *parserContext, s *scanner.Scanner, css *CSSStyleSheet) {
	rule := NewRule(context.NowRuleType)
	selector := append(context.NowSelector, parseSelector(s)...)
	rule.Style.Selector = &CSSValue{Tokens: selector}
	rule.Style.Styles = parseBlock(s)
	if context.CurrentNestedRule != nil {
		context.CurrentNestedRule.Rules = append(context.CurrentNestedRule.Rules, rule)
	} else {
		css.CssRuleList = append(css.CssRuleList, rule)
	}
	context.resetContextStyleRule()
}

// Parse takes a string of valid css rules, stylesheet,
// and parses it. Be aware this function has poor error handling
// so you should have valid syntax in your css
func Parse(csstext string) *CSSStyleSheet {
	context := &parserContext{
		State:             STATE_NONE,
		NowSelector:       make([]*scanner.Token, 0),
		NowRuleType:       STYLE_RULE,
		CurrentNestedRule: nil,
	}

	css := &CSSStyleSheet{}
	css.CssRuleList = make([]*CSSRule, 0)
	s := scanner.New(csstext)

	for {
		token := s.Next()

		if token.Type == scanner.TokenEOF || token.Type == scanner.TokenError {
			break
		}

		switch token.Type {
		case scanner.TokenCDO:
			break
		case scanner.TokenCDC:
			break
		case scanner.TokenComment:
			break
		case scanner.TokenS:
			break
		case scanner.TokenAtKeyword:
			switch token.Value {
			case "@media":
				context.NowRuleType = MEDIA_RULE
			case "@font-face":
				// Parse as normal rule, would be nice to parse according to syntax
				// https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face
				context.NowRuleType = FONT_FACE_RULE
				parseRule(context, s, css)
			case "@import":
				// No validation
				// https://developer.mozilla.org/en-US/docs/Web/CSS/@import
				rule := parseAtNoBody(s, IMPORT_RULE)
				if rule != nil {
					css.CssRuleList = append(css.CssRuleList, rule)
				}
				context.resetContextStyleRule()
			case "@charset":
				// No validation
				// https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
				rule := parseAtNoBody(s, CHARSET_RULE)
				if rule != nil {
					css.CssRuleList = append(css.CssRuleList, rule)
				}
				context.resetContextStyleRule()

			case "@page":
				context.NowRuleType = PAGE_RULE
				parseRule(context, s, css)
			case "@keyframes":
				context.NowRuleType = KEYFRAMES_RULE
			case "@-webkit-keyframes":
				context.NowRuleType = WEBKIT_KEYFRAMES_RULE
			case "@counter-style":
				context.NowRuleType = COUNTER_STYLE_RULE
				parseRule(context, s, css)
			default:
				log.Printf("Skip unsupported atrule: %s", token.Value)
				skipRules(s)
				context.resetContextStyleRule()
			}
		default:
			if context.State == STATE_NONE {
				if token.Value == "}" && context.CurrentNestedRule != nil {
					// close media/keyframe/… rule
					css.CssRuleList = append(css.CssRuleList, context.CurrentNestedRule)
					context.CurrentNestedRule = nil
					break
				}
			}

			if context.NowRuleType == MEDIA_RULE || context.NowRuleType == KEYFRAMES_RULE || context.NowRuleType == WEBKIT_KEYFRAMES_RULE {
				context.CurrentNestedRule = NewRule(context.NowRuleType)
				sel := append([]*scanner.Token{token}, parseSelector(s)...)
				context.CurrentNestedRule.Style.Selector = &CSSValue{Tokens: sel}
				context.resetContextStyleRule()
				break
			} else {
				context.NowSelector = append(context.NowSelector, token)
				parseRule(context, s, css)
				break
			}
		}
	}
	return css
}
<|endoftext|>


<commit_before>// Copyright 2016 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tcp_test

import (
	"math/rand"
	"net"
	"os"
	"runtime"
	"testing"

	"github.com/mikioh/tcp"
)

func TestOptionWithVariousBufferLenghts(t *testing.T) {
	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()
	c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tc, err := tcp.NewConn(c)
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < 256; i++ {
		level, name := rand.Int(), rand.Int()
		b := make([]byte, i)
		tc.Option(level, name, b)
	}
}

func TestOriginalDst(t *testing.T) {
	switch runtime.GOOS {
	case "linux":
	case "freebsd":
		if os.Getuid() != 0 {
			t.Skip("must be root")
		}
	default:
		t.Skipf("not supported on %s", runtime.GOOS)
	}

	for _, address := range []string{"127.0.0.1:0", "[::1]:0"} {
		ln, err := net.Listen("tcp", address)
		if err != nil {
			t.Fatal(err)
		}
		defer ln.Close()
		c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()

		tc, err := tcp.NewConn(c)
		if err != nil {
			t.Fatal(err)
		}
		if _, err := tc.OriginalDst(); err != nil {
			t.Fatal(err)
		}
	}
}
<commit_msg>tcp: fix build<commit_after>// Copyright 2016 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tcp_test

import (
	"math/rand"
	"net"
	"os"
	"runtime"
	"testing"

	"github.com/mikioh/tcp"
)

func TestOptionWithVariousBufferLenghts(t *testing.T) {
	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer ln.Close()
	c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tc, err := tcp.NewConn(c)
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < 256; i++ {
		level, name := rand.Int(), rand.Int()
		b := make([]byte, i)
		tc.Option(level, name, b)
	}
}

func TestOriginalDst(t *testing.T) {
	switch runtime.GOOS {
	case "linux":
	case "freebsd":
		if os.Getuid() != 0 {
			t.Skip("must be root")
		}
	default:
		t.Skipf("not supported on %s", runtime.GOOS)
	}

	for _, address := range []string{"127.0.0.1:0"} {
		ln, err := net.Listen("tcp", address)
		if err != nil {
			t.Fatal(err)
		}
		defer ln.Close()
		c, err := net.Dial(ln.Addr().Network(), ln.Addr().String())
		if err != nil {
			t.Fatal(err)
		}
		defer c.Close()

		tc, err := tcp.NewConn(c)
		if err != nil {
			t.Fatal(err)
		}
		if _, err := tc.OriginalDst(); err != nil {
			t.Fatal(err)
		}
	}
}
<|endoftext|>


<commit_before>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/chttp"
	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
	"golang.org/x/net/context"
)

// Whether NewPage and MustNewPage should reload the provided template.
// Reloading templates on each request is useful to see changes without
// recompiling. In production, reloading should be disabled.
var ReloadTemplates = false

// Path to template that is used as root template when
// Page.Serve[Empty|NotFound|Unauthorized|WithError] is called.
var RootTemplatePath = "./templates/index.html"

// Templates that are used as content template when Page.ServeEmpty or
// Page.ServeNotFound is called.
var (
	TemplateEmpty    = MustNewTemplate("", nil)
	TemplateNotFound = MustNewTemplate("./templates/404-not-found.html", nil)
)

// Template that is used as content template when Page.Error is called.
var TemplateError = MustNewTemplateWithRoot("./templates/error.html", "./templates/500-internal-server-error.html", nil)

// SignInUrl is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInUrl.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInUrl = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	Breadcrumbs []*Breadcrumb

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	responseWriter http.ResponseWriter

	Session *sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string
}

func NewPage(ctx context.Context, tpl *Template) (*Page, error) {
	responseWriter, request, ok := chttp.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: http.ResponseWriter and http.Request are not provided by ctx.")
	}

	language, ok := languages.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: languages.Language is not provided by ctx.")
	}

	session, ok := sessions.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: sessions.Session is not provided by ctx.")
	}

	form, err := forms.New(ctx)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Form:           form,
		Language:       language,
		request:        request,
		responseWriter: responseWriter,
		Session:        session,
		Template:       tpl,
	}

	return page, nil
}

// MustNewPage calls NewPage and panics on error.
func MustNewPage(ctx context.Context, tpl *Template) *Page {
	page, err := NewPage(ctx, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

func (p *Page) AddBreadcrumb(title string, url *url.URL) *Breadcrumb {
	breadcrumb := &Breadcrumb{
		Title: title,
		Url:   url,
	}

	p.Breadcrumbs = append(p.Breadcrumbs, breadcrumb)
	return breadcrumb
}

func (p *Page) Redirect(urlStr string, code int) {
	http.Redirect(p.responseWriter, p.request, urlStr, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInUrl.
// If SignInUrl.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInUrl.Scheme,
		Opaque:   SignInUrl.Opaque,
		User:     SignInUrl.User,
		Host:     SignInUrl.Host,
		Path:     fmt.Sprintf(SignInUrl.Path, p.Language.Code()),
		Fragment: SignInUrl.Fragment,
	}

	if SignInUrl.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: TemplateError is nil.")
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	if err := TemplateError.template.ExecuteTemplate(buffer, path.Base(TemplateError.rootTemplatePath), p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: p.Template is nil."))
		return
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	if err := p.Template.template.ExecuteTemplate(buffer, path.Base(p.Template.rootTemplatePath), p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	p.responseWriter.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_page_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.AddFlashError(p.T("err_unauthorized_access"))
	p.responseWriter.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.AddFlashError(p.T("err_internal_server_error"))
	p.Serve()
}

// T returns the translation associated with translationId. If p.Language
// is nil, translationId is returned.
func (p *Page) T(translationId string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationId
	}
	return p.Language.T(translationId, templateData...)
}

func Error(ctx context.Context, err error) {
	page := MustNewPage(ctx, TemplateError)
	page.Error(err)
}
<commit_msg>Added path for empty template.<commit_after>// Package pages provides a data structure for a web pages.
package pages

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"path"

	"github.com/ChristianSiegert/go-packages/chttp"
	"github.com/ChristianSiegert/go-packages/forms"
	"github.com/ChristianSiegert/go-packages/html"
	"github.com/ChristianSiegert/go-packages/i18n/languages"
	"github.com/ChristianSiegert/go-packages/sessions"
	"golang.org/x/net/context"
)

// Whether NewPage and MustNewPage should reload the provided template.
// Reloading templates on each request is useful to see changes without
// recompiling. In production, reloading should be disabled.
var ReloadTemplates = false

// Path to template that is used as root template when
// Page.Serve[Empty|NotFound|Unauthorized|WithError] is called.
var RootTemplatePath = "./templates/index.html"

// Templates that are used as content template when Page.ServeEmpty or
// Page.ServeNotFound is called.
var (
	TemplateEmpty    = MustNewTemplate("./templates/empty.html", nil)
	TemplateNotFound = MustNewTemplate("./templates/404-not-found.html", nil)
)

// Template that is used as content template when Page.Error is called.
var TemplateError = MustNewTemplateWithRoot("./templates/error.html", "./templates/500-internal-server-error.html", nil)

// SignInUrl is the URL to the page that users are redirected to when
// Page.RequireSignIn is called. If a %s placeholder is present in
// SignInUrl.Path, it is replaced by the page’s language code. E.g.
// “/%s/sign-in” becomes “/en/sign-in” if the page’s language code is “en”.
var SignInUrl = &url.URL{
	Path: "/%s/sign-in",
}

// Page represents a web page.
type Page struct {
	Breadcrumbs []*Breadcrumb

	Data map[string]interface{}

	// Form is an instance of *forms.Form bound to the request.
	Form *forms.Form

	Language *languages.Language

	// Name of the page. Useful in the root template, e.g. to style the
	// navigation link of the current page.
	Name string

	request *http.Request

	responseWriter http.ResponseWriter

	Session *sessions.Session

	Template *Template

	// Title of the page that templates can use to populate the HTML <title>
	// element.
	Title string
}

func NewPage(ctx context.Context, tpl *Template) (*Page, error) {
	responseWriter, request, ok := chttp.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: http.ResponseWriter and http.Request are not provided by ctx.")
	}

	language, ok := languages.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: languages.Language is not provided by ctx.")
	}

	session, ok := sessions.FromContext(ctx)
	if !ok {
		return nil, errors.New("pages.NewPage: sessions.Session is not provided by ctx.")
	}

	form, err := forms.New(ctx)
	if err != nil {
		return nil, err
	}

	page := &Page{
		Form:           form,
		Language:       language,
		request:        request,
		responseWriter: responseWriter,
		Session:        session,
		Template:       tpl,
	}

	return page, nil
}

// MustNewPage calls NewPage and panics on error.
func MustNewPage(ctx context.Context, tpl *Template) *Page {
	page, err := NewPage(ctx, tpl)
	if err != nil {
		panic("pages.MustNewPage: " + err.Error())
	}
	return page
}

func (p *Page) AddBreadcrumb(title string, url *url.URL) *Breadcrumb {
	breadcrumb := &Breadcrumb{
		Title: title,
		Url:   url,
	}

	p.Breadcrumbs = append(p.Breadcrumbs, breadcrumb)
	return breadcrumb
}

func (p *Page) Redirect(urlStr string, code int) {
	http.Redirect(p.responseWriter, p.request, urlStr, code)
}

// RequireSignIn redirects users to the sign-in page specified by SignInUrl.
// If SignInUrl.RawQuery is empty, the query parameters “r” (referrer) and “t”
// (title of the referrer page) are appended. This allows the sign-in page to
// display a message that page <title> is access restricted, and after
// successful authentication, users can be redirected to <referrer>, the page
// they came from.
func (p *Page) RequireSignIn(pageTitle string) {
	u := &url.URL{
		Scheme:   SignInUrl.Scheme,
		Opaque:   SignInUrl.Opaque,
		User:     SignInUrl.User,
		Host:     SignInUrl.Host,
		Path:     fmt.Sprintf(SignInUrl.Path, p.Language.Code()),
		Fragment: SignInUrl.Fragment,
	}

	if SignInUrl.RawQuery == "" {
		query := &url.Values{}
		query.Add("r", p.request.URL.Path)
		query.Add("t", base64.URLEncoding.EncodeToString([]byte(pageTitle))) // TODO: Sign or encrypt parameter to prevent tempering by users
		u.RawQuery = query.Encode()
	}

	p.Redirect(u.String(), http.StatusSeeOther)
}

// Error serves an error page with a generic error message. Err is not displayed
// to the user but written to the error log.
func (p *Page) Error(err error) {
	log.Println(err.Error())

	if TemplateError == nil {
		log.Println("pages.Page.Error: TemplateError is nil.")
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	buffer := bytes.NewBuffer([]byte{})

	p.Data = map[string]interface{}{
		"Error":          err,
		"IsDevAppServer": true,
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	if err := TemplateError.template.ExecuteTemplate(buffer, path.Base(TemplateError.rootTemplatePath), p); err != nil {
		log.Printf("pages.Page.Error: Executing template failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		log.Printf("pages.Page.Error: Writing template to buffer failed: %s\n", err)
		http.Error(p.responseWriter, "Internal Server Error", http.StatusInternalServerError)
	}
}

// Serve serves the root template specified by RootTemplatePath with the content
// template specified by p.Template. HTML comments and whitespace are stripped.
// If p.Template is nil, an empty content template is embedded.
func (p *Page) Serve() {
	buffer := bytes.NewBuffer([]byte{})

	if p.Template == nil {
		p.Template = TemplateEmpty
	}

	// If still nil
	if p.Template == nil {
		p.Error(errors.New("pages.Page.Serve: p.Template is nil."))
		return
	}

	if ReloadTemplates {
		if err := p.Template.Reload(); err != nil {
			p.Error(err)
		}
	}

	if err := p.Template.template.ExecuteTemplate(buffer, path.Base(p.Template.rootTemplatePath), p); err != nil {
		p.Error(err)
		return
	}

	b := html.RemoveWhitespace(buffer.Bytes())

	if _, err := bytes.NewBuffer(b).WriteTo(p.responseWriter); err != nil {
		p.Error(err)
	}
}

// ServeEmpty serves the root template without content template.
func (p *Page) ServeEmpty() {
	p.Template = TemplateEmpty
	p.Serve()
}

// ServeNotFound serves a page that tells the user the requested page does not
// exist.
func (p *Page) ServeNotFound() {
	p.responseWriter.WriteHeader(http.StatusNotFound)
	p.Template = TemplateNotFound
	p.Title = p.T("err_page_not_found")
	p.Serve()
}

// ServeUnauthorized serves a page that tells the user the requested page cannot
// be accessed due to insufficient access rights.
func (p *Page) ServeUnauthorized() {
	p.Session.AddFlashError(p.T("err_unauthorized_access"))
	p.responseWriter.WriteHeader(http.StatusUnauthorized)
	p.ServeEmpty()
}

// ServeWithError is similar to Serve, but additionally an error flash message
// is displayed to the user saying that an internal problem occurred. Err is not
// displayed but written to the error log. This method is useful if the user
// should be informed of a problem while the state, e.g. a filled in form, is
// preserved.
func (p *Page) ServeWithError(err error) {
	log.Println(err.Error())
	p.Session.AddFlashError(p.T("err_internal_server_error"))
	p.Serve()
}

// T returns the translation associated with translationId. If p.Language
// is nil, translationId is returned.
func (p *Page) T(translationId string, templateData ...map[string]interface{}) string {
	if p.Language == nil {
		return translationId
	}
	return p.Language.T(translationId, templateData...)
}

func Error(ctx context.Context, err error) {
	page := MustNewPage(ctx, TemplateError)
	page.Error(err)
}
<|endoftext|>


<commit_before>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	"errors"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type PanicsTest struct {
	matcherCalled bool
	suppliedCandidate interface{}
	wrappedResult MatchResult
	wrappedError error

	matcher Matcher
}

func init() { RegisterTestSuite(&PanicsTest{}) }

func (t *PanicsTest) SetUp() {
	wrapped := &fakeMatcher{
		func(c interface{}) (MatchResult, error) {
			t.matcherCalled = true
			t.suppliedCandidate = c
			return t.wrappedResult, t.wrappedError
		},
		"foo",
	}

	t.matcher = Panics(wrapped)
}

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *PanicsTest) Description() {
	ExpectThat(t.matcher.Description(), Equals("panics with: foo"))
}

func (t *PanicsTest) CandidateIsNil() {
	res, err := t.matcher.Matches(nil)

	ExpectThat(res, Equals(MATCH_UNDEFINED))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
}

func (t *PanicsTest) CandidateIsString() {
	res, err := t.matcher.Matches("taco")

	ExpectThat(res, Equals(MATCH_UNDEFINED))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
}

func (t *PanicsTest) CandidateTakesArgs() {
	res, err := t.matcher.Matches(func(i int) string { return "" })

	ExpectThat(res, Equals(MATCH_UNDEFINED))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
}

func (t *PanicsTest) CallsFunction() {
	callCount := 0
	t.matcher.Matches(func(i int) string {
		callCount++
		return ""
	})

	ExpectThat(callCount, Equals(1))
}

func (t *PanicsTest) FunctionDoesntPanic() {
	res, err := t.matcher.Matches(func() {})

	ExpectThat(res, Equals(MATCH_FALSE))
	ExpectThat(err, Error(Equals("which didn't panic")))
}

func (t *PanicsTest) CallsWrappedMatcher() {
	expectedErr := 17
	t.matcher.Matches(func() { panic(expectedErr) })

	ExpectThat(t.suppliedCandidate, Equals(expectedErr))
}

func (t *PanicsTest) ReturnsWrappedMatcherResult() {
	t.wrappedResult = MatchResult(17)
	t.wrappedError = errors.New("taco")

	res, err := t.matcher.Matches(func() { panic(nil) })

	ExpectThat(res, Equals(t.wrappedResult))
	ExpectThat(err, Equals(t.wrappedError))
}
<commit_msg>Revised Panics tests, for #7.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 oglematchers_test

import (
	"errors"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////

type PanicsTest struct {
	matcherCalled bool
	suppliedCandidate interface{}
	wrappedResult MatchResult
	wrappedError error

	matcher Matcher
}

func init() { RegisterTestSuite(&PanicsTest{}) }

func (t *PanicsTest) SetUp() {
	wrapped := &fakeMatcher{
		func(c interface{}) (MatchResult, error) {
			t.matcherCalled = true
			t.suppliedCandidate = c
			return t.wrappedResult, t.wrappedError
		},
		"foo",
	}

	t.matcher = Panics(wrapped)
}

////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////

func (t *PanicsTest) Description() {
	ExpectThat(t.matcher.Description(), Equals("panics with: foo"))
}

func (t *PanicsTest) CandidateIsNil() {
	res, err := t.matcher.Matches(nil)

	ExpectThat(res, Equals(MATCH_UNDEFINED))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
}

func (t *PanicsTest) CandidateIsString() {
	res, err := t.matcher.Matches("taco")

	ExpectThat(res, Equals(MATCH_UNDEFINED))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
}

func (t *PanicsTest) CandidateTakesArgs() {
	res, err := t.matcher.Matches(func(i int) string { return "" })

	ExpectThat(res, Equals(MATCH_UNDEFINED))
	ExpectThat(err, Error(Equals("which is not a zero-arg function")))
}

func (t *PanicsTest) CallsFunction() {
	callCount := 0
	t.matcher.Matches(func(i int) string {
		callCount++
		return ""
	})

	ExpectThat(callCount, Equals(1))
}

func (t *PanicsTest) FunctionDoesntPanic() {
	res, err := t.matcher.Matches(func() {})

	ExpectThat(res, Equals(MATCH_FALSE))
	ExpectThat(err, Error(Equals("which didn't panic")))
}

func (t *PanicsTest) CallsWrappedMatcher() {
	expectedErr := 17
	t.matcher.Matches(func() { panic(expectedErr) })

	ExpectThat(t.suppliedCandidate, Equals(expectedErr))
}

func (t *PanicsTest) ReturnsWrappedMatcherResult() {
	t.wrappedResult = MatchResult(17)
	res, _ := t.matcher.Matches(func() { panic(nil) })

	ExpectThat(res, Equals(t.wrappedResult))
}

func (t *PanicsTest) WrappedReturnsUndefinedWithoutError() {
	t.wrappedResult = MATCH_UNDEFINED
	t.wrappedError = nil
	_, err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17")))
}

func (t *PanicsTest) WrappedReturnsUndefinedWithError() {
	t.wrappedResult = MATCH_UNDEFINED
	t.wrappedError = "which blah"
	_, err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17, which blah")))
}

func (t *PanicsTest) WrappedReturnsFalseWithoutError() {
	t.wrappedResult = MATCH_FALSE
	t.wrappedError = nil
	_, err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17")))
}

func (t *PanicsTest) WrappedReturnsFalseWithError() {
	t.wrappedResult = MATCH_FALSE
	t.wrappedError = "which blah"
	_, err := t.matcher.Matches(func() { panic(17) })

	ExpectThat(err, Error(Equals("which panicked with: 17, which blah")))
}
<|endoftext|>


<commit_before>package template

var internal_build = `# {{.Update}}
set -eu
# detect os
if [ "$(uname -sm)" = "Linux x86_64" ]
then
  GO_BUILD="go build -v"
  GO_ARTIFACT="{{.Project.Project_name}}"
else
  GO_BUILD="gox -os Linux -arch amd64"
  GO_ARTIFACT="{{.Project.Project_name}}_linux_amd64"
fi
# oas build context
OAS_CURRENT_TAG="$(git for-each-ref --sort=taggerdate --format '%(refname:short)' refs/tags | tail -n1)"
IFS="." read -r OAS_VERSION_MAJOR OAS_VERSION_MINOR OAS_VERSION_PATCH _JUNK <<< "${OAS_CURRENT_TAG}"
OAS_VERSION_MAJOR="${OAS_VERSION_MAJOR/v/}"
OAS_VERSION_MAJOR="${OAS_VERSION_MAJOR:-0}"
OAS_VERSION_MINOR="${OAS_VERSION_MINOR:-0}"
OAS_VERSION_PATCH="${OAS_VERSION_PATCH:-0}"
if [ "${DRONE:-false}" = "true" ]
then
  OAS_VERSION_META="drone.${DRONE_BUILD_NUMBER:-missing_drone_build_number.$(date +%s)}"
elif [ "${TRAVIS:-false}" = "true" ]
then
  OAS_VERSION_META="travis.${TRAVIS_BUILD_NUMBER:-missing_travis_build_number.$(date +%s)}"
else
  OAS_VERSION_META="local.$(date +%s)"
fi
OAS_VERSION="${OAS_VERSION_MAJOR}.${OAS_VERSION_MINOR}.${OAS_VERSION_PATCH}-${OAS_VERSION_META}"
OAS_NAME="{{.Project.Project_name}}"

export OAS_VERSION
export OAS_NAME
export GO_BUILD
export GO_ARTIFACT

rm -rvf target-root
mkdir -pv root
cp -rv root target-root

source scripts/build

# build the package
rm -rvf target
mkdir -p target
if ! which fpm > /dev/null 2>&1
then
  echo fpm no encontrado, tratando de instalar
  gem install fpm
fi

if fpm --help > /dev/null
then
  set -x
  fpm --description '{{.Project.Project_description}}' --package target -C target-root -s dir -t rpm --name "{{.Project.Project_name}}" {{range $key, $value := .Project.Package_dependencies}}{{if eq $key "os"}}{{range $value}}-d {{.}} {{end}}{{end}}{{end}}--version "${OAS_VERSION}" --before-install scripts/before-install --after-install scripts/after-install --before-remove scripts/before-remove --after-remove scripts/after-remove --before-upgrade scripts/before-upgrade --after-upgrade scripts/after-upgrade --rpm-os linux {{if .Project.Sign_package}}--rpm-sign{{end}} .
else
  echo no se encontró fpm
  exit 1
fi
`
<commit_msg>mas precision para encontrar la versión taggeada<commit_after>package template

var internal_build = `# {{.Update}}
set -eu
# detect os
if [ "$(uname -sm)" = "Linux x86_64" ]
then
  GO_BUILD="go build -v"
  GO_ARTIFACT="{{.Project.Project_name}}"
else
  GO_BUILD="gox -os Linux -arch amd64"
  GO_ARTIFACT="{{.Project.Project_name}}_linux_amd64"
fi
# oas build context
OAS_TAG_META="${DRONE_COMMIT:-${TRAVIS_COMMIT:-}}"
OAS_TAG_META="${OAS_TAG_META:-$(git rev-parse HEAD)}"
OAS_CURRENT_TAG="$(git describe --tags --exact-match $OAS_TAG_META|tail -n1)"
IFS="." read -r OAS_VERSION_MAJOR OAS_VERSION_MINOR OAS_VERSION_PATCH _JUNK <<< "${OAS_CURRENT_TAG}"
OAS_VERSION_MAJOR="${OAS_VERSION_MAJOR/v/}"
OAS_VERSION_MAJOR="${OAS_VERSION_MAJOR:-0}"
OAS_VERSION_MINOR="${OAS_VERSION_MINOR:-0}"
OAS_VERSION_PATCH="${OAS_VERSION_PATCH:-0}"
if [ "${DRONE:-false}" = "true" ]
then
  OAS_VERSION_META="drone.${DRONE_BUILD_NUMBER:-missing_drone_build_number.$(date +%s)}"
elif [ "${TRAVIS:-false}" = "true" ]
then
  OAS_VERSION_META="travis.${TRAVIS_BUILD_NUMBER:-missing_travis_build_number.$(date +%s)}"
else
  OAS_VERSION_META="local.$(date +%s)"
fi
OAS_VERSION="${OAS_VERSION_MAJOR}.${OAS_VERSION_MINOR}.${OAS_VERSION_PATCH}-${OAS_VERSION_META}"
OAS_NAME="{{.Project.Project_name}}"

export OAS_VERSION
export OAS_NAME
export GO_BUILD
export GO_ARTIFACT

rm -rvf target-root
mkdir -pv root
cp -rv root target-root

source scripts/build

# build the package
rm -rvf target
mkdir -p target
if ! which fpm > /dev/null 2>&1
then
  echo fpm no encontrado, tratando de instalar
  gem install fpm
fi

if fpm --help > /dev/null
then
  set -x
  fpm --description '{{.Project.Project_description}}' --package target -C target-root -s dir -t rpm --name "{{.Project.Project_name}}" {{range $key, $value := .Project.Package_dependencies}}{{if eq $key "os"}}{{range $value}}-d {{.}} {{end}}{{end}}{{end}}--version "${OAS_VERSION}" --before-install scripts/before-install --after-install scripts/after-install --before-remove scripts/before-remove --after-remove scripts/after-remove --before-upgrade scripts/before-upgrade --after-upgrade scripts/after-upgrade --rpm-os linux {{if .Project.Sign_package}}--rpm-sign{{end}} .
else
  echo no se encontró fpm
  exit 1
fi
`
<|endoftext|>


<commit_before>// Package skiplist implements an indexable ordered multimap.
//
// This skip list implementation is distinguished by supporting index
// addressing, allowing multiple values per key, automatically
// adjusting its depth, and mimicing Go's container/list interface
// where possible.
//
// Insert, Remove, and Find operations all require O(log(N)) time or less.
// The skiplist requires O(N) space.
//
// To efficiently iterate over the list (where s is a *Skiplist):
//   for e := s.Front(); e != nil; e = e.Next() {
//  	// do something with e.Value and/or e.Key()
//   }
// Pop the first element in the list with s.RemoveN(0).  Pop the last
// with s.RemoveN(s.Len()-1).
//
package skiplist

import (
	"fmt"
	"math/rand"
)

// A Skiplist is linked at multiple levels.  The bottom level (L0) is
// a sorted linked list of entries, and each link has a link at the
// next higher level added with probability P at insertion.  Since
// this is a position-addressable skip-list, each link has an
// associated 'width' specifying the number of nodes it skips, so
// nodes can also be referenced by position.
//
// For example, a 64-entry skip list with values from 0x00 to
// 0x3f might look like this:
//   L5 --------------------------------------------------------------->/
//   L4 ---------------------------------->->-------------------------->/
//   L3 ------------------->>-->-------->->->-------------------------->/
//   L2 -->------------>->->>-->-------->->->-->--->->---------->------>/
//   L1 >->->-->-->-->>>->->>>->-------->->->-->->->->-->--->--->------>/
//   L0 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/
//      0000000000000000111111111111111122222222222222223333333333333333
//      0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

type Skiplist struct {
	cnt   int
	less  func(a, b interface{}) bool
	links []link
	prev  []struct{		// Scratch structure
		link *link
		pos int
	}
	rng   *rand.Rand
}
type link struct {
	to    *Element
	width int
}

// Element is an key/value pair inserted into the list.  Use
// element.Key() to access the protected key.
//
type Element struct {
	links []link
	key   interface{} // private to protect order
	Value interface{}
}

// Key returns the key used to insert the value in the list element.
//
func (e *Element) Key() interface{} { return e.key }

// Next returns the next-greater list element or nil.
//
func (e *Element) Next() *Element { return e.links[0].to }

// String returns a Key:Value string representation.
//
func (e *Element) String() string { return fmt.Sprintf("%v:%v", e.Key(), e.Value) }

// New returns a new skiplist in O(1) time.
// Function less must return true iff key a is less than key b.
// The list will be sorted from least to greatest.
// R is the random number generator to use or nil.
//
func New(less func(key1, key2 interface{}) bool, r *rand.Rand) *Skiplist {
	if r == nil {
		r = rand.New(rand.NewSource(42))
	}
	return &Skiplist{0, less, []link{}, []struct{link *link;pos int}{}, r}
}

// Return the first list element in O(1) time.
//
func (s *Skiplist) Front() *Element {
	if len(s.links) == 0 {
		return nil
	}
	return s.links[0].to
}

// Insert a {key,value} pair into the skip list in O(log(N)) time.
//
func (l *Skiplist) Insert(key interface{}, value interface{}) *Skiplist {
	l.grow()
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	pos := 0
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && l.less(ll.to.key, key) {
			pos += ll.width
			links = ll.to.links
			ll = &links[level]
		}
		// Increment the width of the
		ll.width += 1
		// Record the predecessor at this level and its position.
		prev[level].pos = pos
		prev[level].link = ll
	}
	// Set pos to the position of the new element.
	pos++
	// At the bottom level, simply link in the element
	nu := &Element{make([]link,1,2), key, value}
	nu.links[0] = link{prev[0].link.to, 1}
	prev[0].link.to = nu
	prev[0].link.width = 1
	// Link in the element at a random number of higher levels.
	for level:=1; level<levels && l.rng.Intn(2) < 1; level++ {
		end := prev[level].pos + prev[level].link.width
		nu.links = append(nu.links, link{prev[level].link.to, end - pos})
		prev[level].link.to = nu
		prev[level].link.width = pos - prev[level].pos
	}
	return l
}

// Remove the youngest Element associate with Key, if any, in O(log(N)) time.
// Return the removed element or nil.
//
func (l *Skiplist) Remove(key interface{}) *Element {
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && l.less(ll.to.key, key) {
			links = ll.to.links
			ll = &links[level]
		}
		// Record the predecessor at this level and its position.
		prev[level].link = ll
	}
	// Verify there is a matching entry to remove.
	elem := prev[0].link.to
	if elem == nil || l.less(key, elem.key) {
		return nil
	}
	// At the bottom level, simply unlink the element.
	prev[0].link.to = elem.links[0].to
	// Unlink any higher linked levels.
	level := 1
	for ; level<levels && prev[level].link.to == elem; level++ {
		prev[level].link.to = elem.links[level].to
		prev[level].link.width += elem.links[level].width
	}
	// Adjust widths at higher levels
	for ; level < levels; level++ {
		prev[level].link.width -= 1
	}
	l.shrink()
	return elem
}

// RemoveN removes any element at position pos in O(log(N)) time,
// returning it or nil.
//
func (l *Skiplist) RemoveN(index int) *Element {
	if index >= l.cnt {
		return nil
	}
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	pos := -1
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && pos + ll.width < index {
			pos += ll.width
			links = ll.to.links
			ll = &links[level]
		}
		// Record the predecessor at this level and its position.
		prev[level].pos = pos
		prev[level].link = ll
	}
	// Set pos to the position of the new element.
	pos++
	// Verify there is a matching entry to remove.
	elem := prev[0].link.to
	// At the bottom level, simply unlink the element.
	prev[0].link.to = elem.links[0].to
	// Unlink any higher linked levels.
	level := 1
	for ; level<levels && prev[level].link.to == elem; level++ {
		prev[level].link.to = elem.links[level].to
		prev[level].link.width += elem.links[level].width
	}
	// Adjust widths at higher levels
	for ; level < levels; level++ {
		prev[level].link.width -= 1
	}
	l.shrink()
	return elem
}

func removeN(links *[]link, level int, pos int) (removed *Element) {
	// Walk to the correct deletion location.
	for (*links)[level].width < pos {
		pos -= (*links)[level].width
		links = &(*links)[level].to.links
	}
	// For level 0, simply remove the found Element.
	if level == 0 {
		removed = (*links)[0].to
		(*links)[0].to = removed.links[0].to
		return removed
	}
	// For higher levels, recur.
	removed = removeN(links, level-1, pos)
	if removed == (*links)[level].to {
		// Unlink Element at this level.
		(*links)[level].to = removed.links[level].to
		(*links)[level].width += removed.links[level].width - 1
	} else {
		// Account for Element not linked at this level.
		(*links)[level].width -= 1
	}
	return removed
}

// Find returns the youngest element inserted with key in the
// skiplist, without modifying the list, in O(log(N)) time.
// If there is no match, nil is returned.
// It also returns the current position of the found element, or -1.
//
func (l *Skiplist) Find(key interface{}) (e *Element, pos int) {
	p := &l.links
	level := len(l.links) - 1
	for level >= 0 {
		for (*p)[level].to != nil && l.less((*p)[level].to.key, key) {
			pos += (*p)[level].width
			p = &(*p)[level].to.links
		}
		level--
	}
	if (*p)[0].to == nil || l.less(key, (*p)[0].to.key) {
		return nil, -1
	}
	return (*p)[0].to, pos
}

// Len returns the number of elements in the Skiplist.
//
func (l *Skiplist) Len() int {
	return l.cnt
}

// FindN returns the Element at position pos in the skiplist, in O(log(pos)) time.
// If no such entry exists, nil is returned.
//
func (l *Skiplist) FindN(pos int) *Element {
	if pos >= l.cnt {
		return nil
	}
	pos++
	p := &l.links
	levels := len(l.links)
	// Carefully the start-search level.  If we don't, the search
	// is technically O(log(l.cnt)) instead of O(log(pos)).
	level := 0
	for ; level < levels-1; level++ {
		if pos < 1<<uint(level) {
			break
		}
	}
	for level >= 0 {
		for (*p)[level].to != nil && (*p)[level].width < pos {
			pos -= (*p)[level].width
			p = &(*p)[level].to.links
		}
		level--
	}
	if (*p)[0].to == nil || pos < (*p)[0].width {
		return nil
	}
	return (*p)[0].to
}

// Function grow increments the list count and increment the number of
// levels on power-of-two counts.
//
func (l *Skiplist) grow() {
	l.cnt++
	if l.cnt&(l.cnt-1) == 0 {
		l.links = append(l.links, link{nil, l.cnt})
		l.prev = append(l.prev, struct{link *link;pos int}{})
	}
}

// Function shrink decrements the list count and decrement the number
// of levels on power-of-two counts.
//
func (l *Skiplist) shrink() {
	if l.cnt&(l.cnt-1) == 0 {
		l.links = l.links[:len(l.links)-1]
		l.prev = l.prev[:len(l.prev)-1]
	}
	l.cnt--
}

// Function String prints only the key/value pairs in the skip list.
//
func (l *Skiplist) String() string {
	s := append([]byte{}, "{"...)
	for n := l.links[0].to; n != nil; n = n.links[0].to {
		s = append(s, (n.String() + " ")...)
	}
	s[len(s)-1] = '}'
	return string(s)
}
<commit_msg>Remove dead code. Improve .Find*().<commit_after>// Package skiplist implements an indexable ordered multimap.
//
// This skip list implementation is distinguished by supporting index
// addressing, allowing multiple values per key, automatically
// adjusting its depth, and mimicing Go's container/list interface
// where possible.
//
// Insert, Remove, and Find operations all require O(log(N)) time or less.
// The skiplist requires O(N) space.
//
// To efficiently iterate over the list (where s is a *Skiplist):
//   for e := s.Front(); e != nil; e = e.Next() {
//  	// do something with e.Value and/or e.Key()
//   }
// Pop the first element in the list with s.RemoveN(0).  Pop the last
// with s.RemoveN(s.Len()-1).
//
package skiplist

import (
	"fmt"
	"math/rand"
)

// A Skiplist is linked at multiple levels.  The bottom level (L0) is
// a sorted linked list of entries, and each link has a link at the
// next higher level added with probability P at insertion.  Since
// this is a position-addressable skip-list, each link has an
// associated 'width' specifying the number of nodes it skips, so
// nodes can also be referenced by position.
//
// For example, here is a 24-entry skip list:
//   L4 |---------------------------------------------------------------------->/
//   L3 |------------------------------------------->|------------------------->/
//   L2 |---------->|---------->|---------->|------->|---------------->|---->|->/
//   L1 |---------->|---------->|---------->|->|---->|->|->|->|------->|->|->|->/
//   L0 |->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->|->/
//         0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  1  1  1
//         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0  1  2  3  4  5  6

type Skiplist struct {
	cnt   int
	less  func(a, b interface{}) bool
	links []link
	prev  []struct{		// Scratch structure
		link *link
		pos int
	}
	rng   *rand.Rand
}
type link struct {
	to    *Element
	width int
}

// Element is an key/value pair inserted into the list.  Use
// element.Key() to access the protected key.
//
type Element struct {
	links []link
	key   interface{} // private to protect order
	Value interface{}
}

// Key returns the key used to insert the value in the list element.
//
func (e *Element) Key() interface{} { return e.key }

// Next returns the next-greater list element or nil.
//
func (e *Element) Next() *Element { return e.links[0].to }

// String returns a Key:Value string representation.
//
func (e *Element) String() string { return fmt.Sprintf("%v:%v", e.Key(), e.Value) }

// New returns a new skiplist in O(1) time.
// Function less must return true iff key a is less than key b.
// The list will be sorted from least to greatest.
// R is the random number generator to use or nil.
//
func New(less func(key1, key2 interface{}) bool, r *rand.Rand) *Skiplist {
	if r == nil {
		r = rand.New(rand.NewSource(42))
	}
	return &Skiplist{0, less, []link{}, []struct{link *link;pos int}{}, r}
}

// Return the first list element in O(1) time.
//
func (s *Skiplist) Front() *Element {
	if len(s.links) == 0 {
		return nil
	}
	return s.links[0].to
}

// Insert a {key,value} pair into the skip list in O(log(N)) time.
//
func (l *Skiplist) Insert(key interface{}, value interface{}) *Skiplist {
	l.grow()
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	pos := 0
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && l.less(ll.to.key, key) {
			pos += ll.width
			links = ll.to.links
			ll = &links[level]
		}
		// Increment the width of the
		ll.width += 1
		// Record the predecessor at this level and its position.
		prev[level].pos = pos
		prev[level].link = ll
	}
	// Set pos to the position of the new element.
	pos++
	// At the bottom level, simply link in the element
	nu := &Element{make([]link,1,2), key, value}
	nu.links[0] = link{prev[0].link.to, 1}
	prev[0].link.to = nu
	prev[0].link.width = 1
	// Link in the element at a random number of higher levels.
	for level:=1; level<levels && l.rng.Intn(2) < 1; level++ {
		end := prev[level].pos + prev[level].link.width
		nu.links = append(nu.links, link{prev[level].link.to, end - pos})
		prev[level].link.to = nu
		prev[level].link.width = pos - prev[level].pos
	}
	return l
}

// Remove the youngest Element associate with Key, if any, in O(log(N)) time.
// Return the removed element or nil.
//
func (l *Skiplist) Remove(key interface{}) *Element {
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && l.less(ll.to.key, key) {
			links = ll.to.links
			ll = &links[level]
		}
		// Record the predecessor at this level and its position.
		prev[level].link = ll
	}
	// Verify there is a matching entry to remove.
	elem := prev[0].link.to
	if elem == nil || l.less(key, elem.key) {
		return nil
	}
	// At the bottom level, simply unlink the element.
	prev[0].link.to = elem.links[0].to
	// Unlink any higher linked levels.
	level := 1
	for ; level<levels && prev[level].link.to == elem; level++ {
		prev[level].link.to = elem.links[level].to
		prev[level].link.width += elem.links[level].width
	}
	// Adjust widths at higher levels
	for ; level < levels; level++ {
		prev[level].link.width -= 1
	}
	l.shrink()
	return elem
}

// RemoveN removes any element at position pos in O(log(N)) time,
// returning it or nil.
//
func (l *Skiplist) RemoveN(index int) *Element {
	if index >= l.cnt {
		return nil
	}
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	pos := -1
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && pos + ll.width < index {
			pos += ll.width
			links = ll.to.links
			ll = &links[level]
		}
		// Record the predecessor at this level and its position.
		prev[level].pos = pos
		prev[level].link = ll
	}
	// Set pos to the position of the new element.
	pos++
	// Verify there is a matching entry to remove.
	elem := prev[0].link.to
	// At the bottom level, simply unlink the element.
	prev[0].link.to = elem.links[0].to
	// Unlink any higher linked levels.
	level := 1
	for ; level<levels && prev[level].link.to == elem; level++ {
		prev[level].link.to = elem.links[level].to
		prev[level].link.width += elem.links[level].width
	}
	// Adjust widths at higher levels
	for ; level < levels; level++ {
		prev[level].link.width -= 1
	}
	l.shrink()
	return elem
}

// Find returns the youngest element inserted with key in the
// skiplist, without modifying the list, in O(log(N)) time.
// If there is no match, nil is returned.
// It also returns the current position of the found element, or -1.
//
func (l *Skiplist) Find(key interface{}) (e *Element, pos int) {
	levels := len(l.links)
	// Create scratch space to store predecessor information.
	prev := l.prev
	// Compute elements preceding the insertion location at each level.
	links := l.links
	for level := levels-1; level >= 0; level-- {
		ll := &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && l.less(ll.to.key, key) {
			pos += ll.width
			links = ll.to.links
			ll = &links[level]
		}
		// Record the predecessor at this level and its position.
		prev[level].pos = pos
		prev[level].link = ll
	}
	// Set pos to the position of the new element.
	elem := prev[0].link.to
	if elem == nil || l.less(key, elem.key) {
		return nil, -1
	}
	return elem, pos
}

// Len returns the number of elements in the Skiplist.
//
func (l *Skiplist) Len() int {
	return l.cnt
}

// FindN returns the Element at position pos in the skiplist, in O(log(index)) time.
// If no such entry exists, nil is returned.
//
func (l *Skiplist) FindN(index int) *Element {
	if index >= l.cnt {
		return nil
	}
	levels := len(l.links)
	// Compute elements preceding the insertion location at each level.
	pos := -1
	links := l.links
	var ll *link
	for level := levels-1; level >= 0; level-- {
		ll = &links[level]
		// Find predecessor link at this level.
		for ll.to != nil && pos + ll.width < index {
			pos += ll.width
			links = ll.to.links
			ll = &links[level]
		}
	}
	return ll.to
}

// Function grow increments the list count and increment the number of
// levels on power-of-two counts.
//
func (l *Skiplist) grow() {
	l.cnt++
	if l.cnt&(l.cnt-1) == 0 {
		l.links = append(l.links, link{nil, l.cnt})
		l.prev = append(l.prev, struct{link *link;pos int}{})
	}
}

// Function shrink decrements the list count and decrement the number
// of levels on power-of-two counts.
//
func (l *Skiplist) shrink() {
	if l.cnt&(l.cnt-1) == 0 {
		l.links = l.links[:len(l.links)-1]
		l.prev = l.prev[:len(l.prev)-1]
	}
	l.cnt--
}

// Function String prints only the key/value pairs in the skip list.
//
func (l *Skiplist) String() string {
	s := append([]byte{}, "{"...)
	for n := l.links[0].to; n != nil; n = n.links[0].to {
		s = append(s, (n.String() + " ")...)
	}
	s[len(s)-1] = '}'
	return string(s)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

//Structs used when parsing a song file
type Songbook struct {
	FixedOrder    bool
	UseSection    bool
	IndexChorus   bool
	IndexPosition int
	Filename      string
	Title         string
	Songs         map[int]Song
}

const (
	IndexNone  = 0
	IndexStart = 1
	IndexEnd   = 2
)

func ParseSongbookFile(filename string, songs_root string) (*Songbook, error) {
	file, err := os.Open(filename)

	filename = filepath.Base(filename)
	title := filename[0 : len(filename)-len(".songlist")]

	if err != nil {
		return nil, err
	}
	defer file.Close()

	var (
		scanner     = bufio.NewScanner(file)
		fixed_order = false
		use_section = false
		use_chorus  = false
		index_pos   = IndexNone
		songs       = make(map[int]Song)
	)

	//bad_command_regex := regexp.MustCompile("\\{|\\}")

	for scanner.Scan() {
		line := scanner.Text()

		//is this a command
		if strings.HasPrefix(line, "{") {
			command := strings.ToLower(line)
			if strings.HasPrefix(command, "{title:") {
				title = parseCommand(line)
				continue
			} else if strings.HasPrefix(command, "{fixed_order}") {
				fixed_order = true
				continue
			} else if strings.HasPrefix(command, "{index_use_sections}") {
				use_section = true
				continue
			} else if strings.HasPrefix(command, "{index_use_chorus}") {
				use_chorus = true
				continue
			} else if strings.HasPrefix(command, "{index_position:") {
				p := parseCommand(line)

				switch p {
				case "start":
					index_pos = IndexStart
					break
				case "end":
					index_pos = IndexEnd
					break
				case "none":
				default:
					index_pos = IndexNone
				}

				continue
			} else {
				fmt.Printf("Unknown tag: %s\n", line)
				continue
			}
		}

		//ignore blank lines
		if len(line) > 0 {
			num := -1
			//check for fixed numbering
			if strings.Index(line, ",") > 0 {
				num_str := line[0:strings.Index(line, ",")]
				num, err = strconv.Atoi(num_str)
				if err == nil {
					line = line[len(num_str)+1 : len(line)]
				} else {
					num = -1
				}
			}

			line = strings.TrimSpace(line)

			//including '.song' extension is optional
			if !strings.HasSuffix(line, ".song") {
				line += ".song"
			}

			song, err := ParseSongFile(songs_root+"/"+line, 0)

			if err != nil {
				fmt.Println(num, ":", err)
			} else {
				if num < 0 {
					num = len(songs) + 1
				}
				song.SongNumber = num
				songs[num] = *song
			}
		}
	}

	return &Songbook{
			Title:         title,
			FixedOrder:    fixed_order,
			Filename:      filename,
			UseSection:    use_section,
			IndexChorus:   use_chorus,
			IndexPosition: index_pos,
			Songs:         songs},
		nil
}

func GetSongOrder(sbook *Songbook) (keys []int) {
	keys = make([]int, len(sbook.Songs))
	i := 0
	for k := range sbook.Songs {
		keys[i] = k
		i++
	}
	sort.Sort(sort.IntSlice(keys))

	return keys
}

func GetSongSlice(sbook *Songbook) (songs []Song) {
	keys := GetSongOrder(sbook)
	songs = make([]Song, len(sbook.Songs))

	ind := 0
	for _, k := range keys {
		songs[ind] = sbook.Songs[k]
		ind++
	}

	return songs
}

func (sbook Songbook) Link() string {
	return sbook.Filename[0 : len(sbook.Filename)-9]
}
<commit_msg>Reposition space trimming in Songbook parsing<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

//Structs used when parsing a song file
type Songbook struct {
	FixedOrder    bool
	UseSection    bool
	IndexChorus   bool
	IndexPosition int
	Filename      string
	Title         string
	Songs         map[int]Song
}

const (
	IndexNone  = 0
	IndexStart = 1
	IndexEnd   = 2
)

func ParseSongbookFile(filename string, songs_root string) (*Songbook, error) {
	file, err := os.Open(filename)

	filename = filepath.Base(filename)
	title := filename[0 : len(filename)-len(".songlist")]

	if err != nil {
		return nil, err
	}
	defer file.Close()

	var (
		scanner     = bufio.NewScanner(file)
		fixed_order = false
		use_section = false
		use_chorus  = false
		index_pos   = IndexNone
		songs       = make(map[int]Song)
	)

	//bad_command_regex := regexp.MustCompile("\\{|\\}")

	for scanner.Scan() {
		line := scanner.Text()

		//is this a command
		if strings.HasPrefix(line, "{") {
			command := strings.ToLower(line)
			if strings.HasPrefix(command, "{title:") {
				title = parseCommand(line)
				continue
			} else if strings.HasPrefix(command, "{fixed_order}") {
				fixed_order = true
				continue
			} else if strings.HasPrefix(command, "{index_use_sections}") {
				use_section = true
				continue
			} else if strings.HasPrefix(command, "{index_use_chorus}") {
				use_chorus = true
				continue
			} else if strings.HasPrefix(command, "{index_position:") {
				p := parseCommand(line)

				switch p {
				case "start":
					index_pos = IndexStart
					break
				case "end":
					index_pos = IndexEnd
					break
				case "none":
				default:
					index_pos = IndexNone
				}

				continue
			} else {
				fmt.Printf("Unknown tag: %s\n", line)
				continue
			}
		}

		line = strings.TrimSpace(line)

		//ignore blank lines
		if len(line) > 0 {
			num := -1
			//check for fixed numbering
			if strings.Index(line, ",") > 0 {
				num_str := line[0:strings.Index(line, ",")]
				num, err = strconv.Atoi(num_str)
				if err == nil {
					line = line[len(num_str)+1 : len(line)]
				} else {
					num = -1
				}
			}

			//including '.song' extension is optional
			if !strings.HasSuffix(line, ".song") {
				line += ".song"
			}

			song, err := ParseSongFile(songs_root+"/"+line, 0)

			if err != nil {
				fmt.Println(num, ":", err)
			} else {
				if num < 0 {
					num = len(songs) + 1
				}
				song.SongNumber = num
				songs[num] = *song
			}
		}
	}

	return &Songbook{
			Title:         title,
			FixedOrder:    fixed_order,
			Filename:      filename,
			UseSection:    use_section,
			IndexChorus:   use_chorus,
			IndexPosition: index_pos,
			Songs:         songs},
		nil
}

func GetSongOrder(sbook *Songbook) (keys []int) {
	keys = make([]int, len(sbook.Songs))
	i := 0
	for k := range sbook.Songs {
		keys[i] = k
		i++
	}
	sort.Sort(sort.IntSlice(keys))

	return keys
}

func GetSongSlice(sbook *Songbook) (songs []Song) {
	keys := GetSongOrder(sbook)
	songs = make([]Song, len(sbook.Songs))

	ind := 0
	for _, k := range keys {
		songs[ind] = sbook.Songs[k]
		ind++
	}

	return songs
}

func (sbook Songbook) Link() string {
	return sbook.Filename[0 : len(sbook.Filename)-9]
}
<|endoftext|>