diff --git a/.github/actions/check/entrypoint.sh b/.github/actions/check/entrypoint.sh index f38f6f6..4a2cbeb 100644 --- a/.github/actions/check/entrypoint.sh +++ b/.github/actions/check/entrypoint.sh @@ -1,4 +1,4 @@ #!/bin/sh set -e golangci-lint run -go test -cover ./... \ No newline at end of file +go test -cover -short ./... \ No newline at end of file diff --git a/Makefile b/Makefile index 35418d5..0f33e75 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,6 @@ endif git push origin $(NEW_VERSION) vendor: - go run main.go -ra vendor + go mod vendor .PHONY: vendor \ No newline at end of file diff --git a/actions/action.go b/actions/action.go index 3913341..2a3136a 100644 --- a/actions/action.go +++ b/actions/action.go @@ -2,81 +2,46 @@ package actions import ( "fmt" - "net/http" - "net/url" + "log" "os" - "path/filepath" - "regexp" - "strings" - "github.com/nektos/act/common" - log "github.com/sirupsen/logrus" + "github.com/actions/workflow-parser/model" + "github.com/howeyc/gopass" ) -// imageURL is the directory where a `Dockerfile` should exist -func parseImageLocal(workingDir string, contextDir string) (contextDirOut string, tag string, ok bool) { - if !strings.HasPrefix(contextDir, "./") { - return "", "", false - } - contextDir = filepath.Join(workingDir, contextDir) - if _, err := os.Stat(filepath.Join(contextDir, "Dockerfile")); os.IsNotExist(err) { - log.Debugf("Ignoring missing Dockerfile '%s/Dockerfile'", contextDir) - return "", "", false - } +var secretCache map[string]string - sha, _, err := common.FindGitRevision(contextDir) - if err != nil { - log.Warnf("Unable to determine git revision: %v", err) - sha = "latest" - } - return contextDir, fmt.Sprintf("%s:%s", filepath.Base(contextDir), sha), true +type actionEnvironmentApplier struct { + *model.Action } -// imageURL is the URL for a docker repo -func parseImageReference(image string) (ref string, ok bool) { - imageURL, err := url.Parse(image) - if err != nil { - log.Debugf("Unable to parse image as url: %v", err) - return "", false - } - if imageURL.Scheme != "docker" { - log.Debugf("Ignoring non-docker ref '%s'", imageURL.String()) - return "", false - } - - return fmt.Sprintf("%s%s", imageURL.Host, imageURL.Path), true +func newActionEnvironmentApplier(action *model.Action) environmentApplier { + return &actionEnvironmentApplier{action} } -// imageURL is the directory where a `Dockerfile` should exist -func parseImageGithub(image string) (cloneURL *url.URL, ref string, path string, ok bool) { - re := regexp.MustCompile("^([^/@]+)/([^/@]+)(/([^@]*))?(@(.*))?$") - matches := re.FindStringSubmatch(image) - - if matches == nil { - return nil, "", "", false +func (action *actionEnvironmentApplier) applyEnvironment(env map[string]string) { + for envKey, envValue := range action.Env { + env[envKey] = envValue } - cloneURL, err := url.Parse(fmt.Sprintf("https://github.com/%s/%s", matches[1], matches[2])) - if err != nil { - log.Debugf("Unable to parse as URL: %v", err) - return nil, "", "", false - } + for _, secret := range action.Secrets { + if secretVal, ok := os.LookupEnv(secret); ok { + env[secret] = secretVal + } else { + if secretCache == nil { + secretCache = make(map[string]string) + } - resp, err := http.Head(cloneURL.String()) - if resp.StatusCode >= 400 || err != nil { - log.Debugf("Unable to HEAD URL %s status=%v err=%v", cloneURL.String(), resp.StatusCode, err) - return nil, "", "", false - } + if _, ok := secretCache[secret]; !ok { + fmt.Printf("Provide value for '%s': ", secret) + val, err := gopass.GetPasswdMasked() + if err != nil { + log.Fatal("abort") + } - ref = matches[6] - if ref == "" { - ref = "master" + secretCache[secret] = string(val) + } + env[secret] = secretCache[secret] + } } - - path = matches[4] - if path == "" { - path = "." - } - - return cloneURL, ref, path, true } diff --git a/actions/graph.go b/actions/graph.go new file mode 100644 index 0000000..1e1bbc9 --- /dev/null +++ b/actions/graph.go @@ -0,0 +1,64 @@ +package actions + +import ( + "log" + + "github.com/actions/workflow-parser/model" +) + +// return a pipeline that is run in series. pipeline is a list of steps to run in parallel +func newExecutionGraph(workflowConfig *model.Configuration, actionNames ...string) [][]string { + // first, build a list of all the necessary actions to run, and their dependencies + actionDependencies := make(map[string][]string) + for len(actionNames) > 0 { + newActionNames := make([]string, 0) + for _, aName := range actionNames { + // make sure we haven't visited this action yet + if _, ok := actionDependencies[aName]; !ok { + action := workflowConfig.GetAction(aName) + if action != nil { + actionDependencies[aName] = action.Needs + newActionNames = append(newActionNames, action.Needs...) + } + } + } + actionNames = newActionNames + } + + // next, build an execution graph + graph := make([][]string, 0) + for len(actionDependencies) > 0 { + stage := make([]string, 0) + for aName, aDeps := range actionDependencies { + // make sure all deps are in the graph already + if listInLists(aDeps, graph...) { + stage = append(stage, aName) + delete(actionDependencies, aName) + } + } + if len(stage) == 0 { + log.Fatalf("Unable to build dependency graph!") + } + graph = append(graph, stage) + } + + return graph +} + +// return true iff all strings in srcList exist in at least one of the searchLists +func listInLists(srcList []string, searchLists ...[]string) bool { + for _, src := range srcList { + found := false + for _, searchList := range searchLists { + for _, search := range searchList { + if src == search { + found = true + } + } + } + if !found { + return false + } + } + return true +} diff --git a/actions/model.go b/actions/model.go deleted file mode 100644 index bf720d8..0000000 --- a/actions/model.go +++ /dev/null @@ -1,129 +0,0 @@ -package actions - -import ( - "fmt" - "log" - "os" - - "github.com/howeyc/gopass" -) - -type workflowModel struct { - On string - Resolves []string -} - -type actionModel struct { - Needs []string - Uses string - Runs []string - Args []string - Env map[string]string - Secrets []string -} - -type workflowsFile struct { - Workflow map[string]workflowModel - Action map[string]actionModel -} - -func (wFile *workflowsFile) getWorkflow(eventName string) (*workflowModel, string, error) { - var rtn workflowModel - for wName, w := range wFile.Workflow { - if w.On == eventName { - rtn = w - return &rtn, wName, nil - } - } - return nil, "", fmt.Errorf("unsupported event: %v", eventName) -} - -func (wFile *workflowsFile) getAction(actionName string) (*actionModel, error) { - if a, ok := wFile.Action[actionName]; ok { - return &a, nil - } - return nil, fmt.Errorf("unsupported action: %v", actionName) -} - -// return a pipeline that is run in series. pipeline is a list of steps to run in parallel -func (wFile *workflowsFile) newExecutionGraph(actionNames ...string) [][]string { - // first, build a list of all the necessary actions to run, and their dependencies - actionDependencies := make(map[string][]string) - for len(actionNames) > 0 { - newActionNames := make([]string, 0) - for _, aName := range actionNames { - // make sure we haven't visited this action yet - if _, ok := actionDependencies[aName]; !ok { - actionDependencies[aName] = wFile.Action[aName].Needs - newActionNames = append(newActionNames, wFile.Action[aName].Needs...) - } - } - actionNames = newActionNames - } - - // next, build an execution graph - graph := make([][]string, 0) - for len(actionDependencies) > 0 { - stage := make([]string, 0) - for aName, aDeps := range actionDependencies { - // make sure all deps are in the graph already - if listInLists(aDeps, graph...) { - stage = append(stage, aName) - delete(actionDependencies, aName) - } - } - if len(stage) == 0 { - log.Fatalf("Unable to build dependency graph!") - } - graph = append(graph, stage) - } - - return graph -} - -// return true iff all strings in srcList exist in at least one of the searchLists -func listInLists(srcList []string, searchLists ...[]string) bool { - for _, src := range srcList { - found := false - for _, searchList := range searchLists { - for _, search := range searchList { - if src == search { - found = true - } - } - } - if !found { - return false - } - } - return true -} - -var secretCache map[string]string - -func (action *actionModel) applyEnvironment(env map[string]string) { - for envKey, envValue := range action.Env { - env[envKey] = envValue - } - - for _, secret := range action.Secrets { - if secretVal, ok := os.LookupEnv(secret); ok { - env[secret] = secretVal - } else { - if secretCache == nil { - secretCache = make(map[string]string) - } - - if _, ok := secretCache[secret]; !ok { - fmt.Printf("Provide value for '%s': ", secret) - val, err := gopass.GetPasswdMasked() - if err != nil { - log.Fatal("abort") - } - - secretCache[secret] = string(val) - } - env[secret] = secretCache[secret] - } - } -} diff --git a/actions/parser.go b/actions/parser.go deleted file mode 100644 index 2497a4b..0000000 --- a/actions/parser.go +++ /dev/null @@ -1,140 +0,0 @@ -package actions - -import ( - "bytes" - "errors" - "fmt" - "io" - "strings" - - "github.com/hashicorp/hcl" - "github.com/hashicorp/hcl/hcl/ast" - "github.com/hashicorp/hcl/hcl/token" - log "github.com/sirupsen/logrus" -) - -func parseWorkflowsFile(workflowReader io.Reader) (*workflowsFile, error) { - // TODO: add validation logic - // - check for circular dependencies - // - check for valid local path refs - // - check for valid dependencies - - buf := new(bytes.Buffer) - _, err := buf.ReadFrom(workflowReader) - if err != nil { - log.Error(err) - } - - workflows := new(workflowsFile) - - astFile, err := hcl.ParseBytes(buf.Bytes()) - if err != nil { - return nil, err - } - rootNode := ast.Walk(astFile.Node, cleanWorkflowsAST) - err = hcl.DecodeObject(workflows, rootNode) - if err != nil { - return nil, err - } - - return workflows, nil -} - -func cleanWorkflowsAST(node ast.Node) (ast.Node, bool) { - if objectItem, ok := node.(*ast.ObjectItem); ok { - key := objectItem.Keys[0].Token.Value() - - // handle condition where value is a string but should be a list - switch key { - case "args", "runs": - if literalType, ok := objectItem.Val.(*ast.LiteralType); ok { - listType := new(ast.ListType) - parts, err := parseCommand(literalType.Token.Value().(string)) - if err != nil { - return nil, false - } - quote := literalType.Token.Text[0] - for _, part := range parts { - part = fmt.Sprintf("%c%s%c", quote, strings.Replace(part, "\\", "\\\\", -1), quote) - listType.Add(&ast.LiteralType{ - Token: token.Token{ - Type: token.STRING, - Text: part, - }, - }) - } - objectItem.Val = listType - - } - case "resolves", "needs": - if literalType, ok := objectItem.Val.(*ast.LiteralType); ok { - listType := new(ast.ListType) - listType.Add(literalType) - objectItem.Val = listType - - } - } - } - return node, true -} - -// reused from: https://github.com/laurent22/massren/blob/ae4c57da1e09a95d9383f7eb645a9f69790dec6c/main.go#L172 -// nolint: gocyclo -func parseCommand(cmd string) ([]string, error) { - var args []string - state := "start" - current := "" - quote := "\"" - for i := 0; i < len(cmd); i++ { - c := cmd[i] - - if state == "quotes" { - if string(c) != quote { - current += string(c) - } else { - args = append(args, current) - current = "" - state = "start" - } - continue - } - - if c == '"' || c == '\'' { - state = "quotes" - quote = string(c) - continue - } - - if state == "arg" { - if c == ' ' || c == '\t' { - args = append(args, current) - current = "" - state = "start" - } else { - current += string(c) - } - continue - } - - if c != ' ' && c != '\t' { - state = "arg" - current += string(c) - } - } - - if state == "quotes" { - return []string{}, fmt.Errorf("unclosed quote in command line: %s", cmd) - } - - if current != "" { - args = append(args, current) - } - - if len(args) == 0 { - return []string{}, errors.New("empty command line") - } - - log.Debugf("Parsed literal %+q to list %+q", cmd, args) - - return args, nil -} diff --git a/actions/parser_test.go b/actions/parser_test.go deleted file mode 100644 index 9826e21..0000000 --- a/actions/parser_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package actions - -import ( - "strings" - "testing" - - log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" -) - -func TestParseWorkflowsFile(t *testing.T) { - log.SetLevel(log.DebugLevel) - - conf := ` - workflow "build-and-deploy" { - on = "push" - resolves = ["deploy"] - } - - action "build" { - uses = "./action1" - args = "echo 'build'" - } - - action "test" { - uses = "docker://ubuntu:18.04" - runs = "echo 'test'" - needs = ["build"] - } - - action "deploy" { - uses = "./action2" - args = ["echo","deploy"] - needs = ["test"] - } - - action "docker-login" { - uses = "docker://docker" - runs = ["sh", "-c", "echo $DOCKER_AUTH | docker login --username $REGISTRY_USER --password-stdin"] - secrets = ["DOCKER_AUTH"] - env = { - REGISTRY_USER = "username" - } - } - - action "unit-tests" { - uses = "./scripts/github_actions" - runs = "yarn test:ci-unittest || echo \"Unit tests failed, but running danger to present the results!\" 2>&1" - } - - action "regex-in-args" { - uses = "actions/bin/filter@master" - args = "tag v?[0-9]+\\.[0-9]+\\.[0-9]+" - } - - action "regex-in-args-array" { - uses = "actions/bin/filter@master" - args = ["tag","v?[0-9]+\\.[0-9]+\\.[0-9]+"] - } - ` - - workflows, err := parseWorkflowsFile(strings.NewReader(conf)) - - assert.Nil(t, err) - assert.Equal(t, 1, len(workflows.Workflow)) - - w, wName, _ := workflows.getWorkflow("push") - assert.Equal(t, "build-and-deploy", wName) - assert.ElementsMatch(t, []string{"deploy"}, w.Resolves) - - actions := []struct { - name string - uses string - needs []string - runs []string - args []string - secrets []string - }{ - {"build", - "./action1", - nil, - nil, - []string{"echo", "build"}, - nil, - }, - {"test", - "docker://ubuntu:18.04", - []string{"build"}, - []string{"echo", "test"}, - nil, - nil, - }, - {"deploy", - "./action2", - []string{"test"}, - nil, - []string{"echo", "deploy"}, - nil, - }, - {"docker-login", - "docker://docker", - nil, - []string{"sh", "-c", "echo $DOCKER_AUTH | docker login --username $REGISTRY_USER --password-stdin"}, - nil, - []string{"DOCKER_AUTH"}, - }, - {"unit-tests", - "./scripts/github_actions", - nil, - []string{"yarn", "test:ci-unittest", "||", "echo", "Unit tests failed, but running danger to present the results!", "2>&1"}, - nil, - nil, - }, - {"regex-in-args", - "actions/bin/filter@master", - nil, - nil, - []string{"tag", `v?[0-9]+\.[0-9]+\.[0-9]+`}, - nil, - }, - {"regex-in-args-array", - "actions/bin/filter@master", - nil, - nil, - []string{"tag", `v?[0-9]+\.[0-9]+\.[0-9]+`}, - nil, - }, - } - - for _, exp := range actions { - act, _ := workflows.getAction(exp.name) - assert.Equal(t, exp.uses, act.Uses, "[%s] Uses", exp.name) - if exp.needs == nil { - assert.Nil(t, act.Needs, "[%s] Needs", exp.name) - } else { - assert.ElementsMatch(t, exp.needs, act.Needs, "[%s] Needs", exp.name) - } - if exp.runs == nil { - assert.Nil(t, act.Runs, "[%s] Runs", exp.name) - } else { - assert.ElementsMatch(t, exp.runs, act.Runs, "[%s] Runs", exp.name) - } - if exp.args == nil { - assert.Nil(t, act.Args, "[%s] Args", exp.name) - } else { - assert.ElementsMatch(t, exp.args, act.Args, "[%s] Args", exp.name) - } - /* - if exp.env == nil { - assert.Nil(t, act.Env, "[%s] Env", exp.name) - } else { - assert.ElementsMatch(t, exp.env, act.Env, "[%s] Env", exp.name) - } - */ - if exp.secrets == nil { - assert.Nil(t, act.Secrets, "[%s] Secrets", exp.name) - } else { - assert.ElementsMatch(t, exp.secrets, act.Secrets, "[%s] Secrets", exp.name) - } - } -} diff --git a/actions/runner.go b/actions/runner.go index fa92d95..f650e67 100644 --- a/actions/runner.go +++ b/actions/runner.go @@ -6,15 +6,17 @@ import ( "path/filepath" "sort" + "github.com/actions/workflow-parser/model" + "github.com/actions/workflow-parser/parser" "github.com/nektos/act/common" log "github.com/sirupsen/logrus" ) type runnerImpl struct { - config *RunnerConfig - workflows *workflowsFile - tempDir string - eventJSON string + config *RunnerConfig + workflowConfig *model.Configuration + tempDir string + eventJSON string } // NewRunner Creates a new Runner @@ -56,7 +58,15 @@ func (runner *runnerImpl) setupWorkflows() error { defer workflowReader.Close() - runner.workflows, err = parseWorkflowsFile(workflowReader) + runner.workflowConfig, err = parser.Parse(workflowReader) + /* + if err != nil { + parserError := err.(*parser.ParserError) + for _, e := range parserError.Errors { + fmt.Fprintln(os.Stderr, e) + } + } + */ return err } @@ -88,7 +98,7 @@ func (runner *runnerImpl) resolvePath(path string) string { func (runner *runnerImpl) ListEvents() []string { log.Debugf("Listing all events") events := make([]string, 0) - for _, w := range runner.workflows.Workflow { + for _, w := range runner.workflowConfig.Workflows { events = append(events, w.On) } @@ -103,17 +113,14 @@ func (runner *runnerImpl) ListEvents() []string { // GraphEvent builds an execution path func (runner *runnerImpl) GraphEvent(eventName string) ([][]string, error) { log.Debugf("Listing actions for event '%s'", eventName) - workflow, _, err := runner.workflows.getWorkflow(eventName) - if err != nil { - return nil, err - } - return runner.workflows.newExecutionGraph(workflow.Resolves...), nil + resolves := runner.resolveEvent(runner.config.EventName) + return newExecutionGraph(runner.workflowConfig, resolves...), nil } // RunAction runs a set of actions in parallel, and their dependencies func (runner *runnerImpl) RunActions(actionNames ...string) error { log.Debugf("Running actions %+q", actionNames) - graph := runner.workflows.newExecutionGraph(actionNames...) + graph := newExecutionGraph(runner.workflowConfig, actionNames...) pipeline := make([]common.Executor, 0) for _, actions := range graph { @@ -131,15 +138,32 @@ func (runner *runnerImpl) RunActions(actionNames ...string) error { // RunEvent runs the actions for a single event func (runner *runnerImpl) RunEvent() error { log.Debugf("Running event '%s'", runner.config.EventName) - workflow, _, err := runner.workflows.getWorkflow(runner.config.EventName) - if err != nil { - return err - } - - log.Debugf("Running actions %s -> %s", runner.config.EventName, workflow.Resolves) - return runner.RunActions(workflow.Resolves...) + resolves := runner.resolveEvent(runner.config.EventName) + log.Debugf("Running actions %s -> %s", runner.config.EventName, resolves) + return runner.RunActions(resolves...) } func (runner *runnerImpl) Close() error { return os.RemoveAll(runner.tempDir) } + +// get list of resolves for an event +func (runner *runnerImpl) resolveEvent(eventName string) []string { + workflows := runner.workflowConfig.GetWorkflows(runner.config.EventName) + resolves := make([]string, 0) + for _, workflow := range workflows { + for _, resolve := range workflow.Resolves { + found := false + for _, r := range resolves { + if r == resolve { + found = true + break + } + } + if !found { + resolves = append(resolves, resolve) + } + } + } + return resolves +} diff --git a/actions/runner_exec.go b/actions/runner_exec.go index 14a00d0..8466ec0 100644 --- a/actions/runner_exec.go +++ b/actions/runner_exec.go @@ -9,25 +9,96 @@ import ( "path/filepath" "regexp" + "github.com/actions/workflow-parser/model" "github.com/nektos/act/common" "github.com/nektos/act/container" log "github.com/sirupsen/logrus" ) func (runner *runnerImpl) newActionExecutor(actionName string) common.Executor { - action, err := runner.workflows.getAction(actionName) + action := runner.workflowConfig.GetAction(actionName) + if action == nil { + return common.NewErrorExecutor(fmt.Errorf("Unable to find action named '%s'", actionName)) + } + + executors := make([]common.Executor, 0) + image, err := runner.addImageExecutor(action, &executors) if err != nil { return common.NewErrorExecutor(err) } - env := make(map[string]string) - for _, applier := range []environmentApplier{action, runner} { - applier.applyEnvironment(env) + err = runner.addRunExecutor(action, image, &executors) + if err != nil { + return common.NewErrorExecutor(err) } - env["GITHUB_ACTION"] = actionName - logger := newActionLogger(actionName, runner.config.Dryrun) - log.Debugf("Using '%s' for action '%s'", action.Uses, actionName) + return common.NewPipelineExecutor(executors...) +} + +func (runner *runnerImpl) addImageExecutor(action *model.Action, executors *[]common.Executor) (string, error) { + var image string + logger := newActionLogger(action.Identifier, runner.config.Dryrun) + log.Debugf("Using '%s' for action '%s'", action.Uses, action.Identifier) + + in := container.DockerExecutorInput{ + Ctx: runner.config.Ctx, + Logger: logger, + Dryrun: runner.config.Dryrun, + } + switch uses := action.Uses.(type) { + + case *model.UsesDockerImage: + image = uses.Image + *executors = append(*executors, container.NewDockerPullExecutor(container.NewDockerPullExecutorInput{ + DockerExecutorInput: in, + Image: image, + })) + + case *model.UsesPath: + contextDir := filepath.Join(runner.config.WorkingDir, uses.String()) + sha, _, err := common.FindGitRevision(contextDir) + if err != nil { + log.Warnf("Unable to determine git revision: %v", err) + sha = "latest" + } + image = fmt.Sprintf("%s:%s", filepath.Base(contextDir), sha) + + *executors = append(*executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{ + DockerExecutorInput: in, + ContextDir: contextDir, + ImageTag: image, + })) + + case *model.UsesRepository: + image = fmt.Sprintf("%s:%s", filepath.Base(uses.Repository), uses.Ref) + cloneURL := fmt.Sprintf("https://github.com/%s", uses.Repository) + + cloneDir := filepath.Join(os.TempDir(), "act", action.Uses.String()) + *executors = append(*executors, common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{ + URL: cloneURL, + Ref: uses.Ref, + Dir: cloneDir, + Logger: logger, + Dryrun: runner.config.Dryrun, + })) + + contextDir := filepath.Join(cloneDir, uses.Path) + *executors = append(*executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{ + DockerExecutorInput: in, + ContextDir: contextDir, + ImageTag: image, + })) + + default: + return "", fmt.Errorf("unable to determine executor type for image '%s'", action.Uses) + } + + return image, nil +} + +func (runner *runnerImpl) addRunExecutor(action *model.Action, image string, executors *[]common.Executor) error { + logger := newActionLogger(action.Identifier, runner.config.Dryrun) + log.Debugf("Using '%s' for action '%s'", action.Uses, action.Identifier) in := container.DockerExecutorInput{ Ctx: runner.config.Ctx, @@ -35,61 +106,37 @@ func (runner *runnerImpl) newActionExecutor(actionName string) common.Executor { Dryrun: runner.config.Dryrun, } - var image string - executors := make([]common.Executor, 0) - if imageRef, ok := parseImageReference(action.Uses); ok { - executors = append(executors, container.NewDockerPullExecutor(container.NewDockerPullExecutorInput{ - DockerExecutorInput: in, - Image: imageRef, - })) - image = imageRef - } else if contextDir, imageTag, ok := parseImageLocal(runner.config.WorkingDir, action.Uses); ok { - executors = append(executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{ - DockerExecutorInput: in, - ContextDir: contextDir, - ImageTag: imageTag, - })) - image = imageTag - } else if cloneURL, ref, path, ok := parseImageGithub(action.Uses); ok { - cloneDir := filepath.Join(os.TempDir(), "act", action.Uses) - executors = append(executors, common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{ - URL: cloneURL, - Ref: ref, - Dir: cloneDir, - Logger: logger, - Dryrun: runner.config.Dryrun, - })) - - contextDir := filepath.Join(cloneDir, path) - imageTag := fmt.Sprintf("%s:%s", filepath.Base(cloneURL.Path), ref) - - executors = append(executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{ - DockerExecutorInput: in, - ContextDir: contextDir, - ImageTag: imageTag, - })) - image = imageTag - } else { - return common.NewErrorExecutor(fmt.Errorf("unable to determine executor type for image '%s'", action.Uses)) + env := make(map[string]string) + for _, applier := range []environmentApplier{newActionEnvironmentApplier(action), runner} { + applier.applyEnvironment(env) } + env["GITHUB_ACTION"] = action.Identifier ghReader, err := runner.createGithubTarball() if err != nil { - return common.NewErrorExecutor(err) + return err } envList := make([]string, 0) for k, v := range env { envList = append(envList, fmt.Sprintf("%s=%s", k, v)) } - executors = append(executors, container.NewDockerRunExecutor(container.NewDockerRunExecutorInput{ + + var cmd, entrypoint []string + if action.Args != nil { + cmd = action.Args.Split() + } + if action.Runs != nil { + entrypoint = action.Runs.Split() + } + *executors = append(*executors, container.NewDockerRunExecutor(container.NewDockerRunExecutorInput{ DockerExecutorInput: in, - Cmd: action.Args, - Entrypoint: action.Runs, + Cmd: cmd, + Entrypoint: entrypoint, Image: image, WorkingDir: "/github/workspace", Env: envList, - Name: runner.createContainerName(actionName), + Name: runner.createContainerName(action.Identifier), Binds: []string{ fmt.Sprintf("%s:%s", runner.config.WorkingDir, "/github/workspace"), fmt.Sprintf("%s:%s", runner.tempDir, "/github/home"), @@ -99,13 +146,17 @@ func (runner *runnerImpl) newActionExecutor(actionName string) common.Executor { ReuseContainers: runner.config.ReuseContainers, })) - return common.NewPipelineExecutor(executors...) + return nil } func (runner *runnerImpl) applyEnvironment(env map[string]string) { repoPath := runner.config.WorkingDir - _, workflowName, _ := runner.workflows.getWorkflow(runner.config.EventName) + workflows := runner.workflowConfig.GetWorkflows(runner.config.EventName) + if len(workflows) == 0 { + return + } + workflowName := workflows[0].Identifier env["HOME"] = "/github/home" env["GITHUB_ACTOR"] = "nektos/act" diff --git a/actions/runner_test.go b/actions/runner_test.go index bd1d31e..aea55f1 100644 --- a/actions/runner_test.go +++ b/actions/runner_test.go @@ -1,91 +1,47 @@ package actions import ( - "fmt" - "path/filepath" + "context" "testing" - "github.com/nektos/act/common" log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" + "gotest.tools/assert" ) -func TestParseImageReference(t *testing.T) { - log.SetLevel(log.DebugLevel) - tables := []struct { - refIn string - refOut string - ok bool - }{ - {"docker://myhost.com/foo/bar", "myhost.com/foo/bar", true}, - {"docker://ubuntu", "ubuntu", true}, - {"docker://ubuntu:18.04", "ubuntu:18.04", true}, - {"docker://cibuilds/hugo:0.53", "cibuilds/hugo:0.53", true}, - {"http://google.com:8080", "", false}, - {"./foo", "", false}, +func TestRunEvent(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") } + tables := []struct { + workflowPath string + eventName string + errorMessage string + }{ + {"basic.workflow", "push", ""}, + {"pipe.workflow", "push", ""}, + {"fail.workflow", "push", "exit with `FAILURE`: 1"}, + {"regex.workflow", "push", "exit with `NEUTRAL`: 78"}, + {"gitref.workflow", "push", ""}, + {"env.workflow", "push", ""}, + } + log.SetLevel(log.DebugLevel) + for _, table := range tables { - refOut, ok := parseImageReference(table.refIn) - assert.Equal(t, table.refOut, refOut) - assert.Equal(t, table.ok, ok) - } + runnerConfig := &RunnerConfig{ + Ctx: context.Background(), + WorkflowPath: table.workflowPath, + WorkingDir: "testdata", + EventName: table.eventName, + } + runner, err := NewRunner(runnerConfig) + assert.NilError(t, err, table.workflowPath) -} - -func TestParseImageLocal(t *testing.T) { - log.SetLevel(log.DebugLevel) - tables := []struct { - pathIn string - contextDir string - refTag string - ok bool - }{ - {"docker://myhost.com/foo/bar", "", "", false}, - {"http://google.com:8080", "", "", false}, - {"example/action1", "", "", false}, - {"./example/action1", "/example/action1", "action1:", true}, - } - - revision, _, err := common.FindGitRevision(".") - assert.Nil(t, err) - basedir, err := filepath.Abs("..") - assert.Nil(t, err) - for _, table := range tables { - contextDir, refTag, ok := parseImageLocal(basedir, table.pathIn) - assert.Equal(t, table.ok, ok, "ok match for %s", table.pathIn) - if ok { - assert.Equal(t, fmt.Sprintf("%s%s", basedir, table.contextDir), contextDir, "context dir doesn't match for %s", table.pathIn) - assert.Equal(t, fmt.Sprintf("%s%s", table.refTag, revision), refTag) + err = runner.RunEvent() + if table.errorMessage == "" { + assert.NilError(t, err, table.workflowPath) + } else { + assert.Error(t, err, table.errorMessage) } } - -} -func TestParseImageGithub(t *testing.T) { - log.SetLevel(log.DebugLevel) - tables := []struct { - image string - cloneURL string - ref string - path string - ok bool - }{ - {"nektos/act", "https://github.com/nektos/act", "master", ".", true}, - {"nektos/act/foo", "https://github.com/nektos/act", "master", "foo", true}, - {"nektos/act@xxxxx", "https://github.com/nektos/act", "xxxxx", ".", true}, - {"nektos/act/bar/baz@zzzzz", "https://github.com/nektos/act", "zzzzz", "bar/baz", true}, - {"assimovt/actions-github-deploy/github-deploy@deployment-status-metadata", "https://github.com/assimovt/actions-github-deploy", "deployment-status-metadata", "github-deploy", true}, - {"nektos/zzzzundefinedzzzz", "", "", "", false}, - } - - for _, table := range tables { - cloneURL, ref, path, ok := parseImageGithub(table.image) - assert.Equal(t, table.ok, ok, "ok match for %s", table.image) - if ok { - assert.Equal(t, table.cloneURL, cloneURL.String()) - assert.Equal(t, table.ref, ref) - assert.Equal(t, table.path, path) - } - } - } diff --git a/example/action1/Dockerfile b/actions/testdata/action1/Dockerfile similarity index 100% rename from example/action1/Dockerfile rename to actions/testdata/action1/Dockerfile diff --git a/example/action2/Dockerfile b/actions/testdata/action2/Dockerfile similarity index 100% rename from example/action2/Dockerfile rename to actions/testdata/action2/Dockerfile diff --git a/example/.github/main.workflow b/actions/testdata/basic.workflow similarity index 93% rename from example/.github/main.workflow rename to actions/testdata/basic.workflow index 691c643..c3e829c 100644 --- a/example/.github/main.workflow +++ b/actions/testdata/basic.workflow @@ -10,7 +10,7 @@ action "build" { action "test" { uses = "docker://ubuntu:18.04" - args = "echo 'test'" + args = "env" needs = ["build"] } diff --git a/actions/testdata/env.workflow b/actions/testdata/env.workflow new file mode 100644 index 0000000..847d1d4 --- /dev/null +++ b/actions/testdata/env.workflow @@ -0,0 +1,9 @@ +workflow "test" { + on = "push" + resolves = ["test-action"] +} + +action "test-action" { + uses = "docker://alpine:3.9" + runs = ["sh", "-c", "echo $GITHUB_REPOSITORY | grep '^nektos/act$'"] +} \ No newline at end of file diff --git a/actions/testdata/fail.workflow b/actions/testdata/fail.workflow new file mode 100644 index 0000000..2380e47 --- /dev/null +++ b/actions/testdata/fail.workflow @@ -0,0 +1,13 @@ +workflow "test" { + on = "push" + resolves = ["test-action"] +} + +action "test-action" { + uses = "docker://alpine:3.9" + runs = ["sh", "-c", "echo $IN | grep $OUT"] + env = { + IN = "foo" + OUT = "bar" + } +} \ No newline at end of file diff --git a/actions/testdata/gitref.workflow b/actions/testdata/gitref.workflow new file mode 100644 index 0000000..1cd47e0 --- /dev/null +++ b/actions/testdata/gitref.workflow @@ -0,0 +1,14 @@ +workflow "New workflow" { + on = "push" + resolves = ["branch-ref","commit-ref"] +} + +action "branch-ref" { + uses = "actions/docker/cli@master" + args = "version" +} + +action "commit-ref" { + uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6" + args = "version" +} \ No newline at end of file diff --git a/actions/testdata/pipe.workflow b/actions/testdata/pipe.workflow new file mode 100644 index 0000000..3fcc0bd --- /dev/null +++ b/actions/testdata/pipe.workflow @@ -0,0 +1,13 @@ +workflow "test" { + on = "push" + resolves = ["test-action"] +} + +action "test-action" { + uses = "docker://alpine:3.9" + runs = ["sh", "-c", "echo $IN | grep $OUT"] + env = { + IN = "foo" + OUT = "foo" + } +} \ No newline at end of file diff --git a/actions/testdata/regex.workflow b/actions/testdata/regex.workflow new file mode 100644 index 0000000..02b2b65 --- /dev/null +++ b/actions/testdata/regex.workflow @@ -0,0 +1,9 @@ +workflow "New workflow" { + on = "push" + resolves = ["filter-version-before-deploy"] +} + +action "filter-version-before-deploy" { + uses = "actions/bin/filter@master" + args = "tag z?[0-9]+\\.[0-9]+\\.[0-9]+" +} \ No newline at end of file diff --git a/common/git.go b/common/git.go index 4d2995b..a2f7925 100644 --- a/common/git.go +++ b/common/git.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io/ioutil" - "net/url" "os" "path" "path/filepath" @@ -185,7 +184,7 @@ func findGitDirectory(fromFile string) (string, error) { // NewGitCloneExecutorInput the input for the NewGitCloneExecutor type NewGitCloneExecutorInput struct { - URL *url.URL + URL string Ref string Dir string Logger *log.Entry @@ -195,8 +194,8 @@ type NewGitCloneExecutorInput struct { // NewGitCloneExecutor creates an executor to clone git repos func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { return func() error { - input.Logger.Infof("git clone '%s'", input.URL.String()) - input.Logger.Debugf(" cloning %s to %s", input.URL.String(), input.Dir) + input.Logger.Infof("git clone '%s' # ref=%s", input.URL, input.Ref) + input.Logger.Debugf(" cloning %s to %s", input.URL, input.Dir) if input.Dryrun { return nil @@ -210,11 +209,12 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { r, err := git.PlainOpen(input.Dir) if err != nil { r, err = git.PlainClone(input.Dir, false, &git.CloneOptions{ - URL: input.URL.String(), - Progress: input.Logger.WriterLevel(log.DebugLevel), - ReferenceName: refName, + URL: input.URL, + Progress: input.Logger.WriterLevel(log.DebugLevel), + //ReferenceName: refName, }) if err != nil { + input.Logger.Errorf("Unable to clone %v %s: %v", input.URL, refName, err) return err } } @@ -225,17 +225,24 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { } err = w.Pull(&git.PullOptions{ - ReferenceName: refName, - Force: true, + //ReferenceName: refName, + Force: true, }) if err != nil && err.Error() != "already up-to-date" { input.Logger.Errorf("Unable to pull %s: %v", refName, err) } - input.Logger.Debugf("Cloned %s to %s", input.URL.String(), input.Dir) + input.Logger.Debugf("Cloned %s to %s", input.URL, input.Dir) + + hash, err := r.ResolveRevision(plumbing.Revision(input.Ref)) + if err != nil { + input.Logger.Errorf("Unable to resolve %s: %v", input.Ref, err) + return err + } err = w.Checkout(&git.CheckoutOptions{ - Branch: refName, - Force: true, + //Branch: refName, + Hash: *hash, + Force: true, }) if err != nil { input.Logger.Errorf("Unable to checkout %s: %v", refName, err) diff --git a/container/docker_run.go b/container/docker_run.go index 314facb..246fca2 100644 --- a/container/docker_run.go +++ b/container/docker_run.go @@ -204,7 +204,7 @@ func waitContainer(input NewDockerRunExecutorInput, cli *client.Client, containe if statusCode == 0 { return nil } else if statusCode == 78 { - return fmt.Errorf("exiting with `NEUTRAL`: 78") + return fmt.Errorf("exit with `NEUTRAL`: 78") } return fmt.Errorf("exit with `FAILURE`: %v", statusCode) diff --git a/example/event.json b/example/event.json deleted file mode 100644 index c8c4105..0000000 --- a/example/event.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": "bar" -} diff --git a/go.mod b/go.mod index 69bb338..6e8b3f6 100644 --- a/go.mod +++ b/go.mod @@ -4,40 +4,47 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Microsoft/go-winio v0.4.11 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect + github.com/actions/workflow-parser v1.0.0 github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect - github.com/docker/distribution v2.7.0+incompatible // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/docker v1.13.1 github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.3.3 // indirect + github.com/emirpasic/gods v1.12.0 // indirect github.com/go-ini/ini v1.41.0 github.com/gogo/protobuf v1.2.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect - github.com/gorilla/context v1.1.1 // indirect - github.com/gorilla/mux v1.6.2 // indirect - github.com/hashicorp/hcl v1.0.0 + github.com/gorilla/mux v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jtolds/gls v4.2.1+incompatible // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect github.com/pkg/errors v0.8.1 // indirect github.com/sirupsen/logrus v1.3.0 - github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect + github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c // indirect + github.com/soniakeys/graph v0.0.0 // indirect github.com/spf13/cobra v0.0.3 github.com/spf13/pflag v1.0.3 // indirect github.com/stretchr/testify v1.3.0 - golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc - golang.org/x/net v0.0.0-20181220203305-927f97764cc3 // indirect + golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 + golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect - golang.org/x/sys v0.0.0-20190102155601-82a175fd1598 // indirect + golang.org/x/sys v0.0.0-20190201152629-afcc84fd7533 // indirect + golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 // indirect golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect - google.golang.org/grpc v1.17.0 // indirect + google.golang.org/genproto v0.0.0-20190128161407-8ac453e89fca // indirect + google.golang.org/grpc v1.18.0 // indirect gopkg.in/ini.v1 v1.41.0 // indirect - gopkg.in/src-d/go-git.v4 v4.8.1 + gopkg.in/src-d/go-billy.v4 v4.3.0 // indirect + gopkg.in/src-d/go-git-fixtures.v3 v3.3.0 // indirect + gopkg.in/src-d/go-git.v4 v4.9.1 gopkg.in/yaml.v2 v2.2.2 - gotest.tools v2.2.0+incompatible // indirect + gotest.tools v2.2.0+incompatible ) replace github.com/docker/docker => github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb diff --git a/go.sum b/go.sum index 2b495e3..8d099d1 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/actions/workflow-parser v1.0.0 h1:Zz2Ke31f3OMYCSzU2pqZSsk/Oz+lWXfEiXMisjxgGcc= +github.com/actions/workflow-parser v1.0.0/go.mod h1:jz9ZVl8zUIcjMfDQearQjvUHIBhx9l1ys4keDd6be34= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -15,8 +17,8 @@ github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU= -github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb h1:PyjxRdW1mqCmSoxy/6uP01P7CGbsD+woX+oOWbaUPwQ= @@ -27,6 +29,8 @@ github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/emirpasic/gods v1.9.0 h1:rUF4PuzEjMChMiNsVjdI+SyLu7rEqpQ5reNFnhC7oFo= github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw= @@ -37,6 +41,7 @@ github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -44,10 +49,8 @@ github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= +github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= @@ -72,6 +75,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -90,10 +95,14 @@ github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= +github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= +github.com/soniakeys/bits v1.0.0 h1:Rune9VFefdJvLE0Q5iRCVGiKdSu2iDihs2I6SCm7evw= +github.com/soniakeys/bits v1.0.0/go.mod h1:7yJHB//UizrUr64VFneewK6SX5oeCf0SMbDYe2ey1JA= +github.com/soniakeys/graph v0.0.0 h1:C/Rr8rv9wbhZIsYHcWJFoI84pkipJocMYdRteE+/PQA= +github.com/soniakeys/graph v0.0.0/go.mod h1:lxpIbor/bIzWUAqvt1Dx92Hr63uWeyuEAbPnsjYbVwM= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= @@ -111,13 +120,16 @@ github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc h1:F5tKCVGp+MUAHhKp5MZtGqAlGX3+oCsiL1Q629FL90M= -golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 h1:MQ/ZZiDsUapFFiMS+vzwXkCTeEKaum+Do5rINYJDmxc= +golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -127,10 +139,12 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190102155601-82a175fd1598 h1:S8GOgffXV1X3fpVG442QRfWOt0iFl79eHJ7OPt725bo= -golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190201152629-afcc84fd7533 h1:bLfqnzrpeG4usq5OvMCrwTdmMJ6aTmlCuo1eKl0mhkI= +golang.org/x/sys v0.0.0-20190201152629-afcc84fd7533/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52 h1:JG/0uqcGdTNgq7FdU+61l5Pdmb8putNZlXb65bJBROs= @@ -138,8 +152,11 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/genproto v0.0.0-20190128161407-8ac453e89fca h1:L1odPN6KVjhk0Lbg41BKcjGjP7ELTvh/qDcyh6hEfv0= +google.golang.org/genproto v0.0.0-20190128161407-8ac453e89fca/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.18.0 h1:IZl7mfBGfbhYx2p2rKRtYgDFw6SBz+kclmxYrCksPPA= +google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= @@ -148,10 +165,14 @@ gopkg.in/ini.v1 v1.41.0 h1:Ka3ViY6gNYSKiVy71zXBEqKplnV35ImDLVG+8uoIklE= gopkg.in/ini.v1 v1.41.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/src-d/go-billy.v4 v4.2.1 h1:omN5CrMrMcQ+4I8bJ0wEhOBPanIRWzFC953IiXKdYzo= gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= +gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek= +gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= gopkg.in/src-d/go-git-fixtures.v3 v3.1.1 h1:XWW/s5W18RaJpmo1l0IYGqXKuJITWRFuA45iOf1dKJs= gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.8.1 h1:aAyBmkdE1QUUEHcP4YFCGKmsMQRAuRmUcPEQR7lOAa0= -gopkg.in/src-d/go-git.v4 v4.8.1/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= +gopkg.in/src-d/go-git-fixtures.v3 v3.3.0 h1:AxUOwLW3at53ysFqs0Lg+H+8KSQXl7AEHBvWj8wEsT8= +gopkg.in/src-d/go-git-fixtures.v3 v3.3.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.9.1 h1:0oKHJZY8tM7B71378cfTg2c5jmWyNlXvestTT6WfY+4= +gopkg.in/src-d/go-git.v4 v4.9.1/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= diff --git a/vendor/github.com/actions/workflow-parser/LICENSE b/vendor/github.com/actions/workflow-parser/LICENSE new file mode 100644 index 0000000..331b241 --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/actions/workflow-parser/model/command.go b/vendor/github.com/actions/workflow-parser/model/command.go new file mode 100644 index 0000000..468f084 --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/model/command.go @@ -0,0 +1,38 @@ +package model + +import ( + "strings" +) + +// Command represents the optional "runs" and "args" attributes. +// Each one takes one of two forms: +// - runs="entrypoint arg1 arg2 ..." +// - runs=[ "entrypoint", "arg1", "arg2", ... ] +type Command interface { + isCommand() + Split() []string +} + +// StringCommand represents the string based form of the "runs" or "args" +// attribute. +// - runs="entrypoint arg1 arg2 ..." +type StringCommand struct { + Value string +} + +// ListCommand represents the list based form of the "runs" or "args" attribute. +// - runs=[ "entrypoint", "arg1", "arg2", ... ] +type ListCommand struct { + Values []string +} + +func (s *StringCommand) isCommand() {} +func (l *ListCommand) isCommand() {} + +func (s *StringCommand) Split() []string { + return strings.Fields(s.Value) +} + +func (l *ListCommand) Split() []string { + return l.Values +} diff --git a/vendor/github.com/actions/workflow-parser/model/configuration.go b/vendor/github.com/actions/workflow-parser/model/configuration.go new file mode 100644 index 0000000..184c66e --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/model/configuration.go @@ -0,0 +1,64 @@ +package model + +import ( + "strings" +) + +// Configuration is a parsed main.workflow file +type Configuration struct { + Actions []*Action + Workflows []*Workflow +} + +// Action represents a single "action" stanza in a .workflow file. +type Action struct { + Identifier string + Uses Uses + Runs, Args Command + Needs []string + Env map[string]string + Secrets []string +} + +// Workflow represents a single "workflow" stanza in a .workflow file. +type Workflow struct { + Identifier string + On string + Resolves []string +} + +// GetAction looks up action by identifier. +// +// If the action is not found, nil is returned. +func (c *Configuration) GetAction(id string) *Action { + for _, action := range c.Actions { + if action.Identifier == id { + return action + } + } + return nil +} + +// GetWorkflow looks up a workflow by identifier. +// +// If the workflow is not found, nil is returned. +func (c *Configuration) GetWorkflow(id string) *Workflow { + for _, workflow := range c.Workflows { + if workflow.Identifier == id { + return workflow + } + } + return nil +} + +// GetWorkflows gets all Workflow structures that match a given type of event. +// e.g., GetWorkflows("push") +func (c *Configuration) GetWorkflows(eventType string) []*Workflow { + var ret []*Workflow + for _, workflow := range c.Workflows { + if strings.EqualFold(workflow.On, eventType) { + ret = append(ret, workflow) + } + } + return ret +} diff --git a/vendor/github.com/actions/workflow-parser/model/uses.go b/vendor/github.com/actions/workflow-parser/model/uses.go new file mode 100644 index 0000000..54de82f --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/model/uses.go @@ -0,0 +1,57 @@ +package model + +import ( + "fmt" +) + +type Uses interface { + fmt.Stringer + isUses() +} + +// UsesDockerImage represents `uses = "docker://"` +type UsesDockerImage struct { + Image string +} + +// UsesRepository represents `uses = "/[/]@"` +type UsesRepository struct { + Repository string + Path string + Ref string +} + +// UsesPath represents `uses = "./"` +type UsesPath struct { + Path string +} + +// UsesInvalid represents any invalid `uses = ""` value +type UsesInvalid struct { + Raw string +} + +func (u *UsesDockerImage) isUses() {} +func (u *UsesRepository) isUses() {} +func (u *UsesPath) isUses() {} +func (u *UsesInvalid) isUses() {} + +func (u *UsesDockerImage) String() string { + return fmt.Sprintf("docker://%s", u.Image) +} + +func (u *UsesRepository) String() string { + if u.Path == "" { + return fmt.Sprintf("%s@%s", u.Repository, u.Ref) + } + + return fmt.Sprintf("%s/%s@%s", u.Repository, u.Path, u.Ref) +} + +func (u *UsesPath) String() string { + return fmt.Sprintf("./%s", u.Path) +} + +func (u *UsesInvalid) String() string { + return u.Raw +} diff --git a/vendor/github.com/actions/workflow-parser/parser/errors.go b/vendor/github.com/actions/workflow-parser/parser/errors.go new file mode 100644 index 0000000..481abbe --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/parser/errors.go @@ -0,0 +1,136 @@ +package parser + +import ( + "bytes" + "fmt" + "sort" + "strconv" + "strings" + + "github.com/actions/workflow-parser/model" +) + +type Error struct { + message string + Errors []*ParseError + Actions []*model.Action + Workflows []*model.Workflow +} + +func (e *Error) Error() string { + buffer := bytes.NewBuffer(nil) + buffer.WriteString(e.message) + for _, pe := range e.Errors { + buffer.WriteString("\n ") + buffer.WriteString(pe.Error()) + } + return buffer.String() +} + +// FirstError searches a Configuration for the first error at or above a +// given severity level. Checking the return value against nil is a good +// way to see if the file has any errors at or above the given severity. +// A caller intending to execute the file might check for +// `errors.FirstError(parser.WARNING)`, while a caller intending to +// display the file might check for `errors.FirstError(parser.FATAL)`. +func (e *Error) FirstError(severity Severity) error { + for _, pe := range e.Errors { + if pe.Severity >= severity { + return pe + } + } + return nil +} + +// ParseError represents an error identified by the parser, either syntactic +// (HCL) or semantic (.workflow) in nature. There are fields for location +// (File, Line, Column), severity, and base error string. The `Error()` +// function on this type concatenates whatever bits of the location are +// available with the message. The severity is only used for filtering. +type ParseError struct { + message string + Pos ErrorPos + Severity Severity +} + +// ErrorPos represents the location of an error in a user's workflow +// file(s). +type ErrorPos struct { + File string + Line int + Column int +} + +// newFatal creates a new error at the FATAL level, indicating that the +// file is so broken it should not be displayed. +func newFatal(pos ErrorPos, format string, a ...interface{}) *ParseError { + return &ParseError{ + message: fmt.Sprintf(format, a...), + Pos: pos, + Severity: FATAL, + } +} + +// newError creates a new error at the ERROR level, indicating that the +// file can be displayed but cannot be run. +func newError(pos ErrorPos, format string, a ...interface{}) *ParseError { + return &ParseError{ + message: fmt.Sprintf(format, a...), + Pos: pos, + Severity: ERROR, + } +} + +// newWarning creates a new error at the WARNING level, indicating that +// the file might be runnable but might not execute as intended. +func newWarning(pos ErrorPos, format string, a ...interface{}) *ParseError { + return &ParseError{ + message: fmt.Sprintf(format, a...), + Pos: pos, + Severity: WARNING, + } +} + +func (e *ParseError) Error() string { + var sb strings.Builder + if e.Pos.Line != 0 { + sb.WriteString("Line ") // nolint: errcheck + sb.WriteString(strconv.Itoa(e.Pos.Line)) // nolint: errcheck + sb.WriteString(": ") // nolint: errcheck + } + if sb.Len() > 0 { + sb.WriteString(e.message) // nolint: errcheck + return sb.String() + } + return e.message +} + +const ( + _ = iota + + // WARNING indicates a mistake that might affect correctness + WARNING + + // ERROR indicates a mistake that prevents execution of any workflows in the file + ERROR + + // FATAL indicates a mistake that prevents even drawing the file + FATAL +) + +// Severity represents the level of an error encountered while parsing a +// workflow file. See the comments for WARNING, ERROR, and FATAL, above. +type Severity int + +type errorList []*ParseError + +func (a errorList) Len() int { return len(a) } +func (a errorList) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a errorList) Less(i, j int) bool { return a[i].Pos.Line < a[j].Pos.Line } + +// sortErrors sorts the errors reported by the parser. Do this after +// parsing is complete. The sort is stable, so order is preserved within +// a single line: left to right, syntax errors before validation errors. +func (errors errorList) sort() { + sort.Stable(errors) +} diff --git a/vendor/github.com/actions/workflow-parser/parser/events.go b/vendor/github.com/actions/workflow-parser/parser/events.go new file mode 100644 index 0000000..8e47e0c --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/parser/events.go @@ -0,0 +1,42 @@ +package parser + +import ( + "strings" +) + +// isAllowedEventType returns true if the event type is supported. +func isAllowedEventType(eventType string) bool { + _, ok := eventTypeWhitelist[strings.ToLower(eventType)] + return ok +} + +// https://developer.github.com/actions/creating-workflows/workflow-configuration-options/#events-supported-in-workflow-files +var eventTypeWhitelist = map[string]struct{}{ + "check_run": {}, + "check_suite": {}, + "commit_comment": {}, + "create": {}, + "delete": {}, + "deployment": {}, + "deployment_status": {}, + "fork": {}, + "gollum": {}, + "issue_comment": {}, + "issues": {}, + "label": {}, + "member": {}, + "milestone": {}, + "page_build": {}, + "project_card": {}, + "project_column": {}, + "project": {}, + "public": {}, + "pull_request_review_comment": {}, + "pull_request_review": {}, + "pull_request": {}, + "push": {}, + "release": {}, + "repository_dispatch": {}, + "status": {}, + "watch": {}, +} diff --git a/vendor/github.com/actions/workflow-parser/parser/opts.go b/vendor/github.com/actions/workflow-parser/parser/opts.go new file mode 100644 index 0000000..a64eea7 --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/parser/opts.go @@ -0,0 +1,15 @@ +package parser + +type OptionFunc func(*Parser) + +func WithSuppressWarnings() OptionFunc { + return func(ps *Parser) { + ps.suppressSeverity = WARNING + } +} + +func WithSuppressErrors() OptionFunc { + return func(ps *Parser) { + ps.suppressSeverity = ERROR + } +} diff --git a/vendor/github.com/actions/workflow-parser/parser/parser.go b/vendor/github.com/actions/workflow-parser/parser/parser.go new file mode 100644 index 0000000..37a3ec4 --- /dev/null +++ b/vendor/github.com/actions/workflow-parser/parser/parser.go @@ -0,0 +1,807 @@ +package parser + +import ( + "fmt" + "io" + "io/ioutil" + "regexp" + "strings" + + "github.com/actions/workflow-parser/model" + "github.com/hashicorp/hcl" + "github.com/hashicorp/hcl/hcl/ast" + hclparser "github.com/hashicorp/hcl/hcl/parser" + "github.com/hashicorp/hcl/hcl/token" + "github.com/soniakeys/graph" +) + +const minVersion = 0 +const maxVersion = 0 +const maxSecrets = 100 + +type Parser struct { + version int + actions []*model.Action + workflows []*model.Workflow + errors errorList + + posMap map[interface{}]ast.Node + suppressSeverity Severity +} + +// Parse parses a .workflow file and return the actions and global variables found within. +func Parse(reader io.Reader, options ...OptionFunc) (*model.Configuration, error) { + // FIXME - check context for deadline? + b, err := ioutil.ReadAll(reader) + if err != nil { + return nil, err + } + + root, err := hcl.ParseBytes(b) + if err != nil { + if pe, ok := err.(*hclparser.PosError); ok { + pos := ErrorPos{File: pe.Pos.Filename, Line: pe.Pos.Line, Column: pe.Pos.Column} + errors := errorList{newFatal(pos, pe.Err.Error())} + return nil, &Error{ + message: "unable to parse", + Errors: errors, + } + } + return nil, err + } + + p := parseAndValidate(root.Node, options...) + if len(p.errors) > 0 { + return nil, &Error{ + message: "unable to parse and validate", + Errors: p.errors, + Actions: p.actions, + Workflows: p.workflows, + } + } + + return &model.Configuration{ + Actions: p.actions, + Workflows: p.workflows, + }, nil +} + +// parseAndValidate converts a HCL AST into a Parser and validates +// high-level structure. +// Parameters: +// - root - the contents of a .workflow file, as AST +// Returns: +// - a Parser structure containing actions and workflow definitions +func parseAndValidate(root ast.Node, options ...OptionFunc) *Parser { + p := &Parser{ + posMap: make(map[interface{}]ast.Node), + } + + for _, option := range options { + option(p) + } + + p.parseRoot(root) + p.validate() + p.errors.sort() + + return p +} + +func (p *Parser) validate() { + p.analyzeDependencies() + p.checkCircularDependencies() + p.checkActions() + p.checkFlows() +} + +func uniqStrings(items []string) []string { + seen := make(map[string]bool) + ret := make([]string, 0, len(items)) + for _, item := range items { + if !seen[item] { + seen[item] = true + ret = append(ret, item) + } + } + return ret +} + +// checkCircularDependencies finds loops in the action graph. +// It emits a fatal error for each cycle it finds, in the order (top to +// bottom, left to right) they appear in the .workflow file. +func (p *Parser) checkCircularDependencies() { + // make a map from action name to node ID, which is the index in the p.actions array + // That is, p.actions[actionmap[X]].Identifier == X + actionmap := make(map[string]graph.NI) + for i, action := range p.actions { + actionmap[action.Identifier] = graph.NI(i) + } + + // make an adjacency list representation of the action dependency graph + adjList := make(graph.AdjacencyList, len(p.actions)) + for i, action := range p.actions { + adjList[i] = make([]graph.NI, 0, len(action.Needs)) + for _, depName := range action.Needs { + if depIdx, ok := actionmap[depName]; ok { + adjList[i] = append(adjList[i], depIdx) + } + } + } + + // find cycles, and print a fatal error for each one + g := graph.Directed{AdjacencyList: adjList} + g.Cycles(func(cycle []graph.NI) bool { + node := p.posMap[&p.actions[cycle[len(cycle)-1]].Needs] + p.addFatal(node, "Circular dependency on `%s'", p.actions[cycle[0]].Identifier) + return true + }) +} + +// checkActions returns error if any actions are syntactically correct but +// have structural errors +func (p *Parser) checkActions() { + secrets := make(map[string]bool) + for _, t := range p.actions { + // Ensure the Action has a `uses` attribute + if t.Uses == nil { + p.addError(p.posMap[t], "Action `%s' must have a `uses' attribute", t.Identifier) + // continue, checking other actions + } + + // Ensure there aren't too many secrets + for _, str := range t.Secrets { + if !secrets[str] { + secrets[str] = true + if len(secrets) == maxSecrets+1 { + p.addError(p.posMap[&t.Secrets], "All actions combined must not have more than %d unique secrets", maxSecrets) + } + } + } + + // Ensure that no environment variable or secret begins with + // "GITHUB_", unless it's "GITHUB_TOKEN". + // Also ensure that all environment variable names come from the legal + // form for environment variable names. + // Finally, ensure that the same key name isn't used more than once + // between env and secrets, combined. + for k := range t.Env { + p.checkEnvironmentVariable(k, p.posMap[&t.Env]) + } + secretVars := make(map[string]bool) + for _, k := range t.Secrets { + p.checkEnvironmentVariable(k, p.posMap[&t.Secrets]) + if _, found := t.Env[k]; found { + p.addError(p.posMap[&t.Secrets], "Secret `%s' conflicts with an environment variable with the same name", k) + } + if secretVars[k] { + p.addWarning(p.posMap[&t.Secrets], "Secret `%s' redefined", k) + } + secretVars[k] = true + } + } +} + +var envVarChecker = regexp.MustCompile(`\A[A-Za-z_][A-Za-z_0-9]*\z`) + +func (p *Parser) checkEnvironmentVariable(key string, node ast.Node) { + if key != "GITHUB_TOKEN" && strings.HasPrefix(key, "GITHUB_") { + p.addWarning(node, "Environment variables and secrets beginning with `GITHUB_' are reserved") + } + if !envVarChecker.MatchString(key) { + p.addWarning(node, "Environment variables and secrets must contain only A-Z, a-z, 0-9, and _ characters, got `%s'", key) + } +} + +// checkFlows appends an error if any workflows are syntactically correct but +// have structural errors +func (p *Parser) checkFlows() { + actionmap := makeActionMap(p.actions) + for _, f := range p.workflows { + // make sure there's an `on` attribute + if f.On == "" { + p.addError(p.posMap[f], "Workflow `%s' must have an `on' attribute", f.Identifier) + // continue, checking other workflows + } else if !isAllowedEventType(f.On) { + p.addError(p.posMap[&f.On], "Workflow `%s' has unknown `on' value `%s'", f.Identifier, f.On) + // continue, checking other workflows + } + + // make sure that the actions that are resolved all exist + for _, actionID := range f.Resolves { + _, ok := actionmap[actionID] + if !ok { + p.addError(p.posMap[&f.Resolves], "Workflow `%s' resolves unknown action `%s'", f.Identifier, actionID) + // continue, checking other workflows + } + } + } +} + +func makeActionMap(actions []*model.Action) map[string]*model.Action { + actionmap := make(map[string]*model.Action) + for _, action := range actions { + actionmap[action.Identifier] = action + } + return actionmap +} + +// Fill in Action dependencies for all actions based on explicit dependencies +// declarations. +// +// p.actions is an array of Action objects, as parsed. The Action objects in +// this array are mutated, by setting Action.dependencies for each. +func (p *Parser) analyzeDependencies() { + actionmap := makeActionMap(p.actions) + for _, action := range p.actions { + // analyze explicit dependencies for each "needs" keyword + p.analyzeNeeds(action, actionmap) + } + + // uniq all the dependencies lists + for _, action := range p.actions { + if len(action.Needs) >= 2 { + action.Needs = uniqStrings(action.Needs) + } + } +} + +func (p *Parser) analyzeNeeds(action *model.Action, actionmap map[string]*model.Action) { + for _, need := range action.Needs { + _, ok := actionmap[need] + if !ok { + p.addError(p.posMap[&action.Needs], "Action `%s' needs nonexistent action `%s'", action.Identifier, need) + // continue, checking other actions + } + } +} + +// literalToStringMap converts a object value from the AST to a +// map[string]string. For example, the HCL `{ a="b" c="d" }` becomes the +// Go expression map[string]string{ "a": "b", "c": "d" }. +// If the value doesn't adhere to that format -- e.g., +// if it's not an object, or it has non-assignment attributes, or if any +// of its values are anything other than a string, the function appends an +// appropriate error. +func (p *Parser) literalToStringMap(node ast.Node) map[string]string { + obj, ok := node.(*ast.ObjectType) + + if !ok { + p.addError(node, "Expected object, got %s", typename(node)) + return nil + } + + p.checkAssignmentsOnly(obj.List, "") + + ret := make(map[string]string) + for _, item := range obj.List.Items { + if !isAssignment(item) { + continue + } + str, ok := p.literalToString(item.Val) + if ok { + key := p.identString(item.Keys[0].Token) + if key != "" { + if _, found := ret[key]; found { + p.addWarning(node, "Environment variable `%s' redefined", key) + } + ret[key] = str + } + } + } + + return ret +} + +func (p *Parser) identString(t token.Token) string { + switch t.Type { + case token.STRING: + return t.Value().(string) + case token.IDENT: + return t.Text + default: + p.addErrorFromToken(t, + "Each identifier should be a string, got %s", + strings.ToLower(t.Type.String())) + return "" + } +} + +// literalToStringArray converts a list value from the AST to a []string. +// For example, the HCL `[ "a", "b", "c" ]` becomes the Go expression +// []string{ "a", "b", "c" }. +// If the value doesn't adhere to that format -- it's not a list, or it +// contains anything other than strings, the function appends an +// appropriate error. +// If promoteScalars is true, then values that are scalar strings are +// promoted to a single-entry string array. E.g., "foo" becomes the Go +// expression []string{ "foo" }. +func (p *Parser) literalToStringArray(node ast.Node, promoteScalars bool) ([]string, bool) { + literal, ok := node.(*ast.LiteralType) + if ok { + if promoteScalars && literal.Token.Type == token.STRING { + return []string{literal.Token.Value().(string)}, true + } + p.addError(node, "Expected list, got %s", typename(node)) + return nil, false + } + + list, ok := node.(*ast.ListType) + if !ok { + p.addError(node, "Expected list, got %s", typename(node)) + return nil, false + } + + ret := make([]string, 0, len(list.List)) + for _, literal := range list.List { + str, ok := p.literalToString(literal) + if ok { + ret = append(ret, str) + } + } + + return ret, true +} + +// literalToString converts a literal value from the AST into a string. +// If the value isn't a scalar or isn't a string, the function appends an +// appropriate error and returns "", false. +func (p *Parser) literalToString(node ast.Node) (string, bool) { + val := p.literalCast(node, token.STRING) + if val == nil { + return "", false + } + return val.(string), true +} + +// literalToInt converts a literal value from the AST into an int64. +// Supported number formats are: 123, 0x123, and 0123. +// Exponents (1e6) and floats (123.456) generate errors. +// If the value isn't a scalar or isn't a number, the function appends an +// appropriate error and returns 0, false. +func (p *Parser) literalToInt(node ast.Node) (int64, bool) { + val := p.literalCast(node, token.NUMBER) + if val == nil { + return 0, false + } + return val.(int64), true +} + +func (p *Parser) literalCast(node ast.Node, t token.Type) interface{} { + literal, ok := node.(*ast.LiteralType) + if !ok { + p.addError(node, "Expected %s, got %s", strings.ToLower(t.String()), typename(node)) + return nil + } + + if literal.Token.Type != t { + p.addError(node, "Expected %s, got %s", strings.ToLower(t.String()), typename(node)) + return nil + } + + return literal.Token.Value() +} + +// parseRoot parses the root of the AST, filling in p.version, p.actions, +// and p.workflows. +func (p *Parser) parseRoot(node ast.Node) { + objectList, ok := node.(*ast.ObjectList) + if !ok { + // It should be impossible for HCL to return anything other than an + // ObjectList as the root node. This error should never happen. + p.addError(node, "Internal error: root node must be an ObjectList") + return + } + + p.actions = make([]*model.Action, 0, len(objectList.Items)) + p.workflows = make([]*model.Workflow, 0, len(objectList.Items)) + identifiers := make(map[string]bool) + for idx, item := range objectList.Items { + if item.Assign.IsValid() { + p.parseVersion(idx, item) + continue + } + p.parseBlock(item, identifiers) + } +} + +// parseBlock parses a single, top-level "action" or "workflow" block, +// appending it to p.actions or p.workflows as appropriate. +func (p *Parser) parseBlock(item *ast.ObjectItem, identifiers map[string]bool) { + if len(item.Keys) != 2 { + p.addError(item, "Invalid toplevel declaration") + return + } + + cmd := p.identString(item.Keys[0].Token) + var id string + + switch cmd { + case "action": + action := p.actionifyItem(item) + if action != nil { + id = action.Identifier + p.actions = append(p.actions, action) + } + case "workflow": + workflow := p.workflowifyItem(item) + if workflow != nil { + id = workflow.Identifier + p.workflows = append(p.workflows, workflow) + } + default: + p.addError(item, "Invalid toplevel keyword, `%s'", cmd) + return + } + + if identifiers[id] { + p.addError(item, "Identifier `%s' redefined", id) + } + + identifiers[id] = true +} + +// parseVersion parses a top-level `version=N` statement, filling in +// p.version. +func (p *Parser) parseVersion(idx int, item *ast.ObjectItem) { + if len(item.Keys) != 1 || p.identString(item.Keys[0].Token) != "version" { + // not a valid `version` declaration + p.addError(item.Val, "Toplevel declarations cannot be assignments") + return + } + if idx != 0 { + p.addError(item.Val, "`version` must be the first declaration") + return + } + version, ok := p.literalToInt(item.Val) + if !ok { + return + } + if version < minVersion || version > maxVersion { + p.addError(item.Val, "`version = %d` is not supported", version) + return + } + p.version = int(version) +} + +// parseIdentifier parses the double-quoted identifier (name) for a +// "workflow" or "action" block. +func (p *Parser) parseIdentifier(key *ast.ObjectKey) string { + id := key.Token.Text + if len(id) < 3 || id[0] != '"' || id[len(id)-1] != '"' { + p.addError(key, "Invalid format for identifier `%s'", id) + return "" + } + return id[1 : len(id)-1] +} + +// parseRequiredString parses a string value, setting its value into the +// out-parameter `value` and returning true if successful. +func (p *Parser) parseRequiredString(value *string, val ast.Node, nodeType, name, id string) bool { + if *value != "" { + p.addWarning(val, "`%s' redefined in %s `%s'", name, nodeType, id) + // continue, allowing the redefinition + } + + newVal, ok := p.literalToString(val) + if !ok { + p.addError(val, "Invalid format for `%s' in %s `%s', expected string", name, nodeType, id) + return false + } + + if newVal == "" { + p.addError(val, "`%s' value in %s `%s' cannot be blank", name, nodeType, id) + return false + } + + *value = newVal + return true +} + +// parseBlockPreamble parses the beginning of a "workflow" or "action" +// block. +func (p *Parser) parseBlockPreamble(item *ast.ObjectItem, nodeType string) (string, *ast.ObjectType) { + id := p.parseIdentifier(item.Keys[1]) + if id == "" { + return "", nil + } + + node := item.Val + obj, ok := node.(*ast.ObjectType) + if !ok { + p.addError(node, "Each %s must have an { ... } block", nodeType) + return "", nil + } + + p.checkAssignmentsOnly(obj.List, id) + + return id, obj +} + +// actionifyItem converts an AST block to an Action object. +func (p *Parser) actionifyItem(item *ast.ObjectItem) *model.Action { + id, obj := p.parseBlockPreamble(item, "action") + if obj == nil { + return nil + } + + action := &model.Action{ + Identifier: id, + } + p.posMap[action] = item + + for _, item := range obj.List.Items { + p.parseActionAttribute(p.identString(item.Keys[0].Token), action, item.Val) + } + + return action +} + +// parseActionAttribute parses a single key-value pair from an "action" +// block. This function rejects any unknown keys and enforces formatting +// requirements on all values. +// It also has higher-than-normal cyclomatic complexity, so we ask the +// gocyclo linter to ignore it. +// nolint: gocyclo +func (p *Parser) parseActionAttribute(name string, action *model.Action, val ast.Node) { + switch name { + case "uses": + p.parseUses(action, val) + case "needs": + if needs, ok := p.literalToStringArray(val, true); ok { + action.Needs = needs + p.posMap[&action.Needs] = val + } + case "runs": + if runs := p.parseCommand(action, action.Runs, name, val, false); runs != nil { + action.Runs = runs + } + case "args": + if args := p.parseCommand(action, action.Args, name, val, true); args != nil { + action.Args = args + } + case "env": + if env := p.literalToStringMap(val); env != nil { + action.Env = env + } + p.posMap[&action.Env] = val + case "secrets": + if secrets, ok := p.literalToStringArray(val, false); ok { + action.Secrets = secrets + p.posMap[&action.Secrets] = val + } + default: + p.addWarning(val, "Unknown action attribute `%s'", name) + } +} + +// parseUses sets the action.Uses value based on the contents of the AST +// node. This function enforces formatting requirements on the value. +func (p *Parser) parseUses(action *model.Action, node ast.Node) { + if action.Uses != nil { + p.addWarning(node, "`uses' redefined in action `%s'", action.Identifier) + // continue, allowing the redefinition + } + strVal, ok := p.literalToString(node) + if !ok { + return + } + + if strVal == "" { + action.Uses = &model.UsesInvalid{} + p.addError(node, "`uses' value in action `%s' cannot be blank", action.Identifier) + return + } + if strings.HasPrefix(strVal, "./") { + action.Uses = &model.UsesPath{Path: strings.TrimPrefix(strVal, "./")} + return + } + + if strings.HasPrefix(strVal, "docker://") { + action.Uses = &model.UsesDockerImage{Image: strings.TrimPrefix(strVal, "docker://")} + return + } + + tok := strings.Split(strVal, "@") + if len(tok) != 2 { + action.Uses = &model.UsesInvalid{Raw: strVal} + p.addError(node, "The `uses' attribute must be a path, a Docker image, or owner/repo@ref") + return + } + ref := tok[1] + tok = strings.SplitN(tok[0], "/", 3) + if len(tok) < 2 { + action.Uses = &model.UsesInvalid{Raw: strVal} + p.addError(node, "The `uses' attribute must be a path, a Docker image, or owner/repo@ref") + return + } + usesRepo := &model.UsesRepository{Repository: tok[0] + "/" + tok[1], Ref: ref} + action.Uses = usesRepo + if len(tok) == 3 { + usesRepo.Path = tok[2] + } +} + +// parseUses sets the action.Runs or action.Args value based on the +// contents of the AST node. This function enforces formatting +// requirements on the value. +func (p *Parser) parseCommand(action *model.Action, cmd model.Command, name string, node ast.Node, allowBlank bool) model.Command { + if cmd != nil { + p.addWarning(node, "`%s' redefined in action `%s'", name, action.Identifier) + // continue, allowing the redefinition + } + + // Is it a list? + if _, ok := node.(*ast.ListType); ok { + if parsed, ok := p.literalToStringArray(node, false); ok { + return &model.ListCommand{Values: parsed} + } + return nil + } + + // If not, parse a whitespace-separated string into a list. + var raw string + var ok bool + if raw, ok = p.literalToString(node); !ok { + p.addError(node, "The `%s' attribute must be a string or a list", name) + return nil + } + if raw == "" && !allowBlank { + p.addError(node, "`%s' value in action `%s' cannot be blank", name, action.Identifier) + return nil + } + return &model.StringCommand{Value: raw} +} + +func typename(val interface{}) string { + switch cast := val.(type) { + case *ast.ListType: + return "list" + case *ast.LiteralType: + return strings.ToLower(cast.Token.Type.String()) + case *ast.ObjectType: + return "object" + default: + return fmt.Sprintf("%T", val) + } +} + +// workflowifyItem converts an AST block to a Workflow object. +func (p *Parser) workflowifyItem(item *ast.ObjectItem) *model.Workflow { + id, obj := p.parseBlockPreamble(item, "workflow") + if obj == nil { + return nil + } + + var ok bool + workflow := &model.Workflow{Identifier: id} + for _, item := range obj.List.Items { + name := p.identString(item.Keys[0].Token) + + switch name { + case "on": + ok = p.parseRequiredString(&workflow.On, item.Val, "workflow", name, id) + if ok { + p.posMap[&workflow.On] = item + } + case "resolves": + if workflow.Resolves != nil { + p.addWarning(item.Val, "`resolves' redefined in workflow `%s'", id) + // continue, allowing the redefinition + } + workflow.Resolves, ok = p.literalToStringArray(item.Val, true) + p.posMap[&workflow.Resolves] = item + if !ok { + p.addError(item.Val, "Invalid format for `resolves' in workflow `%s', expected list of strings", id) + // continue, allowing workflow with no `resolves` + } + default: + p.addWarning(item.Val, "Unknown workflow attribute `%s'", name) + // continue, treat as no-op + } + } + + p.posMap[workflow] = item + return workflow +} + +func isAssignment(item *ast.ObjectItem) bool { + return len(item.Keys) == 1 && item.Assign.IsValid() +} + +// checkAssignmentsOnly ensures that all elements in the object are "key = +// value" pairs. +func (p *Parser) checkAssignmentsOnly(objectList *ast.ObjectList, actionID string) { + for _, item := range objectList.Items { + if !isAssignment(item) { + var desc string + if actionID == "" { + desc = "the object" + } else { + desc = fmt.Sprintf("action `%s'", actionID) + } + p.addErrorFromObjectItem(item, "Each attribute of %s must be an assignment", desc) + continue + } + + child, ok := item.Val.(*ast.ObjectType) + if ok { + p.checkAssignmentsOnly(child.List, actionID) + } + } +} + +func (p *Parser) addWarning(node ast.Node, format string, a ...interface{}) { + if p.suppressSeverity < WARNING { + p.errors = append(p.errors, newWarning(posFromNode(node), format, a...)) + } +} + +func (p *Parser) addError(node ast.Node, format string, a ...interface{}) { + if p.suppressSeverity < ERROR { + p.errors = append(p.errors, newError(posFromNode(node), format, a...)) + } +} + +func (p *Parser) addErrorFromToken(t token.Token, format string, a ...interface{}) { + if p.suppressSeverity < ERROR { + p.errors = append(p.errors, newError(posFromToken(t), format, a...)) + } +} + +func (p *Parser) addErrorFromObjectItem(objectItem *ast.ObjectItem, format string, a ...interface{}) { + if p.suppressSeverity < ERROR { + p.errors = append(p.errors, newError(posFromObjectItem(objectItem), format, a...)) + } +} + +func (p *Parser) addFatal(node ast.Node, format string, a ...interface{}) { + if p.suppressSeverity < FATAL { + p.errors = append(p.errors, newFatal(posFromNode(node), format, a...)) + } +} + +// posFromNode returns an ErrorPos (file, line, and column) from an AST +// node, so we can report specific locations for each parse error. +func posFromNode(node ast.Node) ErrorPos { + var pos *token.Pos + switch cast := node.(type) { + case *ast.ObjectList: + if len(cast.Items) > 0 { + if len(cast.Items[0].Keys) > 0 { + pos = &cast.Items[0].Keys[0].Token.Pos + } + } + case *ast.ObjectItem: + return posFromNode(cast.Val) + case *ast.ObjectType: + pos = &cast.Lbrace + case *ast.LiteralType: + pos = &cast.Token.Pos + case *ast.ListType: + pos = &cast.Lbrack + case *ast.ObjectKey: + pos = &cast.Token.Pos + } + + if pos == nil { + return ErrorPos{} + } + return ErrorPos{File: pos.Filename, Line: pos.Line, Column: pos.Column} +} + +// posFromObjectItem returns an ErrorPos from an ObjectItem. This is for +// cases where posFromNode(item) would fail because the item has no Val +// set. +func posFromObjectItem(item *ast.ObjectItem) ErrorPos { + if len(item.Keys) > 0 { + return posFromNode(item.Keys[0]) + } + return ErrorPos{} +} + +// posFromToken returns an ErrorPos from a Token. We can't use +// posFromNode here because Tokens aren't Nodes. +func posFromToken(token token.Token) ErrorPos { + return ErrorPos{File: token.Pos.Filename, Line: token.Pos.Line, Column: token.Pos.Column} +} diff --git a/vendor/github.com/emirpasic/gods/containers/enumerable.go b/vendor/github.com/emirpasic/gods/containers/enumerable.go index b0b56e4..ac48b54 100644 --- a/vendor/github.com/emirpasic/gods/containers/enumerable.go +++ b/vendor/github.com/emirpasic/gods/containers/enumerable.go @@ -11,7 +11,7 @@ type EnumerableWithIndex interface { // Map invokes the given function once for each element and returns a // container containing the values returned by the given function. - // TODO need help on how to enforce this in containers (don't want to type assert when chaining) + // TODO would appreciate help on how to enforce this in containers (don't want to type assert when chaining) // Map(func(index int, value interface{}) interface{}) Container // Select returns a new container containing all elements for which the given function returns a true value. diff --git a/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go b/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go index f9e3543..bfedac9 100644 --- a/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go +++ b/vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go @@ -11,9 +11,10 @@ package arraylist import ( "fmt" + "strings" + "github.com/emirpasic/gods/lists" "github.com/emirpasic/gods/utils" - "strings" ) func assertListImplementation() { @@ -31,9 +32,13 @@ const ( shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink) ) -// New instantiates a new empty list -func New() *List { - return &List{} +// New instantiates a new list and adds the passed values, if any, to the list +func New(values ...interface{}) *List { + list := &List{} + if len(values) > 0 { + list.Add(values...) + } + return list } // Add appends a value at the end of the list @@ -56,7 +61,7 @@ func (list *List) Get(index int) (interface{}, bool) { return list.elements[index], true } -// Remove removes one or more elements from the list with the supplied indices. +// Remove removes the element at the given index from the list. func (list *List) Remove(index int) { if !list.withinRange(index) { @@ -98,6 +103,19 @@ func (list *List) Values() []interface{} { return newElements } +//IndexOf returns index of provided element +func (list *List) IndexOf(value interface{}) int { + if list.size == 0 { + return -1 + } + for index, element := range list.elements { + if element == value { + return index + } + } + return -1 +} + // Empty returns true if list does not contain any elements. func (list *List) Empty() bool { return list.size == 0 @@ -145,14 +163,24 @@ func (list *List) Insert(index int, values ...interface{}) { l := len(values) list.growBy(l) list.size += l - // Shift old to right - for i := list.size - 1; i >= index+l; i-- { - list.elements[i] = list.elements[i-l] - } - // Insert new - for i, value := range values { - list.elements[index+i] = value + copy(list.elements[index+l:], list.elements[index:list.size-l]) + copy(list.elements[index:], values) +} + +// Set the value at specified index +// Does not do anything if position is negative or bigger than list's size +// Note: position equal to list's size is valid, i.e. append. +func (list *List) Set(index int, value interface{}) { + + if !list.withinRange(index) { + // Append + if index == list.size { + list.Add(value) + } + return } + + list.elements[index] = value } // String returns a string representation of container diff --git a/vendor/github.com/emirpasic/gods/lists/lists.go b/vendor/github.com/emirpasic/gods/lists/lists.go index 3b1d323..1f6bb08 100644 --- a/vendor/github.com/emirpasic/gods/lists/lists.go +++ b/vendor/github.com/emirpasic/gods/lists/lists.go @@ -23,6 +23,7 @@ type List interface { Sort(comparator utils.Comparator) Swap(index1, index2 int) Insert(index int, values ...interface{}) + Set(index int, value interface{}) containers.Container // Empty() bool diff --git a/vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go b/vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go index 299319b..00d0c77 100644 --- a/vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go +++ b/vendor/github.com/emirpasic/gods/trees/binaryheap/serialization.go @@ -11,12 +11,12 @@ func assertSerializationImplementation() { var _ containers.JSONDeserializer = (*Heap)(nil) } -// ToJSON outputs the JSON representation of list's elements. +// ToJSON outputs the JSON representation of the heap. func (heap *Heap) ToJSON() ([]byte, error) { return heap.list.ToJSON() } -// FromJSON populates list's elements from the input JSON representation. +// FromJSON populates the heap from the input JSON representation. func (heap *Heap) FromJSON(data []byte) error { return heap.list.FromJSON(data) } diff --git a/vendor/github.com/google/go-cmp/LICENSE b/vendor/github.com/google/go-cmp/LICENSE new file mode 100644 index 0000000..32017f8 --- /dev/null +++ b/vendor/github.com/google/go-cmp/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2017 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-cmp/cmp/compare.go b/vendor/github.com/google/go-cmp/cmp/compare.go new file mode 100644 index 0000000..7e215f2 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/compare.go @@ -0,0 +1,553 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// Package cmp determines equality of values. +// +// This package is intended to be a more powerful and safer alternative to +// reflect.DeepEqual for comparing whether two values are semantically equal. +// +// The primary features of cmp are: +// +// • When the default behavior of equality does not suit the needs of the test, +// custom equality functions can override the equality operation. +// For example, an equality function may report floats as equal so long as they +// are within some tolerance of each other. +// +// • Types that have an Equal method may use that method to determine equality. +// This allows package authors to determine the equality operation for the types +// that they define. +// +// • If no custom equality functions are used and no Equal method is defined, +// equality is determined by recursively comparing the primitive kinds on both +// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported +// fields are not compared by default; they result in panics unless suppressed +// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly compared +// using the AllowUnexported option. +package cmp + +import ( + "fmt" + "reflect" + + "github.com/google/go-cmp/cmp/internal/diff" + "github.com/google/go-cmp/cmp/internal/function" + "github.com/google/go-cmp/cmp/internal/value" +) + +// BUG(dsnet): Maps with keys containing NaN values cannot be properly compared due to +// the reflection package's inability to retrieve such entries. Equal will panic +// anytime it comes across a NaN key, but this behavior may change. +// +// See https://golang.org/issue/11104 for more details. + +var nothing = reflect.Value{} + +// Equal reports whether x and y are equal by recursively applying the +// following rules in the given order to x and y and all of their sub-values: +// +// • If two values are not of the same type, then they are never equal +// and the overall result is false. +// +// • Let S be the set of all Ignore, Transformer, and Comparer options that +// remain after applying all path filters, value filters, and type filters. +// If at least one Ignore exists in S, then the comparison is ignored. +// If the number of Transformer and Comparer options in S is greater than one, +// then Equal panics because it is ambiguous which option to use. +// If S contains a single Transformer, then use that to transform the current +// values and recursively call Equal on the output values. +// If S contains a single Comparer, then use that to compare the current values. +// Otherwise, evaluation proceeds to the next rule. +// +// • If the values have an Equal method of the form "(T) Equal(T) bool" or +// "(T) Equal(I) bool" where T is assignable to I, then use the result of +// x.Equal(y) even if x or y is nil. +// Otherwise, no such method exists and evaluation proceeds to the next rule. +// +// • Lastly, try to compare x and y based on their basic kinds. +// Simple kinds like booleans, integers, floats, complex numbers, strings, and +// channels are compared using the equivalent of the == operator in Go. +// Functions are only equal if they are both nil, otherwise they are unequal. +// Pointers are equal if the underlying values they point to are also equal. +// Interfaces are equal if their underlying concrete values are also equal. +// +// Structs are equal if all of their fields are equal. If a struct contains +// unexported fields, Equal panics unless the AllowUnexported option is used or +// an Ignore option (e.g., cmpopts.IgnoreUnexported) ignores that field. +// +// Arrays, slices, and maps are equal if they are both nil or both non-nil +// with the same length and the elements at each index or key are equal. +// Note that a non-nil empty slice and a nil slice are not equal. +// To equate empty slices and maps, consider using cmpopts.EquateEmpty. +// Map keys are equal according to the == operator. +// To use custom comparisons for map keys, consider using cmpopts.SortMaps. +func Equal(x, y interface{}, opts ...Option) bool { + s := newState(opts) + s.compareAny(reflect.ValueOf(x), reflect.ValueOf(y)) + return s.result.Equal() +} + +// Diff returns a human-readable report of the differences between two values. +// It returns an empty string if and only if Equal returns true for the same +// input values and options. The output string will use the "-" symbol to +// indicate elements removed from x, and the "+" symbol to indicate elements +// added to y. +// +// Do not depend on this output being stable. +func Diff(x, y interface{}, opts ...Option) string { + r := new(defaultReporter) + opts = Options{Options(opts), r} + eq := Equal(x, y, opts...) + d := r.String() + if (d == "") != eq { + panic("inconsistent difference and equality results") + } + return d +} + +type state struct { + // These fields represent the "comparison state". + // Calling statelessCompare must not result in observable changes to these. + result diff.Result // The current result of comparison + curPath Path // The current path in the value tree + reporter reporter // Optional reporter used for difference formatting + + // dynChecker triggers pseudo-random checks for option correctness. + // It is safe for statelessCompare to mutate this value. + dynChecker dynChecker + + // These fields, once set by processOption, will not change. + exporters map[reflect.Type]bool // Set of structs with unexported field visibility + opts Options // List of all fundamental and filter options +} + +func newState(opts []Option) *state { + s := new(state) + for _, opt := range opts { + s.processOption(opt) + } + return s +} + +func (s *state) processOption(opt Option) { + switch opt := opt.(type) { + case nil: + case Options: + for _, o := range opt { + s.processOption(o) + } + case coreOption: + type filtered interface { + isFiltered() bool + } + if fopt, ok := opt.(filtered); ok && !fopt.isFiltered() { + panic(fmt.Sprintf("cannot use an unfiltered option: %v", opt)) + } + s.opts = append(s.opts, opt) + case visibleStructs: + if s.exporters == nil { + s.exporters = make(map[reflect.Type]bool) + } + for t := range opt { + s.exporters[t] = true + } + case reporter: + if s.reporter != nil { + panic("difference reporter already registered") + } + s.reporter = opt + default: + panic(fmt.Sprintf("unknown option %T", opt)) + } +} + +// statelessCompare compares two values and returns the result. +// This function is stateless in that it does not alter the current result, +// or output to any registered reporters. +func (s *state) statelessCompare(vx, vy reflect.Value) diff.Result { + // We do not save and restore the curPath because all of the compareX + // methods should properly push and pop from the path. + // It is an implementation bug if the contents of curPath differs from + // when calling this function to when returning from it. + + oldResult, oldReporter := s.result, s.reporter + s.result = diff.Result{} // Reset result + s.reporter = nil // Remove reporter to avoid spurious printouts + s.compareAny(vx, vy) + res := s.result + s.result, s.reporter = oldResult, oldReporter + return res +} + +func (s *state) compareAny(vx, vy reflect.Value) { + // TODO: Support cyclic data structures. + + // Rule 0: Differing types are never equal. + if !vx.IsValid() || !vy.IsValid() { + s.report(vx.IsValid() == vy.IsValid(), vx, vy) + return + } + if vx.Type() != vy.Type() { + s.report(false, vx, vy) // Possible for path to be empty + return + } + t := vx.Type() + if len(s.curPath) == 0 { + s.curPath.push(&pathStep{typ: t}) + defer s.curPath.pop() + } + vx, vy = s.tryExporting(vx, vy) + + // Rule 1: Check whether an option applies on this node in the value tree. + if s.tryOptions(vx, vy, t) { + return + } + + // Rule 2: Check whether the type has a valid Equal method. + if s.tryMethod(vx, vy, t) { + return + } + + // Rule 3: Recursively descend into each value's underlying kind. + switch t.Kind() { + case reflect.Bool: + s.report(vx.Bool() == vy.Bool(), vx, vy) + return + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + s.report(vx.Int() == vy.Int(), vx, vy) + return + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + s.report(vx.Uint() == vy.Uint(), vx, vy) + return + case reflect.Float32, reflect.Float64: + s.report(vx.Float() == vy.Float(), vx, vy) + return + case reflect.Complex64, reflect.Complex128: + s.report(vx.Complex() == vy.Complex(), vx, vy) + return + case reflect.String: + s.report(vx.String() == vy.String(), vx, vy) + return + case reflect.Chan, reflect.UnsafePointer: + s.report(vx.Pointer() == vy.Pointer(), vx, vy) + return + case reflect.Func: + s.report(vx.IsNil() && vy.IsNil(), vx, vy) + return + case reflect.Ptr: + if vx.IsNil() || vy.IsNil() { + s.report(vx.IsNil() && vy.IsNil(), vx, vy) + return + } + s.curPath.push(&indirect{pathStep{t.Elem()}}) + defer s.curPath.pop() + s.compareAny(vx.Elem(), vy.Elem()) + return + case reflect.Interface: + if vx.IsNil() || vy.IsNil() { + s.report(vx.IsNil() && vy.IsNil(), vx, vy) + return + } + if vx.Elem().Type() != vy.Elem().Type() { + s.report(false, vx.Elem(), vy.Elem()) + return + } + s.curPath.push(&typeAssertion{pathStep{vx.Elem().Type()}}) + defer s.curPath.pop() + s.compareAny(vx.Elem(), vy.Elem()) + return + case reflect.Slice: + if vx.IsNil() || vy.IsNil() { + s.report(vx.IsNil() && vy.IsNil(), vx, vy) + return + } + fallthrough + case reflect.Array: + s.compareArray(vx, vy, t) + return + case reflect.Map: + s.compareMap(vx, vy, t) + return + case reflect.Struct: + s.compareStruct(vx, vy, t) + return + default: + panic(fmt.Sprintf("%v kind not handled", t.Kind())) + } +} + +func (s *state) tryExporting(vx, vy reflect.Value) (reflect.Value, reflect.Value) { + if sf, ok := s.curPath[len(s.curPath)-1].(*structField); ok && sf.unexported { + if sf.force { + // Use unsafe pointer arithmetic to get read-write access to an + // unexported field in the struct. + vx = unsafeRetrieveField(sf.pvx, sf.field) + vy = unsafeRetrieveField(sf.pvy, sf.field) + } else { + // We are not allowed to export the value, so invalidate them + // so that tryOptions can panic later if not explicitly ignored. + vx = nothing + vy = nothing + } + } + return vx, vy +} + +func (s *state) tryOptions(vx, vy reflect.Value, t reflect.Type) bool { + // If there were no FilterValues, we will not detect invalid inputs, + // so manually check for them and append invalid if necessary. + // We still evaluate the options since an ignore can override invalid. + opts := s.opts + if !vx.IsValid() || !vy.IsValid() { + opts = Options{opts, invalid{}} + } + + // Evaluate all filters and apply the remaining options. + if opt := opts.filter(s, vx, vy, t); opt != nil { + opt.apply(s, vx, vy) + return true + } + return false +} + +func (s *state) tryMethod(vx, vy reflect.Value, t reflect.Type) bool { + // Check if this type even has an Equal method. + m, ok := t.MethodByName("Equal") + if !ok || !function.IsType(m.Type, function.EqualAssignable) { + return false + } + + eq := s.callTTBFunc(m.Func, vx, vy) + s.report(eq, vx, vy) + return true +} + +func (s *state) callTRFunc(f, v reflect.Value) reflect.Value { + v = sanitizeValue(v, f.Type().In(0)) + if !s.dynChecker.Next() { + return f.Call([]reflect.Value{v})[0] + } + + // Run the function twice and ensure that we get the same results back. + // We run in goroutines so that the race detector (if enabled) can detect + // unsafe mutations to the input. + c := make(chan reflect.Value) + go detectRaces(c, f, v) + want := f.Call([]reflect.Value{v})[0] + if got := <-c; !s.statelessCompare(got, want).Equal() { + // To avoid false-positives with non-reflexive equality operations, + // we sanity check whether a value is equal to itself. + if !s.statelessCompare(want, want).Equal() { + return want + } + fn := getFuncName(f.Pointer()) + panic(fmt.Sprintf("non-deterministic function detected: %s", fn)) + } + return want +} + +func (s *state) callTTBFunc(f, x, y reflect.Value) bool { + x = sanitizeValue(x, f.Type().In(0)) + y = sanitizeValue(y, f.Type().In(1)) + if !s.dynChecker.Next() { + return f.Call([]reflect.Value{x, y})[0].Bool() + } + + // Swapping the input arguments is sufficient to check that + // f is symmetric and deterministic. + // We run in goroutines so that the race detector (if enabled) can detect + // unsafe mutations to the input. + c := make(chan reflect.Value) + go detectRaces(c, f, y, x) + want := f.Call([]reflect.Value{x, y})[0].Bool() + if got := <-c; !got.IsValid() || got.Bool() != want { + fn := getFuncName(f.Pointer()) + panic(fmt.Sprintf("non-deterministic or non-symmetric function detected: %s", fn)) + } + return want +} + +func detectRaces(c chan<- reflect.Value, f reflect.Value, vs ...reflect.Value) { + var ret reflect.Value + defer func() { + recover() // Ignore panics, let the other call to f panic instead + c <- ret + }() + ret = f.Call(vs)[0] +} + +// sanitizeValue converts nil interfaces of type T to those of type R, +// assuming that T is assignable to R. +// Otherwise, it returns the input value as is. +func sanitizeValue(v reflect.Value, t reflect.Type) reflect.Value { + // TODO(dsnet): Remove this hacky workaround. + // See https://golang.org/issue/22143 + if v.Kind() == reflect.Interface && v.IsNil() && v.Type() != t { + return reflect.New(t).Elem() + } + return v +} + +func (s *state) compareArray(vx, vy reflect.Value, t reflect.Type) { + step := &sliceIndex{pathStep{t.Elem()}, 0, 0} + s.curPath.push(step) + + // Compute an edit-script for slices vx and vy. + es := diff.Difference(vx.Len(), vy.Len(), func(ix, iy int) diff.Result { + step.xkey, step.ykey = ix, iy + return s.statelessCompare(vx.Index(ix), vy.Index(iy)) + }) + + // Report the entire slice as is if the arrays are of primitive kind, + // and the arrays are different enough. + isPrimitive := false + switch t.Elem().Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, + reflect.Bool, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: + isPrimitive = true + } + if isPrimitive && es.Dist() > (vx.Len()+vy.Len())/4 { + s.curPath.pop() // Pop first since we are reporting the whole slice + s.report(false, vx, vy) + return + } + + // Replay the edit-script. + var ix, iy int + for _, e := range es { + switch e { + case diff.UniqueX: + step.xkey, step.ykey = ix, -1 + s.report(false, vx.Index(ix), nothing) + ix++ + case diff.UniqueY: + step.xkey, step.ykey = -1, iy + s.report(false, nothing, vy.Index(iy)) + iy++ + default: + step.xkey, step.ykey = ix, iy + if e == diff.Identity { + s.report(true, vx.Index(ix), vy.Index(iy)) + } else { + s.compareAny(vx.Index(ix), vy.Index(iy)) + } + ix++ + iy++ + } + } + s.curPath.pop() + return +} + +func (s *state) compareMap(vx, vy reflect.Value, t reflect.Type) { + if vx.IsNil() || vy.IsNil() { + s.report(vx.IsNil() && vy.IsNil(), vx, vy) + return + } + + // We combine and sort the two map keys so that we can perform the + // comparisons in a deterministic order. + step := &mapIndex{pathStep: pathStep{t.Elem()}} + s.curPath.push(step) + defer s.curPath.pop() + for _, k := range value.SortKeys(append(vx.MapKeys(), vy.MapKeys()...)) { + step.key = k + vvx := vx.MapIndex(k) + vvy := vy.MapIndex(k) + switch { + case vvx.IsValid() && vvy.IsValid(): + s.compareAny(vvx, vvy) + case vvx.IsValid() && !vvy.IsValid(): + s.report(false, vvx, nothing) + case !vvx.IsValid() && vvy.IsValid(): + s.report(false, nothing, vvy) + default: + // It is possible for both vvx and vvy to be invalid if the + // key contained a NaN value in it. There is no way in + // reflection to be able to retrieve these values. + // See https://golang.org/issue/11104 + panic(fmt.Sprintf("%#v has map key with NaNs", s.curPath)) + } + } +} + +func (s *state) compareStruct(vx, vy reflect.Value, t reflect.Type) { + var vax, vay reflect.Value // Addressable versions of vx and vy + + step := &structField{} + s.curPath.push(step) + defer s.curPath.pop() + for i := 0; i < t.NumField(); i++ { + vvx := vx.Field(i) + vvy := vy.Field(i) + step.typ = t.Field(i).Type + step.name = t.Field(i).Name + step.idx = i + step.unexported = !isExported(step.name) + if step.unexported { + // Defer checking of unexported fields until later to give an + // Ignore a chance to ignore the field. + if !vax.IsValid() || !vay.IsValid() { + // For unsafeRetrieveField to work, the parent struct must + // be addressable. Create a new copy of the values if + // necessary to make them addressable. + vax = makeAddressable(vx) + vay = makeAddressable(vy) + } + step.force = s.exporters[t] + step.pvx = vax + step.pvy = vay + step.field = t.Field(i) + } + s.compareAny(vvx, vvy) + } +} + +// report records the result of a single comparison. +// It also calls Report if any reporter is registered. +func (s *state) report(eq bool, vx, vy reflect.Value) { + if eq { + s.result.NSame++ + } else { + s.result.NDiff++ + } + if s.reporter != nil { + s.reporter.Report(vx, vy, eq, s.curPath) + } +} + +// dynChecker tracks the state needed to periodically perform checks that +// user provided functions are symmetric and deterministic. +// The zero value is safe for immediate use. +type dynChecker struct{ curr, next int } + +// Next increments the state and reports whether a check should be performed. +// +// Checks occur every Nth function call, where N is a triangular number: +// 0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 ... +// See https://en.wikipedia.org/wiki/Triangular_number +// +// This sequence ensures that the cost of checks drops significantly as +// the number of functions calls grows larger. +func (dc *dynChecker) Next() bool { + ok := dc.curr == dc.next + if ok { + dc.curr = 0 + dc.next++ + } + dc.curr++ + return ok +} + +// makeAddressable returns a value that is always addressable. +// It returns the input verbatim if it is already addressable, +// otherwise it creates a new value and returns an addressable copy. +func makeAddressable(v reflect.Value) reflect.Value { + if v.CanAddr() { + return v + } + vc := reflect.New(v.Type()).Elem() + vc.Set(v) + return vc +} diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go new file mode 100644 index 0000000..42afa49 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_disable.go @@ -0,0 +1,17 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// +build !debug + +package diff + +var debug debugger + +type debugger struct{} + +func (debugger) Begin(_, _ int, f EqualFunc, _, _ *EditScript) EqualFunc { + return f +} +func (debugger) Update() {} +func (debugger) Finish() {} diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go new file mode 100644 index 0000000..fd9f7f1 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/debug_enable.go @@ -0,0 +1,122 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// +build debug + +package diff + +import ( + "fmt" + "strings" + "sync" + "time" +) + +// The algorithm can be seen running in real-time by enabling debugging: +// go test -tags=debug -v +// +// Example output: +// === RUN TestDifference/#34 +// ┌───────────────────────────────┐ +// │ \ · · · · · · · · · · · · · · │ +// │ · # · · · · · · · · · · · · · │ +// │ · \ · · · · · · · · · · · · · │ +// │ · · \ · · · · · · · · · · · · │ +// │ · · · X # · · · · · · · · · · │ +// │ · · · # \ · · · · · · · · · · │ +// │ · · · · · # # · · · · · · · · │ +// │ · · · · · # \ · · · · · · · · │ +// │ · · · · · · · \ · · · · · · · │ +// │ · · · · · · · · \ · · · · · · │ +// │ · · · · · · · · · \ · · · · · │ +// │ · · · · · · · · · · \ · · # · │ +// │ · · · · · · · · · · · \ # # · │ +// │ · · · · · · · · · · · # # # · │ +// │ · · · · · · · · · · # # # # · │ +// │ · · · · · · · · · # # # # # · │ +// │ · · · · · · · · · · · · · · \ │ +// └───────────────────────────────┘ +// [.Y..M.XY......YXYXY.|] +// +// The grid represents the edit-graph where the horizontal axis represents +// list X and the vertical axis represents list Y. The start of the two lists +// is the top-left, while the ends are the bottom-right. The '·' represents +// an unexplored node in the graph. The '\' indicates that the two symbols +// from list X and Y are equal. The 'X' indicates that two symbols are similar +// (but not exactly equal) to each other. The '#' indicates that the two symbols +// are different (and not similar). The algorithm traverses this graph trying to +// make the paths starting in the top-left and the bottom-right connect. +// +// The series of '.', 'X', 'Y', and 'M' characters at the bottom represents +// the currently established path from the forward and reverse searches, +// separated by a '|' character. + +const ( + updateDelay = 100 * time.Millisecond + finishDelay = 500 * time.Millisecond + ansiTerminal = true // ANSI escape codes used to move terminal cursor +) + +var debug debugger + +type debugger struct { + sync.Mutex + p1, p2 EditScript + fwdPath, revPath *EditScript + grid []byte + lines int +} + +func (dbg *debugger) Begin(nx, ny int, f EqualFunc, p1, p2 *EditScript) EqualFunc { + dbg.Lock() + dbg.fwdPath, dbg.revPath = p1, p2 + top := "┌─" + strings.Repeat("──", nx) + "┐\n" + row := "│ " + strings.Repeat("· ", nx) + "│\n" + btm := "└─" + strings.Repeat("──", nx) + "┘\n" + dbg.grid = []byte(top + strings.Repeat(row, ny) + btm) + dbg.lines = strings.Count(dbg.String(), "\n") + fmt.Print(dbg) + + // Wrap the EqualFunc so that we can intercept each result. + return func(ix, iy int) (r Result) { + cell := dbg.grid[len(top)+iy*len(row):][len("│ ")+len("· ")*ix:][:len("·")] + for i := range cell { + cell[i] = 0 // Zero out the multiple bytes of UTF-8 middle-dot + } + switch r = f(ix, iy); { + case r.Equal(): + cell[0] = '\\' + case r.Similar(): + cell[0] = 'X' + default: + cell[0] = '#' + } + return + } +} + +func (dbg *debugger) Update() { + dbg.print(updateDelay) +} + +func (dbg *debugger) Finish() { + dbg.print(finishDelay) + dbg.Unlock() +} + +func (dbg *debugger) String() string { + dbg.p1, dbg.p2 = *dbg.fwdPath, dbg.p2[:0] + for i := len(*dbg.revPath) - 1; i >= 0; i-- { + dbg.p2 = append(dbg.p2, (*dbg.revPath)[i]) + } + return fmt.Sprintf("%s[%v|%v]\n\n", dbg.grid, dbg.p1, dbg.p2) +} + +func (dbg *debugger) print(d time.Duration) { + if ansiTerminal { + fmt.Printf("\x1b[%dA", dbg.lines) // Reset terminal cursor + } + fmt.Print(dbg) + time.Sleep(d) +} diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go new file mode 100644 index 0000000..260befe --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go @@ -0,0 +1,363 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// Package diff implements an algorithm for producing edit-scripts. +// The edit-script is a sequence of operations needed to transform one list +// of symbols into another (or vice-versa). The edits allowed are insertions, +// deletions, and modifications. The summation of all edits is called the +// Levenshtein distance as this problem is well-known in computer science. +// +// This package prioritizes performance over accuracy. That is, the run time +// is more important than obtaining a minimal Levenshtein distance. +package diff + +// EditType represents a single operation within an edit-script. +type EditType uint8 + +const ( + // Identity indicates that a symbol pair is identical in both list X and Y. + Identity EditType = iota + // UniqueX indicates that a symbol only exists in X and not Y. + UniqueX + // UniqueY indicates that a symbol only exists in Y and not X. + UniqueY + // Modified indicates that a symbol pair is a modification of each other. + Modified +) + +// EditScript represents the series of differences between two lists. +type EditScript []EditType + +// String returns a human-readable string representing the edit-script where +// Identity, UniqueX, UniqueY, and Modified are represented by the +// '.', 'X', 'Y', and 'M' characters, respectively. +func (es EditScript) String() string { + b := make([]byte, len(es)) + for i, e := range es { + switch e { + case Identity: + b[i] = '.' + case UniqueX: + b[i] = 'X' + case UniqueY: + b[i] = 'Y' + case Modified: + b[i] = 'M' + default: + panic("invalid edit-type") + } + } + return string(b) +} + +// stats returns a histogram of the number of each type of edit operation. +func (es EditScript) stats() (s struct{ NI, NX, NY, NM int }) { + for _, e := range es { + switch e { + case Identity: + s.NI++ + case UniqueX: + s.NX++ + case UniqueY: + s.NY++ + case Modified: + s.NM++ + default: + panic("invalid edit-type") + } + } + return +} + +// Dist is the Levenshtein distance and is guaranteed to be 0 if and only if +// lists X and Y are equal. +func (es EditScript) Dist() int { return len(es) - es.stats().NI } + +// LenX is the length of the X list. +func (es EditScript) LenX() int { return len(es) - es.stats().NY } + +// LenY is the length of the Y list. +func (es EditScript) LenY() int { return len(es) - es.stats().NX } + +// EqualFunc reports whether the symbols at indexes ix and iy are equal. +// When called by Difference, the index is guaranteed to be within nx and ny. +type EqualFunc func(ix int, iy int) Result + +// Result is the result of comparison. +// NSame is the number of sub-elements that are equal. +// NDiff is the number of sub-elements that are not equal. +type Result struct{ NSame, NDiff int } + +// Equal indicates whether the symbols are equal. Two symbols are equal +// if and only if NDiff == 0. If Equal, then they are also Similar. +func (r Result) Equal() bool { return r.NDiff == 0 } + +// Similar indicates whether two symbols are similar and may be represented +// by using the Modified type. As a special case, we consider binary comparisons +// (i.e., those that return Result{1, 0} or Result{0, 1}) to be similar. +// +// The exact ratio of NSame to NDiff to determine similarity may change. +func (r Result) Similar() bool { + // Use NSame+1 to offset NSame so that binary comparisons are similar. + return r.NSame+1 >= r.NDiff +} + +// Difference reports whether two lists of lengths nx and ny are equal +// given the definition of equality provided as f. +// +// This function returns an edit-script, which is a sequence of operations +// needed to convert one list into the other. The following invariants for +// the edit-script are maintained: +// • eq == (es.Dist()==0) +// • nx == es.LenX() +// • ny == es.LenY() +// +// This algorithm is not guaranteed to be an optimal solution (i.e., one that +// produces an edit-script with a minimal Levenshtein distance). This algorithm +// favors performance over optimality. The exact output is not guaranteed to +// be stable and may change over time. +func Difference(nx, ny int, f EqualFunc) (es EditScript) { + // This algorithm is based on traversing what is known as an "edit-graph". + // See Figure 1 from "An O(ND) Difference Algorithm and Its Variations" + // by Eugene W. Myers. Since D can be as large as N itself, this is + // effectively O(N^2). Unlike the algorithm from that paper, we are not + // interested in the optimal path, but at least some "decent" path. + // + // For example, let X and Y be lists of symbols: + // X = [A B C A B B A] + // Y = [C B A B A C] + // + // The edit-graph can be drawn as the following: + // A B C A B B A + // ┌─────────────┐ + // C │_|_|\|_|_|_|_│ 0 + // B │_|\|_|_|\|\|_│ 1 + // A │\|_|_|\|_|_|\│ 2 + // B │_|\|_|_|\|\|_│ 3 + // A │\|_|_|\|_|_|\│ 4 + // C │ | |\| | | | │ 5 + // └─────────────┘ 6 + // 0 1 2 3 4 5 6 7 + // + // List X is written along the horizontal axis, while list Y is written + // along the vertical axis. At any point on this grid, if the symbol in + // list X matches the corresponding symbol in list Y, then a '\' is drawn. + // The goal of any minimal edit-script algorithm is to find a path from the + // top-left corner to the bottom-right corner, while traveling through the + // fewest horizontal or vertical edges. + // A horizontal edge is equivalent to inserting a symbol from list X. + // A vertical edge is equivalent to inserting a symbol from list Y. + // A diagonal edge is equivalent to a matching symbol between both X and Y. + + // Invariants: + // • 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx + // • 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny + // + // In general: + // • fwdFrontier.X < revFrontier.X + // • fwdFrontier.Y < revFrontier.Y + // Unless, it is time for the algorithm to terminate. + fwdPath := path{+1, point{0, 0}, make(EditScript, 0, (nx+ny)/2)} + revPath := path{-1, point{nx, ny}, make(EditScript, 0)} + fwdFrontier := fwdPath.point // Forward search frontier + revFrontier := revPath.point // Reverse search frontier + + // Search budget bounds the cost of searching for better paths. + // The longest sequence of non-matching symbols that can be tolerated is + // approximately the square-root of the search budget. + searchBudget := 4 * (nx + ny) // O(n) + + // The algorithm below is a greedy, meet-in-the-middle algorithm for + // computing sub-optimal edit-scripts between two lists. + // + // The algorithm is approximately as follows: + // • Searching for differences switches back-and-forth between + // a search that starts at the beginning (the top-left corner), and + // a search that starts at the end (the bottom-right corner). The goal of + // the search is connect with the search from the opposite corner. + // • As we search, we build a path in a greedy manner, where the first + // match seen is added to the path (this is sub-optimal, but provides a + // decent result in practice). When matches are found, we try the next pair + // of symbols in the lists and follow all matches as far as possible. + // • When searching for matches, we search along a diagonal going through + // through the "frontier" point. If no matches are found, we advance the + // frontier towards the opposite corner. + // • This algorithm terminates when either the X coordinates or the + // Y coordinates of the forward and reverse frontier points ever intersect. + // + // This algorithm is correct even if searching only in the forward direction + // or in the reverse direction. We do both because it is commonly observed + // that two lists commonly differ because elements were added to the front + // or end of the other list. + // + // Running the tests with the "debug" build tag prints a visualization of + // the algorithm running in real-time. This is educational for understanding + // how the algorithm works. See debug_enable.go. + f = debug.Begin(nx, ny, f, &fwdPath.es, &revPath.es) + for { + // Forward search from the beginning. + if fwdFrontier.X >= revFrontier.X || fwdFrontier.Y >= revFrontier.Y || searchBudget == 0 { + break + } + for stop1, stop2, i := false, false, 0; !(stop1 && stop2) && searchBudget > 0; i++ { + // Search in a diagonal pattern for a match. + z := zigzag(i) + p := point{fwdFrontier.X + z, fwdFrontier.Y - z} + switch { + case p.X >= revPath.X || p.Y < fwdPath.Y: + stop1 = true // Hit top-right corner + case p.Y >= revPath.Y || p.X < fwdPath.X: + stop2 = true // Hit bottom-left corner + case f(p.X, p.Y).Equal(): + // Match found, so connect the path to this point. + fwdPath.connect(p, f) + fwdPath.append(Identity) + // Follow sequence of matches as far as possible. + for fwdPath.X < revPath.X && fwdPath.Y < revPath.Y { + if !f(fwdPath.X, fwdPath.Y).Equal() { + break + } + fwdPath.append(Identity) + } + fwdFrontier = fwdPath.point + stop1, stop2 = true, true + default: + searchBudget-- // Match not found + } + debug.Update() + } + // Advance the frontier towards reverse point. + if revPath.X-fwdFrontier.X >= revPath.Y-fwdFrontier.Y { + fwdFrontier.X++ + } else { + fwdFrontier.Y++ + } + + // Reverse search from the end. + if fwdFrontier.X >= revFrontier.X || fwdFrontier.Y >= revFrontier.Y || searchBudget == 0 { + break + } + for stop1, stop2, i := false, false, 0; !(stop1 && stop2) && searchBudget > 0; i++ { + // Search in a diagonal pattern for a match. + z := zigzag(i) + p := point{revFrontier.X - z, revFrontier.Y + z} + switch { + case fwdPath.X >= p.X || revPath.Y < p.Y: + stop1 = true // Hit bottom-left corner + case fwdPath.Y >= p.Y || revPath.X < p.X: + stop2 = true // Hit top-right corner + case f(p.X-1, p.Y-1).Equal(): + // Match found, so connect the path to this point. + revPath.connect(p, f) + revPath.append(Identity) + // Follow sequence of matches as far as possible. + for fwdPath.X < revPath.X && fwdPath.Y < revPath.Y { + if !f(revPath.X-1, revPath.Y-1).Equal() { + break + } + revPath.append(Identity) + } + revFrontier = revPath.point + stop1, stop2 = true, true + default: + searchBudget-- // Match not found + } + debug.Update() + } + // Advance the frontier towards forward point. + if revFrontier.X-fwdPath.X >= revFrontier.Y-fwdPath.Y { + revFrontier.X-- + } else { + revFrontier.Y-- + } + } + + // Join the forward and reverse paths and then append the reverse path. + fwdPath.connect(revPath.point, f) + for i := len(revPath.es) - 1; i >= 0; i-- { + t := revPath.es[i] + revPath.es = revPath.es[:i] + fwdPath.append(t) + } + debug.Finish() + return fwdPath.es +} + +type path struct { + dir int // +1 if forward, -1 if reverse + point // Leading point of the EditScript path + es EditScript +} + +// connect appends any necessary Identity, Modified, UniqueX, or UniqueY types +// to the edit-script to connect p.point to dst. +func (p *path) connect(dst point, f EqualFunc) { + if p.dir > 0 { + // Connect in forward direction. + for dst.X > p.X && dst.Y > p.Y { + switch r := f(p.X, p.Y); { + case r.Equal(): + p.append(Identity) + case r.Similar(): + p.append(Modified) + case dst.X-p.X >= dst.Y-p.Y: + p.append(UniqueX) + default: + p.append(UniqueY) + } + } + for dst.X > p.X { + p.append(UniqueX) + } + for dst.Y > p.Y { + p.append(UniqueY) + } + } else { + // Connect in reverse direction. + for p.X > dst.X && p.Y > dst.Y { + switch r := f(p.X-1, p.Y-1); { + case r.Equal(): + p.append(Identity) + case r.Similar(): + p.append(Modified) + case p.Y-dst.Y >= p.X-dst.X: + p.append(UniqueY) + default: + p.append(UniqueX) + } + } + for p.X > dst.X { + p.append(UniqueX) + } + for p.Y > dst.Y { + p.append(UniqueY) + } + } +} + +func (p *path) append(t EditType) { + p.es = append(p.es, t) + switch t { + case Identity, Modified: + p.add(p.dir, p.dir) + case UniqueX: + p.add(p.dir, 0) + case UniqueY: + p.add(0, p.dir) + } + debug.Update() +} + +type point struct{ X, Y int } + +func (p *point) add(dx, dy int) { p.X += dx; p.Y += dy } + +// zigzag maps a consecutive sequence of integers to a zig-zag sequence. +// [0 1 2 3 4 5 ...] => [0 -1 +1 -2 +2 ...] +func zigzag(x int) int { + if x&1 != 0 { + x = ^x + } + return x >> 1 +} diff --git a/vendor/github.com/google/go-cmp/cmp/internal/function/func.go b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go new file mode 100644 index 0000000..4c35ff1 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/internal/function/func.go @@ -0,0 +1,49 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// Package function identifies function types. +package function + +import "reflect" + +type funcType int + +const ( + _ funcType = iota + + ttbFunc // func(T, T) bool + tibFunc // func(T, I) bool + trFunc // func(T) R + + Equal = ttbFunc // func(T, T) bool + EqualAssignable = tibFunc // func(T, I) bool; encapsulates func(T, T) bool + Transformer = trFunc // func(T) R + ValueFilter = ttbFunc // func(T, T) bool + Less = ttbFunc // func(T, T) bool +) + +var boolType = reflect.TypeOf(true) + +// IsType reports whether the reflect.Type is of the specified function type. +func IsType(t reflect.Type, ft funcType) bool { + if t == nil || t.Kind() != reflect.Func || t.IsVariadic() { + return false + } + ni, no := t.NumIn(), t.NumOut() + switch ft { + case ttbFunc: // func(T, T) bool + if ni == 2 && no == 1 && t.In(0) == t.In(1) && t.Out(0) == boolType { + return true + } + case tibFunc: // func(T, I) bool + if ni == 2 && no == 1 && t.In(0).AssignableTo(t.In(1)) && t.Out(0) == boolType { + return true + } + case trFunc: // func(T) R + if ni == 1 && no == 1 { + return true + } + } + return false +} diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/format.go b/vendor/github.com/google/go-cmp/cmp/internal/value/format.go new file mode 100644 index 0000000..657e508 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/internal/value/format.go @@ -0,0 +1,277 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// Package value provides functionality for reflect.Value types. +package value + +import ( + "fmt" + "reflect" + "strconv" + "strings" + "unicode" +) + +var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + +// Format formats the value v as a string. +// +// This is similar to fmt.Sprintf("%+v", v) except this: +// * Prints the type unless it can be elided +// * Avoids printing struct fields that are zero +// * Prints a nil-slice as being nil, not empty +// * Prints map entries in deterministic order +func Format(v reflect.Value, conf FormatConfig) string { + conf.printType = true + conf.followPointers = true + conf.realPointers = true + return formatAny(v, conf, nil) +} + +type FormatConfig struct { + UseStringer bool // Should the String method be used if available? + printType bool // Should we print the type before the value? + PrintPrimitiveType bool // Should we print the type of primitives? + followPointers bool // Should we recursively follow pointers? + realPointers bool // Should we print the real address of pointers? +} + +func formatAny(v reflect.Value, conf FormatConfig, visited map[uintptr]bool) string { + // TODO: Should this be a multi-line printout in certain situations? + + if !v.IsValid() { + return "" + } + if conf.UseStringer && v.Type().Implements(stringerIface) && v.CanInterface() { + if (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && v.IsNil() { + return "" + } + + const stringerPrefix = "s" // Indicates that the String method was used + s := v.Interface().(fmt.Stringer).String() + return stringerPrefix + formatString(s) + } + + switch v.Kind() { + case reflect.Bool: + return formatPrimitive(v.Type(), v.Bool(), conf) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return formatPrimitive(v.Type(), v.Int(), conf) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + if v.Type().PkgPath() == "" || v.Kind() == reflect.Uintptr { + // Unnamed uints are usually bytes or words, so use hexadecimal. + return formatPrimitive(v.Type(), formatHex(v.Uint()), conf) + } + return formatPrimitive(v.Type(), v.Uint(), conf) + case reflect.Float32, reflect.Float64: + return formatPrimitive(v.Type(), v.Float(), conf) + case reflect.Complex64, reflect.Complex128: + return formatPrimitive(v.Type(), v.Complex(), conf) + case reflect.String: + return formatPrimitive(v.Type(), formatString(v.String()), conf) + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + return formatPointer(v, conf) + case reflect.Ptr: + if v.IsNil() { + if conf.printType { + return fmt.Sprintf("(%v)(nil)", v.Type()) + } + return "" + } + if visited[v.Pointer()] || !conf.followPointers { + return formatPointer(v, conf) + } + visited = insertPointer(visited, v.Pointer()) + return "&" + formatAny(v.Elem(), conf, visited) + case reflect.Interface: + if v.IsNil() { + if conf.printType { + return fmt.Sprintf("%v(nil)", v.Type()) + } + return "" + } + return formatAny(v.Elem(), conf, visited) + case reflect.Slice: + if v.IsNil() { + if conf.printType { + return fmt.Sprintf("%v(nil)", v.Type()) + } + return "" + } + if visited[v.Pointer()] { + return formatPointer(v, conf) + } + visited = insertPointer(visited, v.Pointer()) + fallthrough + case reflect.Array: + var ss []string + subConf := conf + subConf.printType = v.Type().Elem().Kind() == reflect.Interface + for i := 0; i < v.Len(); i++ { + s := formatAny(v.Index(i), subConf, visited) + ss = append(ss, s) + } + s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) + if conf.printType { + return v.Type().String() + s + } + return s + case reflect.Map: + if v.IsNil() { + if conf.printType { + return fmt.Sprintf("%v(nil)", v.Type()) + } + return "" + } + if visited[v.Pointer()] { + return formatPointer(v, conf) + } + visited = insertPointer(visited, v.Pointer()) + + var ss []string + keyConf, valConf := conf, conf + keyConf.printType = v.Type().Key().Kind() == reflect.Interface + keyConf.followPointers = false + valConf.printType = v.Type().Elem().Kind() == reflect.Interface + for _, k := range SortKeys(v.MapKeys()) { + sk := formatAny(k, keyConf, visited) + sv := formatAny(v.MapIndex(k), valConf, visited) + ss = append(ss, fmt.Sprintf("%s: %s", sk, sv)) + } + s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) + if conf.printType { + return v.Type().String() + s + } + return s + case reflect.Struct: + var ss []string + subConf := conf + subConf.printType = true + for i := 0; i < v.NumField(); i++ { + vv := v.Field(i) + if isZero(vv) { + continue // Elide zero value fields + } + name := v.Type().Field(i).Name + subConf.UseStringer = conf.UseStringer + s := formatAny(vv, subConf, visited) + ss = append(ss, fmt.Sprintf("%s: %s", name, s)) + } + s := fmt.Sprintf("{%s}", strings.Join(ss, ", ")) + if conf.printType { + return v.Type().String() + s + } + return s + default: + panic(fmt.Sprintf("%v kind not handled", v.Kind())) + } +} + +func formatString(s string) string { + // Use quoted string if it the same length as a raw string literal. + // Otherwise, attempt to use the raw string form. + qs := strconv.Quote(s) + if len(qs) == 1+len(s)+1 { + return qs + } + + // Disallow newlines to ensure output is a single line. + // Only allow printable runes for readability purposes. + rawInvalid := func(r rune) bool { + return r == '`' || r == '\n' || !unicode.IsPrint(r) + } + if strings.IndexFunc(s, rawInvalid) < 0 { + return "`" + s + "`" + } + return qs +} + +func formatPrimitive(t reflect.Type, v interface{}, conf FormatConfig) string { + if conf.printType && (conf.PrintPrimitiveType || t.PkgPath() != "") { + return fmt.Sprintf("%v(%v)", t, v) + } + return fmt.Sprintf("%v", v) +} + +func formatPointer(v reflect.Value, conf FormatConfig) string { + p := v.Pointer() + if !conf.realPointers { + p = 0 // For deterministic printing purposes + } + s := formatHex(uint64(p)) + if conf.printType { + return fmt.Sprintf("(%v)(%s)", v.Type(), s) + } + return s +} + +func formatHex(u uint64) string { + var f string + switch { + case u <= 0xff: + f = "0x%02x" + case u <= 0xffff: + f = "0x%04x" + case u <= 0xffffff: + f = "0x%06x" + case u <= 0xffffffff: + f = "0x%08x" + case u <= 0xffffffffff: + f = "0x%010x" + case u <= 0xffffffffffff: + f = "0x%012x" + case u <= 0xffffffffffffff: + f = "0x%014x" + case u <= 0xffffffffffffffff: + f = "0x%016x" + } + return fmt.Sprintf(f, u) +} + +// insertPointer insert p into m, allocating m if necessary. +func insertPointer(m map[uintptr]bool, p uintptr) map[uintptr]bool { + if m == nil { + m = make(map[uintptr]bool) + } + m[p] = true + return m +} + +// isZero reports whether v is the zero value. +// This does not rely on Interface and so can be used on unexported fields. +func isZero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return v.Bool() == false + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() == 0 + case reflect.String: + return v.String() == "" + case reflect.UnsafePointer: + return v.Pointer() == 0 + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + return v.IsNil() + case reflect.Array: + for i := 0; i < v.Len(); i++ { + if !isZero(v.Index(i)) { + return false + } + } + return true + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + if !isZero(v.Field(i)) { + return false + } + } + return true + } + return false +} diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/sort.go b/vendor/github.com/google/go-cmp/cmp/internal/value/sort.go new file mode 100644 index 0000000..fe8aa27 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/internal/value/sort.go @@ -0,0 +1,111 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +package value + +import ( + "fmt" + "math" + "reflect" + "sort" +) + +// SortKeys sorts a list of map keys, deduplicating keys if necessary. +// The type of each value must be comparable. +func SortKeys(vs []reflect.Value) []reflect.Value { + if len(vs) == 0 { + return vs + } + + // Sort the map keys. + sort.Sort(valueSorter(vs)) + + // Deduplicate keys (fails for NaNs). + vs2 := vs[:1] + for _, v := range vs[1:] { + if isLess(vs2[len(vs2)-1], v) { + vs2 = append(vs2, v) + } + } + return vs2 +} + +// TODO: Use sort.Slice once Google AppEngine is on Go1.8 or above. +type valueSorter []reflect.Value + +func (vs valueSorter) Len() int { return len(vs) } +func (vs valueSorter) Less(i, j int) bool { return isLess(vs[i], vs[j]) } +func (vs valueSorter) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] } + +// isLess is a generic function for sorting arbitrary map keys. +// The inputs must be of the same type and must be comparable. +func isLess(x, y reflect.Value) bool { + switch x.Type().Kind() { + case reflect.Bool: + return !x.Bool() && y.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return x.Int() < y.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return x.Uint() < y.Uint() + case reflect.Float32, reflect.Float64: + fx, fy := x.Float(), y.Float() + return fx < fy || math.IsNaN(fx) && !math.IsNaN(fy) + case reflect.Complex64, reflect.Complex128: + cx, cy := x.Complex(), y.Complex() + rx, ix, ry, iy := real(cx), imag(cx), real(cy), imag(cy) + if rx == ry || (math.IsNaN(rx) && math.IsNaN(ry)) { + return ix < iy || math.IsNaN(ix) && !math.IsNaN(iy) + } + return rx < ry || math.IsNaN(rx) && !math.IsNaN(ry) + case reflect.Ptr, reflect.UnsafePointer, reflect.Chan: + return x.Pointer() < y.Pointer() + case reflect.String: + return x.String() < y.String() + case reflect.Array: + for i := 0; i < x.Len(); i++ { + if isLess(x.Index(i), y.Index(i)) { + return true + } + if isLess(y.Index(i), x.Index(i)) { + return false + } + } + return false + case reflect.Struct: + for i := 0; i < x.NumField(); i++ { + if isLess(x.Field(i), y.Field(i)) { + return true + } + if isLess(y.Field(i), x.Field(i)) { + return false + } + } + return false + case reflect.Interface: + vx, vy := x.Elem(), y.Elem() + if !vx.IsValid() || !vy.IsValid() { + return !vx.IsValid() && vy.IsValid() + } + tx, ty := vx.Type(), vy.Type() + if tx == ty { + return isLess(x.Elem(), y.Elem()) + } + if tx.Kind() != ty.Kind() { + return vx.Kind() < vy.Kind() + } + if tx.String() != ty.String() { + return tx.String() < ty.String() + } + if tx.PkgPath() != ty.PkgPath() { + return tx.PkgPath() < ty.PkgPath() + } + // This can happen in rare situations, so we fallback to just comparing + // the unique pointer for a reflect.Type. This guarantees deterministic + // ordering within a program, but it is obviously not stable. + return reflect.ValueOf(vx.Type()).Pointer() < reflect.ValueOf(vy.Type()).Pointer() + default: + // Must be Func, Map, or Slice; which are not comparable. + panic(fmt.Sprintf("%T is not comparable", x.Type())) + } +} diff --git a/vendor/github.com/google/go-cmp/cmp/options.go b/vendor/github.com/google/go-cmp/cmp/options.go new file mode 100644 index 0000000..91d4b06 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/options.go @@ -0,0 +1,453 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +package cmp + +import ( + "fmt" + "reflect" + "runtime" + "strings" + + "github.com/google/go-cmp/cmp/internal/function" +) + +// Option configures for specific behavior of Equal and Diff. In particular, +// the fundamental Option functions (Ignore, Transformer, and Comparer), +// configure how equality is determined. +// +// The fundamental options may be composed with filters (FilterPath and +// FilterValues) to control the scope over which they are applied. +// +// The cmp/cmpopts package provides helper functions for creating options that +// may be used with Equal and Diff. +type Option interface { + // filter applies all filters and returns the option that remains. + // Each option may only read s.curPath and call s.callTTBFunc. + // + // An Options is returned only if multiple comparers or transformers + // can apply simultaneously and will only contain values of those types + // or sub-Options containing values of those types. + filter(s *state, vx, vy reflect.Value, t reflect.Type) applicableOption +} + +// applicableOption represents the following types: +// Fundamental: ignore | invalid | *comparer | *transformer +// Grouping: Options +type applicableOption interface { + Option + + // apply executes the option, which may mutate s or panic. + apply(s *state, vx, vy reflect.Value) +} + +// coreOption represents the following types: +// Fundamental: ignore | invalid | *comparer | *transformer +// Filters: *pathFilter | *valuesFilter +type coreOption interface { + Option + isCore() +} + +type core struct{} + +func (core) isCore() {} + +// Options is a list of Option values that also satisfies the Option interface. +// Helper comparison packages may return an Options value when packing multiple +// Option values into a single Option. When this package processes an Options, +// it will be implicitly expanded into a flat list. +// +// Applying a filter on an Options is equivalent to applying that same filter +// on all individual options held within. +type Options []Option + +func (opts Options) filter(s *state, vx, vy reflect.Value, t reflect.Type) (out applicableOption) { + for _, opt := range opts { + switch opt := opt.filter(s, vx, vy, t); opt.(type) { + case ignore: + return ignore{} // Only ignore can short-circuit evaluation + case invalid: + out = invalid{} // Takes precedence over comparer or transformer + case *comparer, *transformer, Options: + switch out.(type) { + case nil: + out = opt + case invalid: + // Keep invalid + case *comparer, *transformer, Options: + out = Options{out, opt} // Conflicting comparers or transformers + } + } + } + return out +} + +func (opts Options) apply(s *state, _, _ reflect.Value) { + const warning = "ambiguous set of applicable options" + const help = "consider using filters to ensure at most one Comparer or Transformer may apply" + var ss []string + for _, opt := range flattenOptions(nil, opts) { + ss = append(ss, fmt.Sprint(opt)) + } + set := strings.Join(ss, "\n\t") + panic(fmt.Sprintf("%s at %#v:\n\t%s\n%s", warning, s.curPath, set, help)) +} + +func (opts Options) String() string { + var ss []string + for _, opt := range opts { + ss = append(ss, fmt.Sprint(opt)) + } + return fmt.Sprintf("Options{%s}", strings.Join(ss, ", ")) +} + +// FilterPath returns a new Option where opt is only evaluated if filter f +// returns true for the current Path in the value tree. +// +// The option passed in may be an Ignore, Transformer, Comparer, Options, or +// a previously filtered Option. +func FilterPath(f func(Path) bool, opt Option) Option { + if f == nil { + panic("invalid path filter function") + } + if opt := normalizeOption(opt); opt != nil { + return &pathFilter{fnc: f, opt: opt} + } + return nil +} + +type pathFilter struct { + core + fnc func(Path) bool + opt Option +} + +func (f pathFilter) filter(s *state, vx, vy reflect.Value, t reflect.Type) applicableOption { + if f.fnc(s.curPath) { + return f.opt.filter(s, vx, vy, t) + } + return nil +} + +func (f pathFilter) String() string { + fn := getFuncName(reflect.ValueOf(f.fnc).Pointer()) + return fmt.Sprintf("FilterPath(%s, %v)", fn, f.opt) +} + +// FilterValues returns a new Option where opt is only evaluated if filter f, +// which is a function of the form "func(T, T) bool", returns true for the +// current pair of values being compared. If the type of the values is not +// assignable to T, then this filter implicitly returns false. +// +// The filter function must be +// symmetric (i.e., agnostic to the order of the inputs) and +// deterministic (i.e., produces the same result when given the same inputs). +// If T is an interface, it is possible that f is called with two values with +// different concrete types that both implement T. +// +// The option passed in may be an Ignore, Transformer, Comparer, Options, or +// a previously filtered Option. +func FilterValues(f interface{}, opt Option) Option { + v := reflect.ValueOf(f) + if !function.IsType(v.Type(), function.ValueFilter) || v.IsNil() { + panic(fmt.Sprintf("invalid values filter function: %T", f)) + } + if opt := normalizeOption(opt); opt != nil { + vf := &valuesFilter{fnc: v, opt: opt} + if ti := v.Type().In(0); ti.Kind() != reflect.Interface || ti.NumMethod() > 0 { + vf.typ = ti + } + return vf + } + return nil +} + +type valuesFilter struct { + core + typ reflect.Type // T + fnc reflect.Value // func(T, T) bool + opt Option +} + +func (f valuesFilter) filter(s *state, vx, vy reflect.Value, t reflect.Type) applicableOption { + if !vx.IsValid() || !vy.IsValid() { + return invalid{} + } + if (f.typ == nil || t.AssignableTo(f.typ)) && s.callTTBFunc(f.fnc, vx, vy) { + return f.opt.filter(s, vx, vy, t) + } + return nil +} + +func (f valuesFilter) String() string { + fn := getFuncName(f.fnc.Pointer()) + return fmt.Sprintf("FilterValues(%s, %v)", fn, f.opt) +} + +// Ignore is an Option that causes all comparisons to be ignored. +// This value is intended to be combined with FilterPath or FilterValues. +// It is an error to pass an unfiltered Ignore option to Equal. +func Ignore() Option { return ignore{} } + +type ignore struct{ core } + +func (ignore) isFiltered() bool { return false } +func (ignore) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return ignore{} } +func (ignore) apply(_ *state, _, _ reflect.Value) { return } +func (ignore) String() string { return "Ignore()" } + +// invalid is a sentinel Option type to indicate that some options could not +// be evaluated due to unexported fields. +type invalid struct{ core } + +func (invalid) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { return invalid{} } +func (invalid) apply(s *state, _, _ reflect.Value) { + const help = "consider using AllowUnexported or cmpopts.IgnoreUnexported" + panic(fmt.Sprintf("cannot handle unexported field: %#v\n%s", s.curPath, help)) +} + +// Transformer returns an Option that applies a transformation function that +// converts values of a certain type into that of another. +// +// The transformer f must be a function "func(T) R" that converts values of +// type T to those of type R and is implicitly filtered to input values +// assignable to T. The transformer must not mutate T in any way. +// +// To help prevent some cases of infinite recursive cycles applying the +// same transform to the output of itself (e.g., in the case where the +// input and output types are the same), an implicit filter is added such that +// a transformer is applicable only if that exact transformer is not already +// in the tail of the Path since the last non-Transform step. +// +// The name is a user provided label that is used as the Transform.Name in the +// transformation PathStep. If empty, an arbitrary name is used. +func Transformer(name string, f interface{}) Option { + v := reflect.ValueOf(f) + if !function.IsType(v.Type(), function.Transformer) || v.IsNil() { + panic(fmt.Sprintf("invalid transformer function: %T", f)) + } + if name == "" { + name = "λ" // Lambda-symbol as place-holder for anonymous transformer + } + if !isValid(name) { + panic(fmt.Sprintf("invalid name: %q", name)) + } + tr := &transformer{name: name, fnc: reflect.ValueOf(f)} + if ti := v.Type().In(0); ti.Kind() != reflect.Interface || ti.NumMethod() > 0 { + tr.typ = ti + } + return tr +} + +type transformer struct { + core + name string + typ reflect.Type // T + fnc reflect.Value // func(T) R +} + +func (tr *transformer) isFiltered() bool { return tr.typ != nil } + +func (tr *transformer) filter(s *state, _, _ reflect.Value, t reflect.Type) applicableOption { + for i := len(s.curPath) - 1; i >= 0; i-- { + if t, ok := s.curPath[i].(*transform); !ok { + break // Hit most recent non-Transform step + } else if tr == t.trans { + return nil // Cannot directly use same Transform + } + } + if tr.typ == nil || t.AssignableTo(tr.typ) { + return tr + } + return nil +} + +func (tr *transformer) apply(s *state, vx, vy reflect.Value) { + // Update path before calling the Transformer so that dynamic checks + // will use the updated path. + s.curPath.push(&transform{pathStep{tr.fnc.Type().Out(0)}, tr}) + defer s.curPath.pop() + + vx = s.callTRFunc(tr.fnc, vx) + vy = s.callTRFunc(tr.fnc, vy) + s.compareAny(vx, vy) +} + +func (tr transformer) String() string { + return fmt.Sprintf("Transformer(%s, %s)", tr.name, getFuncName(tr.fnc.Pointer())) +} + +// Comparer returns an Option that determines whether two values are equal +// to each other. +// +// The comparer f must be a function "func(T, T) bool" and is implicitly +// filtered to input values assignable to T. If T is an interface, it is +// possible that f is called with two values of different concrete types that +// both implement T. +// +// The equality function must be: +// • Symmetric: equal(x, y) == equal(y, x) +// • Deterministic: equal(x, y) == equal(x, y) +// • Pure: equal(x, y) does not modify x or y +func Comparer(f interface{}) Option { + v := reflect.ValueOf(f) + if !function.IsType(v.Type(), function.Equal) || v.IsNil() { + panic(fmt.Sprintf("invalid comparer function: %T", f)) + } + cm := &comparer{fnc: v} + if ti := v.Type().In(0); ti.Kind() != reflect.Interface || ti.NumMethod() > 0 { + cm.typ = ti + } + return cm +} + +type comparer struct { + core + typ reflect.Type // T + fnc reflect.Value // func(T, T) bool +} + +func (cm *comparer) isFiltered() bool { return cm.typ != nil } + +func (cm *comparer) filter(_ *state, _, _ reflect.Value, t reflect.Type) applicableOption { + if cm.typ == nil || t.AssignableTo(cm.typ) { + return cm + } + return nil +} + +func (cm *comparer) apply(s *state, vx, vy reflect.Value) { + eq := s.callTTBFunc(cm.fnc, vx, vy) + s.report(eq, vx, vy) +} + +func (cm comparer) String() string { + return fmt.Sprintf("Comparer(%s)", getFuncName(cm.fnc.Pointer())) +} + +// AllowUnexported returns an Option that forcibly allows operations on +// unexported fields in certain structs, which are specified by passing in a +// value of each struct type. +// +// Users of this option must understand that comparing on unexported fields +// from external packages is not safe since changes in the internal +// implementation of some external package may cause the result of Equal +// to unexpectedly change. However, it may be valid to use this option on types +// defined in an internal package where the semantic meaning of an unexported +// field is in the control of the user. +// +// For some cases, a custom Comparer should be used instead that defines +// equality as a function of the public API of a type rather than the underlying +// unexported implementation. +// +// For example, the reflect.Type documentation defines equality to be determined +// by the == operator on the interface (essentially performing a shallow pointer +// comparison) and most attempts to compare *regexp.Regexp types are interested +// in only checking that the regular expression strings are equal. +// Both of these are accomplished using Comparers: +// +// Comparer(func(x, y reflect.Type) bool { return x == y }) +// Comparer(func(x, y *regexp.Regexp) bool { return x.String() == y.String() }) +// +// In other cases, the cmpopts.IgnoreUnexported option can be used to ignore +// all unexported fields on specified struct types. +func AllowUnexported(types ...interface{}) Option { + if !supportAllowUnexported { + panic("AllowUnexported is not supported on purego builds, Google App Engine Standard, or GopherJS") + } + m := make(map[reflect.Type]bool) + for _, typ := range types { + t := reflect.TypeOf(typ) + if t.Kind() != reflect.Struct { + panic(fmt.Sprintf("invalid struct type: %T", typ)) + } + m[t] = true + } + return visibleStructs(m) +} + +type visibleStructs map[reflect.Type]bool + +func (visibleStructs) filter(_ *state, _, _ reflect.Value, _ reflect.Type) applicableOption { + panic("not implemented") +} + +// reporter is an Option that configures how differences are reported. +type reporter interface { + // TODO: Not exported yet. + // + // Perhaps add PushStep and PopStep and change Report to only accept + // a PathStep instead of the full-path? Adding a PushStep and PopStep makes + // it clear that we are traversing the value tree in a depth-first-search + // manner, which has an effect on how values are printed. + + Option + + // Report is called for every comparison made and will be provided with + // the two values being compared, the equality result, and the + // current path in the value tree. It is possible for x or y to be an + // invalid reflect.Value if one of the values is non-existent; + // which is possible with maps and slices. + Report(x, y reflect.Value, eq bool, p Path) +} + +// normalizeOption normalizes the input options such that all Options groups +// are flattened and groups with a single element are reduced to that element. +// Only coreOptions and Options containing coreOptions are allowed. +func normalizeOption(src Option) Option { + switch opts := flattenOptions(nil, Options{src}); len(opts) { + case 0: + return nil + case 1: + return opts[0] + default: + return opts + } +} + +// flattenOptions copies all options in src to dst as a flat list. +// Only coreOptions and Options containing coreOptions are allowed. +func flattenOptions(dst, src Options) Options { + for _, opt := range src { + switch opt := opt.(type) { + case nil: + continue + case Options: + dst = flattenOptions(dst, opt) + case coreOption: + dst = append(dst, opt) + default: + panic(fmt.Sprintf("invalid option type: %T", opt)) + } + } + return dst +} + +// getFuncName returns a short function name from the pointer. +// The string parsing logic works up until Go1.9. +func getFuncName(p uintptr) string { + fnc := runtime.FuncForPC(p) + if fnc == nil { + return "" + } + name := fnc.Name() // E.g., "long/path/name/mypkg.(mytype).(long/path/name/mypkg.myfunc)-fm" + if strings.HasSuffix(name, ")-fm") || strings.HasSuffix(name, ")·fm") { + // Strip the package name from method name. + name = strings.TrimSuffix(name, ")-fm") + name = strings.TrimSuffix(name, ")·fm") + if i := strings.LastIndexByte(name, '('); i >= 0 { + methodName := name[i+1:] // E.g., "long/path/name/mypkg.myfunc" + if j := strings.LastIndexByte(methodName, '.'); j >= 0 { + methodName = methodName[j+1:] // E.g., "myfunc" + } + name = name[:i] + methodName // E.g., "long/path/name/mypkg.(mytype)." + "myfunc" + } + } + if i := strings.LastIndexByte(name, '/'); i >= 0 { + // Strip the package name. + name = name[i+1:] // E.g., "mypkg.(mytype).myfunc" + } + return name +} diff --git a/vendor/github.com/google/go-cmp/cmp/path.go b/vendor/github.com/google/go-cmp/cmp/path.go new file mode 100644 index 0000000..c08a3cf --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/path.go @@ -0,0 +1,309 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +package cmp + +import ( + "fmt" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +type ( + // Path is a list of PathSteps describing the sequence of operations to get + // from some root type to the current position in the value tree. + // The first Path element is always an operation-less PathStep that exists + // simply to identify the initial type. + // + // When traversing structs with embedded structs, the embedded struct will + // always be accessed as a field before traversing the fields of the + // embedded struct themselves. That is, an exported field from the + // embedded struct will never be accessed directly from the parent struct. + Path []PathStep + + // PathStep is a union-type for specific operations to traverse + // a value's tree structure. Users of this package never need to implement + // these types as values of this type will be returned by this package. + PathStep interface { + String() string + Type() reflect.Type // Resulting type after performing the path step + isPathStep() + } + + // SliceIndex is an index operation on a slice or array at some index Key. + SliceIndex interface { + PathStep + Key() int // May return -1 if in a split state + + // SplitKeys returns the indexes for indexing into slices in the + // x and y values, respectively. These indexes may differ due to the + // insertion or removal of an element in one of the slices, causing + // all of the indexes to be shifted. If an index is -1, then that + // indicates that the element does not exist in the associated slice. + // + // Key is guaranteed to return -1 if and only if the indexes returned + // by SplitKeys are not the same. SplitKeys will never return -1 for + // both indexes. + SplitKeys() (x int, y int) + + isSliceIndex() + } + // MapIndex is an index operation on a map at some index Key. + MapIndex interface { + PathStep + Key() reflect.Value + isMapIndex() + } + // TypeAssertion represents a type assertion on an interface. + TypeAssertion interface { + PathStep + isTypeAssertion() + } + // StructField represents a struct field access on a field called Name. + StructField interface { + PathStep + Name() string + Index() int + isStructField() + } + // Indirect represents pointer indirection on the parent type. + Indirect interface { + PathStep + isIndirect() + } + // Transform is a transformation from the parent type to the current type. + Transform interface { + PathStep + Name() string + Func() reflect.Value + + // Option returns the originally constructed Transformer option. + // The == operator can be used to detect the exact option used. + Option() Option + + isTransform() + } +) + +func (pa *Path) push(s PathStep) { + *pa = append(*pa, s) +} + +func (pa *Path) pop() { + *pa = (*pa)[:len(*pa)-1] +} + +// Last returns the last PathStep in the Path. +// If the path is empty, this returns a non-nil PathStep that reports a nil Type. +func (pa Path) Last() PathStep { + return pa.Index(-1) +} + +// Index returns the ith step in the Path and supports negative indexing. +// A negative index starts counting from the tail of the Path such that -1 +// refers to the last step, -2 refers to the second-to-last step, and so on. +// If index is invalid, this returns a non-nil PathStep that reports a nil Type. +func (pa Path) Index(i int) PathStep { + if i < 0 { + i = len(pa) + i + } + if i < 0 || i >= len(pa) { + return pathStep{} + } + return pa[i] +} + +// String returns the simplified path to a node. +// The simplified path only contains struct field accesses. +// +// For example: +// MyMap.MySlices.MyField +func (pa Path) String() string { + var ss []string + for _, s := range pa { + if _, ok := s.(*structField); ok { + ss = append(ss, s.String()) + } + } + return strings.TrimPrefix(strings.Join(ss, ""), ".") +} + +// GoString returns the path to a specific node using Go syntax. +// +// For example: +// (*root.MyMap["key"].(*mypkg.MyStruct).MySlices)[2][3].MyField +func (pa Path) GoString() string { + var ssPre, ssPost []string + var numIndirect int + for i, s := range pa { + var nextStep PathStep + if i+1 < len(pa) { + nextStep = pa[i+1] + } + switch s := s.(type) { + case *indirect: + numIndirect++ + pPre, pPost := "(", ")" + switch nextStep.(type) { + case *indirect: + continue // Next step is indirection, so let them batch up + case *structField: + numIndirect-- // Automatic indirection on struct fields + case nil: + pPre, pPost = "", "" // Last step; no need for parenthesis + } + if numIndirect > 0 { + ssPre = append(ssPre, pPre+strings.Repeat("*", numIndirect)) + ssPost = append(ssPost, pPost) + } + numIndirect = 0 + continue + case *transform: + ssPre = append(ssPre, s.trans.name+"(") + ssPost = append(ssPost, ")") + continue + case *typeAssertion: + // As a special-case, elide type assertions on anonymous types + // since they are typically generated dynamically and can be very + // verbose. For example, some transforms return interface{} because + // of Go's lack of generics, but typically take in and return the + // exact same concrete type. + if s.Type().PkgPath() == "" { + continue + } + } + ssPost = append(ssPost, s.String()) + } + for i, j := 0, len(ssPre)-1; i < j; i, j = i+1, j-1 { + ssPre[i], ssPre[j] = ssPre[j], ssPre[i] + } + return strings.Join(ssPre, "") + strings.Join(ssPost, "") +} + +type ( + pathStep struct { + typ reflect.Type + } + + sliceIndex struct { + pathStep + xkey, ykey int + } + mapIndex struct { + pathStep + key reflect.Value + } + typeAssertion struct { + pathStep + } + structField struct { + pathStep + name string + idx int + + // These fields are used for forcibly accessing an unexported field. + // pvx, pvy, and field are only valid if unexported is true. + unexported bool + force bool // Forcibly allow visibility + pvx, pvy reflect.Value // Parent values + field reflect.StructField // Field information + } + indirect struct { + pathStep + } + transform struct { + pathStep + trans *transformer + } +) + +func (ps pathStep) Type() reflect.Type { return ps.typ } +func (ps pathStep) String() string { + if ps.typ == nil { + return "" + } + s := ps.typ.String() + if s == "" || strings.ContainsAny(s, "{}\n") { + return "root" // Type too simple or complex to print + } + return fmt.Sprintf("{%s}", s) +} + +func (si sliceIndex) String() string { + switch { + case si.xkey == si.ykey: + return fmt.Sprintf("[%d]", si.xkey) + case si.ykey == -1: + // [5->?] means "I don't know where X[5] went" + return fmt.Sprintf("[%d->?]", si.xkey) + case si.xkey == -1: + // [?->3] means "I don't know where Y[3] came from" + return fmt.Sprintf("[?->%d]", si.ykey) + default: + // [5->3] means "X[5] moved to Y[3]" + return fmt.Sprintf("[%d->%d]", si.xkey, si.ykey) + } +} +func (mi mapIndex) String() string { return fmt.Sprintf("[%#v]", mi.key) } +func (ta typeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) } +func (sf structField) String() string { return fmt.Sprintf(".%s", sf.name) } +func (in indirect) String() string { return "*" } +func (tf transform) String() string { return fmt.Sprintf("%s()", tf.trans.name) } + +func (si sliceIndex) Key() int { + if si.xkey != si.ykey { + return -1 + } + return si.xkey +} +func (si sliceIndex) SplitKeys() (x, y int) { return si.xkey, si.ykey } +func (mi mapIndex) Key() reflect.Value { return mi.key } +func (sf structField) Name() string { return sf.name } +func (sf structField) Index() int { return sf.idx } +func (tf transform) Name() string { return tf.trans.name } +func (tf transform) Func() reflect.Value { return tf.trans.fnc } +func (tf transform) Option() Option { return tf.trans } + +func (pathStep) isPathStep() {} +func (sliceIndex) isSliceIndex() {} +func (mapIndex) isMapIndex() {} +func (typeAssertion) isTypeAssertion() {} +func (structField) isStructField() {} +func (indirect) isIndirect() {} +func (transform) isTransform() {} + +var ( + _ SliceIndex = sliceIndex{} + _ MapIndex = mapIndex{} + _ TypeAssertion = typeAssertion{} + _ StructField = structField{} + _ Indirect = indirect{} + _ Transform = transform{} + + _ PathStep = sliceIndex{} + _ PathStep = mapIndex{} + _ PathStep = typeAssertion{} + _ PathStep = structField{} + _ PathStep = indirect{} + _ PathStep = transform{} +) + +// isExported reports whether the identifier is exported. +func isExported(id string) bool { + r, _ := utf8.DecodeRuneInString(id) + return unicode.IsUpper(r) +} + +// isValid reports whether the identifier is valid. +// Empty and underscore-only strings are not valid. +func isValid(id string) bool { + ok := id != "" && id != "_" + for j, c := range id { + ok = ok && (j > 0 || !unicode.IsDigit(c)) + ok = ok && (c == '_' || unicode.IsLetter(c) || unicode.IsDigit(c)) + } + return ok +} diff --git a/vendor/github.com/google/go-cmp/cmp/reporter.go b/vendor/github.com/google/go-cmp/cmp/reporter.go new file mode 100644 index 0000000..20e9f18 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/reporter.go @@ -0,0 +1,53 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +package cmp + +import ( + "fmt" + "reflect" + "strings" + + "github.com/google/go-cmp/cmp/internal/value" +) + +type defaultReporter struct { + Option + diffs []string // List of differences, possibly truncated + ndiffs int // Total number of differences + nbytes int // Number of bytes in diffs + nlines int // Number of lines in diffs +} + +var _ reporter = (*defaultReporter)(nil) + +func (r *defaultReporter) Report(x, y reflect.Value, eq bool, p Path) { + if eq { + return // Ignore equal results + } + const maxBytes = 4096 + const maxLines = 256 + r.ndiffs++ + if r.nbytes < maxBytes && r.nlines < maxLines { + sx := value.Format(x, value.FormatConfig{UseStringer: true}) + sy := value.Format(y, value.FormatConfig{UseStringer: true}) + if sx == sy { + // Unhelpful output, so use more exact formatting. + sx = value.Format(x, value.FormatConfig{PrintPrimitiveType: true}) + sy = value.Format(y, value.FormatConfig{PrintPrimitiveType: true}) + } + s := fmt.Sprintf("%#v:\n\t-: %s\n\t+: %s\n", p, sx, sy) + r.diffs = append(r.diffs, s) + r.nbytes += len(s) + r.nlines += strings.Count(s, "\n") + } +} + +func (r *defaultReporter) String() string { + s := strings.Join(r.diffs, "") + if r.ndiffs == len(r.diffs) { + return s + } + return fmt.Sprintf("%s... %d more differences ...", s, r.ndiffs-len(r.diffs)) +} diff --git a/vendor/github.com/google/go-cmp/cmp/unsafe_panic.go b/vendor/github.com/google/go-cmp/cmp/unsafe_panic.go new file mode 100644 index 0000000..d1518eb --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/unsafe_panic.go @@ -0,0 +1,15 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// +build purego appengine js + +package cmp + +import "reflect" + +const supportAllowUnexported = false + +func unsafeRetrieveField(reflect.Value, reflect.StructField) reflect.Value { + panic("unsafeRetrieveField is not implemented") +} diff --git a/vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go b/vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go new file mode 100644 index 0000000..579b655 --- /dev/null +++ b/vendor/github.com/google/go-cmp/cmp/unsafe_reflect.go @@ -0,0 +1,23 @@ +// Copyright 2017, The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE.md file. + +// +build !purego,!appengine,!js + +package cmp + +import ( + "reflect" + "unsafe" +) + +const supportAllowUnexported = true + +// unsafeRetrieveField uses unsafe to forcibly retrieve any field from a struct +// such that the value has read-write permissions. +// +// The parent struct, v, must be addressable, while f must be a StructField +// describing the field to retrieve. +func unsafeRetrieveField(v reflect.Value, f reflect.StructField) reflect.Value { + return reflect.NewAt(f.Type, unsafe.Pointer(v.UnsafeAddr()+f.Offset)).Elem() +} diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go index fb87bef..2537853 100644 --- a/vendor/github.com/mitchellh/go-homedir/homedir.go +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -76,6 +76,16 @@ func Expand(path string) (string, error) { return filepath.Join(dir, path[1:]), nil } +// Reset clears the cache, forcing the next call to Dir to re-detect +// the home directory. This generally never has to be called, but can be +// useful in tests if you're modifying the home directory via the HOME +// env var or something. +func Reset() { + cacheLock.Lock() + defer cacheLock.Unlock() + homedirCache = "" +} + func dirUnix() (string, error) { homeEnv := "HOME" if runtime.GOOS == "plan9" { diff --git a/vendor/github.com/soniakeys/bits/.travis.yml b/vendor/github.com/soniakeys/bits/.travis.yml new file mode 100644 index 0000000..2df1f24 --- /dev/null +++ b/vendor/github.com/soniakeys/bits/.travis.yml @@ -0,0 +1,9 @@ +sudo: false +language: go +go: master +before_script: + - go vet + - go get github.com/client9/misspell/cmd/misspell + - misspell -error * + - go get github.com/soniakeys/vetc + - vetc diff --git a/vendor/github.com/soniakeys/bits/bits.go b/vendor/github.com/soniakeys/bits/bits.go new file mode 100644 index 0000000..416b0d8 --- /dev/null +++ b/vendor/github.com/soniakeys/bits/bits.go @@ -0,0 +1,463 @@ +// Copyright 2017 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +// Bits implements methods on a bit array type. +// +// The Bits type holds a fixed size array of bits, numbered consecutively +// from zero. Some set-like operations are possible, but the API is more +// array-like or register-like. +package bits + +import ( + "fmt" + mb "math/bits" +) + +// Bits holds a fixed number of bits. +// +// Bit number 0 is stored in the LSB, or bit 0, of the word indexed at 0. +// +// When Num is not a multiple of 64, the last element of Bits will hold some +// bits beyond Num. These bits are undefined. They are not required to be +// zero but do not have any meaning. Bits methods are not required to leave +// them undisturbed. +type Bits struct { + Num int // number of bits + Bits []uint64 +} + +// New constructs a Bits value with the given number of bits. +// +// It panics if num is negative. +func New(num int) Bits { + if num < 0 { + panic("negative number of bits") + } + return Bits{num, make([]uint64, (num+63)>>6)} +} + +// NewGivens constructs a Bits value with the given bits nums set to 1. +// +// The number of bits will be just enough to hold the largest bit value +// listed. That is, the number of bits will be the max bit number plus one. +// +// It panics if any bit number is negative. +func NewGivens(nums ...int) Bits { + max := -1 + for _, p := range nums { + if p > max { + max = p + } + } + b := New(max + 1) + for _, p := range nums { + b.SetBit(p, 1) + } + return b +} + +// AllOnes returns true if all Num bits are 1. +func (b Bits) AllOnes() bool { + last := len(b.Bits) - 1 + for _, w := range b.Bits[:last] { + if w != ^uint64(0) { + return false + } + } + return ^b.Bits[last]<= b.Num { + panic("bit number out of range") + } + return int(b.Bits[n>>6] >> uint(n&63) & 1) +} + +// ClearAll sets all bits to 0. +func (b Bits) ClearAll() { + for i := range b.Bits { + b.Bits[i] = 0 + } +} + +// ClearBits sets the given bits to 0 in receiver b. +// +// Other bits of b are left unchanged. +// +// It panics if any bit number is out of range. +// That is, negative or >= the number of bits. +func (b Bits) ClearBits(nums ...int) { + for _, p := range nums { + b.SetBit(p, 0) + } +} + +// Equal returns true if all Num bits of a and b are equal. +// +// It panics if a and b have different Num. +func (a Bits) Equal(b Bits) bool { + if a.Num != b.Num { + panic("receiver and argument have different number of bits") + } + if a.Num == 0 { + return true + } + last := len(a.Bits) - 1 + for i, w := range a.Bits[:last] { + if w != b.Bits[i] { + return false + } + } + return (a.Bits[last]^b.Bits[last])<= b.Num { + return true + } + if !v(x<<6 | i) { + return false + } + w >>= uint(t + 1) + if w == 0 { + break + } + t = mb.TrailingZeros64(w) + i += 1 + t + } + } + } + return true +} + +// IterateZeros calls visitor function v for each bit with a value of 0, +// in order from lowest bit to highest bit. +// +// Iteration continues to the highest bit as long as v returns true. +// It stops if v returns false. +// +// IterateZeros returns true normally. It returns false if v returns false. +// +// IterateZeros may not be sensitive to changes if bits are changed during +// iteration, by the vistor function for example. +// See ZeroFrom for an iteration method sensitive to changes during iteration. +func (b Bits) IterateZeros(v func(int) bool) bool { + for x, w := range b.Bits { + w = ^w + if w != 0 { + t := mb.TrailingZeros64(w) + i := t // index in w of next 1 bit + for { + n := x<<6 | i + if n >= b.Num { + return true + } + if !v(x<<6 | i) { + return false + } + w >>= uint(t + 1) + if w == 0 { + break + } + t = mb.TrailingZeros64(w) + i += 1 + t + } + } + } + return true +} + +// Not sets receiver z to the complement of b. +func (z *Bits) Not(b Bits) { + if z.Num != b.Num { + *z = New(b.Num) + } + for i, w := range b.Bits { + z.Bits[i] = ^w + } +} + +// OneFrom returns the number of the first 1 bit at or after (from) bit num. +// +// It returns -1 if there is no one bit at or after num. +// +// This provides one way to iterate over one bits. +// To iterate over the one bits, call OneFrom with n = 0 to get the the first +// one bit, then call with the result + 1 to get successive one bits. +// Unlike the Iterate method, this technique is stateless and so allows +// bits to be changed between successive calls. +// +// There is no panic for calling OneFrom with an argument >= b.Num. +// In this case OneFrom simply returns -1. +// +// See also Iterate. +func (b Bits) OneFrom(num int) int { + if num >= b.Num { + return -1 + } + x := num >> 6 + // test for 1 in this word at or after n + if wx := b.Bits[x] >> uint(num&63); wx != 0 { + num += mb.TrailingZeros64(wx) + if num >= b.Num { + return -1 + } + return num + } + x++ + for y, wy := range b.Bits[x:] { + if wy != 0 { + num = (x+y)<<6 | mb.TrailingZeros64(wy) + if num >= b.Num { + return -1 + } + return num + } + } + return -1 +} + +// Or sets z = x | y. +// +// It panics if x and y do not have the same Num. +func (z *Bits) Or(x, y Bits) { + if x.Num != y.Num { + panic("arguments have different number of bits") + } + if z.Num != x.Num { + *z = New(x.Num) + } + for i, w := range y.Bits { + z.Bits[i] = x.Bits[i] | w + } +} + +// OnesCount returns the number of 1 bits. +func (b Bits) OnesCount() (c int) { + if b.Num == 0 { + return 0 + } + last := len(b.Bits) - 1 + for _, w := range b.Bits[:last] { + c += mb.OnesCount64(w) + } + c += mb.OnesCount64(b.Bits[last] << uint(len(b.Bits)*64-b.Num)) + return +} + +// Set sets the bits of z to the bits of x. +func (z *Bits) Set(b Bits) { + if z.Num != b.Num { + *z = New(b.Num) + } + copy(z.Bits, b.Bits) +} + +// SetAll sets z to have all 1 bits. +func (b Bits) SetAll() { + for i := range b.Bits { + b.Bits[i] = ^uint64(0) + } +} + +// SetBit sets the n'th bit to x, where x is a 0 or 1. +// +// It panics if n is out of range +func (b Bits) SetBit(n, x int) { + if n < 0 || n >= b.Num { + panic("bit number out of range") + } + if x == 0 { + b.Bits[n>>6] &^= 1 << uint(n&63) + } else { + b.Bits[n>>6] |= 1 << uint(n&63) + } +} + +// SetBits sets the given bits to 1 in receiver b. +// +// Other bits of b are left unchanged. +// +// It panics if any bit number is out of range, negative or >= the number +// of bits. +func (b Bits) SetBits(nums ...int) { + for _, p := range nums { + b.SetBit(p, 1) + } +} + +// Single returns true if b has exactly one 1 bit. +func (b Bits) Single() bool { + // like OnesCount, but stop as soon as two are found + if b.Num == 0 { + return false + } + c := 0 + last := len(b.Bits) - 1 + for _, w := range b.Bits[:last] { + c += mb.OnesCount64(w) + if c > 1 { + return false + } + } + c += mb.OnesCount64(b.Bits[last] << uint(len(b.Bits)*64-b.Num)) + return c == 1 +} + +// Slice returns a slice with the bit numbers of each 1 bit. +func (b Bits) Slice() (s []int) { + for x, w := range b.Bits { + if w == 0 { + continue + } + t := mb.TrailingZeros64(w) + i := t // index in w of next 1 bit + for { + n := x<<6 | i + if n >= b.Num { + break + } + s = append(s, n) + w >>= uint(t + 1) + if w == 0 { + break + } + t = mb.TrailingZeros64(w) + i += 1 + t + } + } + return +} + +// String returns a readable representation. +// +// The returned string is big-endian, with the highest number bit first. +// +// If Num is 0, an empty string is returned. +func (b Bits) String() (s string) { + if b.Num == 0 { + return "" + } + last := len(b.Bits) - 1 + for _, w := range b.Bits[:last] { + s = fmt.Sprintf("%064b", w) + s + } + lb := b.Num - 64*last + return fmt.Sprintf("%0*b", lb, + b.Bits[last]&(^uint64(0)>>uint(64-lb))) + s +} + +// Xor sets z = x ^ y. +func (z *Bits) Xor(x, y Bits) { + if x.Num != y.Num { + panic("arguments have different number of bits") + } + if z.Num != x.Num { + *z = New(x.Num) + } + for i, w := range y.Bits { + z.Bits[i] = x.Bits[i] ^ w + } +} + +// ZeroFrom returns the number of the first 0 bit at or after (from) bit num. +// +// It returns -1 if there is no zero bit at or after num. +// +// This provides one way to iterate over zero bits. +// To iterate over the zero bits, call ZeroFrom with n = 0 to get the the first +// zero bit, then call with the result + 1 to get successive zero bits. +// Unlike the IterateZeros method, this technique is stateless and so allows +// bits to be changed between successive calls. +// +// There is no panic for calling ZeroFrom with an argument >= b.Num. +// In this case ZeroFrom simply returns -1. +// +// See also IterateZeros. +func (b Bits) ZeroFrom(num int) int { + // code much like OneFrom except words are negated before testing + if num >= b.Num { + return -1 + } + x := num >> 6 + // negate word to test for 0 at or after n + if wx := ^b.Bits[x] >> uint(num&63); wx != 0 { + num += mb.TrailingZeros64(wx) + if num >= b.Num { + return -1 + } + return num + } + x++ + for y, wy := range b.Bits[x:] { + wy = ^wy + if wy != 0 { + num = (x+y)<<6 | mb.TrailingZeros64(wy) + if num >= b.Num { + return -1 + } + return num + } + } + return -1 +} diff --git a/vendor/github.com/soniakeys/bits/go.mod b/vendor/github.com/soniakeys/bits/go.mod new file mode 100644 index 0000000..a2464ef --- /dev/null +++ b/vendor/github.com/soniakeys/bits/go.mod @@ -0,0 +1 @@ +module "github.com/soniakeys/bits" diff --git a/vendor/github.com/soniakeys/bits/readme.adoc b/vendor/github.com/soniakeys/bits/readme.adoc new file mode 100644 index 0000000..d39b1ae --- /dev/null +++ b/vendor/github.com/soniakeys/bits/readme.adoc @@ -0,0 +1,38 @@ += Bits + +Bits provides methods on a bit array type. + +The Bits type holds a fixed size array of bits, numbered consecutively +from zero. Some set-like operations are possible, but the API is more +array-like or register-like. + +image:https://godoc.org/github.com/soniakeys/bits?status.svg[link=https://godoc.org/github.com/soniakeys/bits] image:https://travis-ci.org/soniakeys/bits.svg[link=https://travis-ci.org/soniakeys/bits] + +== Motivation and history + +This package evolved from needs of my library of +https://github.com/soniakeys/graph[graph algorithms]. For graph algorithms +a common need is to store a single bit of information per node in a way that +is both fast and memory efficient. I began by using `big.Int` from the standard +library, then wrapped big.Int in a type. From time to time I considered +other publicly available bit array or bit set packages, such as Will +Fitzgerald's popular https://github.com/willf/bitset[bitset], but there were +always little reasons I preferred my own type and methods. My type that +wrapped `big.Int` met my needs until some simple benchmarks indicated it +might be causing performance problems. Some further experiments supported +this hypothesis so I ran further tests with a prototype bit array written +from scratch. Then satisfied that my custom bit array was solving the graph +performance problems, I decided to move it to a separate package with the +idea it might have more general utility. For the initial version of this +package I did the following: + +- implemented a few tests to demonstrate fundamental correctness +- brought over most methods of my type that wrapped big.Int +- changed the index type from the graph-specific node index to a general `int` +- replaced some custom bit-twiddling with use of the new `math/bits` package + in the standard library +- renamed a few methods for clarity +- added a few methods for symmetry +- added a few new methods I had seen a need for in my graph library +- added doc, examples, tests, and more tests for 100% coverage +- added this readme diff --git a/vendor/github.com/soniakeys/graph/.gitignore b/vendor/github.com/soniakeys/graph/.gitignore new file mode 100644 index 0000000..a93b25f --- /dev/null +++ b/vendor/github.com/soniakeys/graph/.gitignore @@ -0,0 +1,2 @@ +*.dot +anecdote/anecdote diff --git a/vendor/github.com/soniakeys/graph/.travis.yml b/vendor/github.com/soniakeys/graph/.travis.yml new file mode 100644 index 0000000..ffc16a1 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/.travis.yml @@ -0,0 +1,11 @@ +sudo: false +language: go +go: + - "1.9.x" + - master +before_script: + - go tool vet -composites=false -printf=false -shift=false . + - go get github.com/client9/misspell/cmd/misspell + - go get github.com/soniakeys/vetc + - misspell -error * */* */*/* + - vetc diff --git a/vendor/github.com/soniakeys/graph/adj.go b/vendor/github.com/soniakeys/graph/adj.go new file mode 100644 index 0000000..dbae481 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/adj.go @@ -0,0 +1,406 @@ +// Copyright 2014 Sonia Keys +// License MIT: https://opensource.org/licenses/MIT + +package graph + +// adj.go contains methods on AdjacencyList and LabeledAdjacencyList. +// +// AdjacencyList methods are placed first and are alphabetized. +// LabeledAdjacencyList methods follow, also alphabetized. +// Only exported methods need be alphabetized; non-exported methods can +// be left near their use. + +import ( + "sort" + + "github.com/soniakeys/bits" +) + +// NI is a "node int" +// +// It is a node number or node ID. NIs are used extensively as slice indexes. +// NIs typically account for a significant fraction of the memory footprint of +// a graph. +type NI int32 + +// AnyParallel identifies if a graph contains parallel arcs, multiple arcs +// that lead from a node to the same node. +// +// If the graph has parallel arcs, the results fr and to represent an example +// where there are parallel arcs from node `fr` to node `to`. +// +// If there are no parallel arcs, the method returns false -1 -1. +// +// Multiple loops on a node count as parallel arcs. +// +// See also alt.AnyParallelMap, which can perform better for some large +// or dense graphs. +func (g AdjacencyList) AnyParallel() (has bool, fr, to NI) { + var t []NI + for n, to := range g { + if len(to) == 0 { + continue + } + // different code in the labeled version, so no code gen. + t = append(t[:0], to...) + sort.Slice(t, func(i, j int) bool { return t[i] < t[j] }) + t0 := t[0] + for _, to := range t[1:] { + if to == t0 { + return true, NI(n), t0 + } + t0 = to + } + } + return false, -1, -1 +} + +// Complement returns the arc-complement of a simple graph. +// +// The result will have an arc for every pair of distinct nodes where there +// is not an arc in g. The complement is valid for both directed and +// undirected graphs. If g is undirected, the complement will be undirected. +// The result will always be a simple graph, having no loops or parallel arcs. +func (g AdjacencyList) Complement() AdjacencyList { + c := make(AdjacencyList, len(g)) + b := bits.New(len(g)) + for n, to := range g { + b.ClearAll() + for _, to := range to { + b.SetBit(int(to), 1) + } + b.SetBit(n, 1) + ct := make([]NI, len(g)-b.OnesCount()) + i := 0 + b.IterateZeros(func(to int) bool { + ct[i] = NI(to) + i++ + return true + }) + c[n] = ct + } + return c +} + +// IsUndirected returns true if g represents an undirected graph. +// +// Returns true when all non-loop arcs are paired in reciprocal pairs. +// Otherwise returns false and an example unpaired arc. +func (g AdjacencyList) IsUndirected() (u bool, from, to NI) { + // similar code in dot/writeUndirected + unpaired := make(AdjacencyList, len(g)) + for fr, to := range g { + arc: // for each arc in g + for _, to := range to { + if to == NI(fr) { + continue // loop + } + // search unpaired arcs + ut := unpaired[to] + for i, u := range ut { + if u == NI(fr) { // found reciprocal + last := len(ut) - 1 + ut[i] = ut[last] + unpaired[to] = ut[:last] + continue arc + } + } + // reciprocal not found + unpaired[fr] = append(unpaired[fr], to) + } + } + for fr, to := range unpaired { + if len(to) > 0 { + return false, NI(fr), to[0] + } + } + return true, -1, -1 +} + +// SortArcLists sorts the arc lists of each node of receiver g. +// +// Nodes are not relabeled and the graph remains equivalent. +func (g AdjacencyList) SortArcLists() { + for _, to := range g { + sort.Slice(to, func(i, j int) bool { return to[i] < to[j] }) + } +} + +// ------- Labeled methods below ------- + +// ArcsAsEdges constructs an edge list with an edge for each arc, including +// reciprocals. +// +// This is a simple way to construct an edge list for algorithms that allow +// the duplication represented by the reciprocal arcs. (e.g. Kruskal) +// +// See also LabeledUndirected.Edges for the edge list without this duplication. +func (g LabeledAdjacencyList) ArcsAsEdges() (el []LabeledEdge) { + for fr, to := range g { + for _, to := range to { + el = append(el, LabeledEdge{Edge{NI(fr), to.To}, to.Label}) + } + } + return +} + +// DistanceMatrix constructs a distance matrix corresponding to the arcs +// of graph g and weight function w. +// +// An arc from f to t with WeightFunc return w is represented by d[f][t] == w. +// In case of parallel arcs, the lowest weight is stored. The distance from +// any node to itself d[n][n] is 0, unless the node has a loop with a negative +// weight. If g has no arc from f to distinct t, +Inf is stored for d[f][t]. +// +// The returned DistanceMatrix is suitable for DistanceMatrix.FloydWarshall. +func (g LabeledAdjacencyList) DistanceMatrix(w WeightFunc) (d DistanceMatrix) { + d = newDM(len(g)) + for fr, to := range g { + for _, to := range to { + // < to pick min of parallel arcs (also nicely ignores NaN) + if wt := w(to.Label); wt < d[fr][to.To] { + d[fr][to.To] = wt + } + } + } + return +} + +// HasArcLabel returns true if g has any arc from node `fr` to node `to` +// with label `l`. +// +// Also returned is the index within the slice of arcs from node `fr`. +// If no arc from `fr` to `to` with label `l` is present, HasArcLabel returns +// false, -1. +func (g LabeledAdjacencyList) HasArcLabel(fr, to NI, l LI) (bool, int) { + t := Half{to, l} + for x, h := range g[fr] { + if h == t { + return true, x + } + } + return false, -1 +} + +// AnyParallel identifies if a graph contains parallel arcs, multiple arcs +// that lead from a node to the same node. +// +// If the graph has parallel arcs, the results fr and to represent an example +// where there are parallel arcs from node `fr` to node `to`. +// +// If there are no parallel arcs, the method returns -1 -1. +// +// Multiple loops on a node count as parallel arcs. +// +// See also alt.AnyParallelMap, which can perform better for some large +// or dense graphs. +func (g LabeledAdjacencyList) AnyParallel() (has bool, fr, to NI) { + var t []NI + for n, to := range g { + if len(to) == 0 { + continue + } + // slightly different code needed here compared to AdjacencyList + t = t[:0] + for _, to := range to { + t = append(t, to.To) + } + sort.Slice(t, func(i, j int) bool { return t[i] < t[j] }) + t0 := t[0] + for _, to := range t[1:] { + if to == t0 { + return true, NI(n), t0 + } + t0 = to + } + } + return false, -1, -1 +} + +// AnyParallelLabel identifies if a graph contains parallel arcs with the same +// label. +// +// If the graph has parallel arcs with the same label, the results fr and to +// represent an example where there are parallel arcs from node `fr` +// to node `to`. +// +// If there are no parallel arcs, the method returns false -1 Half{}. +// +// Multiple loops on a node count as parallel arcs. +func (g LabeledAdjacencyList) AnyParallelLabel() (has bool, fr NI, to Half) { + var t []Half + for n, to := range g { + if len(to) == 0 { + continue + } + // slightly different code needed here compared to AdjacencyList + t = t[:0] + for _, to := range to { + t = append(t, to) + } + sort.Slice(t, func(i, j int) bool { + return t[i].To < t[j].To || + t[i].To == t[j].To && t[i].Label < t[j].Label + }) + t0 := t[0] + for _, to := range t[1:] { + if to == t0 { + return true, NI(n), t0 + } + t0 = to + } + } + return false, -1, Half{} +} + +// IsUndirected returns true if g represents an undirected graph. +// +// Returns true when all non-loop arcs are paired in reciprocal pairs with +// matching labels. Otherwise returns false and an example unpaired arc. +// +// Note the requirement that reciprocal pairs have matching labels is +// an additional test not present in the otherwise equivalent unlabeled version +// of IsUndirected. +func (g LabeledAdjacencyList) IsUndirected() (u bool, from NI, to Half) { + // similar code in LabeledAdjacencyList.Edges + unpaired := make(LabeledAdjacencyList, len(g)) + for fr, to := range g { + arc: // for each arc in g + for _, to := range to { + if to.To == NI(fr) { + continue // loop + } + // search unpaired arcs + ut := unpaired[to.To] + for i, u := range ut { + if u.To == NI(fr) && u.Label == to.Label { // found reciprocal + last := len(ut) - 1 + ut[i] = ut[last] + unpaired[to.To] = ut[:last] + continue arc + } + } + // reciprocal not found + unpaired[fr] = append(unpaired[fr], to) + } + } + for fr, to := range unpaired { + if len(to) > 0 { + return false, NI(fr), to[0] + } + } + return true, -1, to +} + +// ArcLabels constructs the multiset of LIs present in g. +func (g LabeledAdjacencyList) ArcLabels() map[LI]int { + s := map[LI]int{} + for _, to := range g { + for _, to := range to { + s[to.Label]++ + } + } + return s +} + +// NegativeArc returns true if the receiver graph contains a negative arc. +func (g LabeledAdjacencyList) NegativeArc(w WeightFunc) bool { + for _, nbs := range g { + for _, nb := range nbs { + if w(nb.Label) < 0 { + return true + } + } + } + return false +} + +// ParallelArcsLabel identifies all arcs from node `fr` to node `to` with label `l`. +// +// The returned slice contains an element for each arc from node `fr` to node `to` +// with label `l`. The element value is the index within the slice of arcs from node +// `fr`. +// +// See also the method HasArcLabel, which stops after finding a single arc. +func (g LabeledAdjacencyList) ParallelArcsLabel(fr, to NI, l LI) (p []int) { + t := Half{to, l} + for x, h := range g[fr] { + if h == t { + p = append(p, x) + } + } + return +} + +// Unlabeled constructs the unlabeled graph corresponding to g. +func (g LabeledAdjacencyList) Unlabeled() AdjacencyList { + a := make(AdjacencyList, len(g)) + for n, nbs := range g { + to := make([]NI, len(nbs)) + for i, nb := range nbs { + to[i] = nb.To + } + a[n] = to + } + return a +} + +// WeightedArcsAsEdges constructs a WeightedEdgeList object from the receiver. +// +// Internally it calls g.ArcsAsEdges() to obtain the Edges member. +// See LabeledAdjacencyList.ArcsAsEdges(). +func (g LabeledAdjacencyList) WeightedArcsAsEdges(w WeightFunc) *WeightedEdgeList { + return &WeightedEdgeList{ + Order: g.Order(), + WeightFunc: w, + Edges: g.ArcsAsEdges(), + } +} + +// WeightedInDegree computes the weighted in-degree of each node in g +// for a given weight function w. +// +// The weighted in-degree of a node is the sum of weights of arcs going to +// the node. +// +// A weighted degree of a node is often termed the "strength" of a node. +// +// See note for undirected graphs at LabeledAdjacencyList.WeightedOutDegree. +func (g LabeledAdjacencyList) WeightedInDegree(w WeightFunc) []float64 { + ind := make([]float64, len(g)) + for _, to := range g { + for _, to := range to { + ind[to.To] += w(to.Label) + } + } + return ind +} + +// WeightedOutDegree computes the weighted out-degree of the specified node +// for a given weight function w. +// +// The weighted out-degree of a node is the sum of weights of arcs going from +// the node. +// +// A weighted degree of a node is often termed the "strength" of a node. +// +// Note for undirected graphs, the WeightedOutDegree result for a node will +// equal the WeightedInDegree for the node. You can use WeightedInDegree if +// you have need for the weighted degrees of all nodes or use WeightedOutDegree +// to compute the weighted degrees of individual nodes. In either case loops +// are counted just once, unlike the (unweighted) UndirectedDegree methods. +func (g LabeledAdjacencyList) WeightedOutDegree(n NI, w WeightFunc) (d float64) { + for _, to := range g[n] { + d += w(to.Label) + } + return +} + +// More about loops and strength: I didn't see consensus on this especially +// in the case of undirected graphs. Some sources said to add in-degree and +// out-degree, which would seemingly double both loops and non-loops. +// Some said to double loops. Some said sum the edge weights and had no +// comment on loops. R of course makes everything an option. The meaning +// of "strength" where loops exist is unclear. So while I could write an +// UndirectedWeighted degree function that doubles loops but not edges, +// I'm going to just leave this for now. diff --git a/vendor/github.com/soniakeys/graph/adj_RO.go b/vendor/github.com/soniakeys/graph/adj_RO.go new file mode 100644 index 0000000..17df67c --- /dev/null +++ b/vendor/github.com/soniakeys/graph/adj_RO.go @@ -0,0 +1,417 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// adj_RO.go is code generated from adj_cg.go by directives in graph.go. +// Editing adj_cg.go is okay. +// DO NOT EDIT adj_RO.go. The RO is for Read Only. + +import ( + "errors" + "fmt" + "math/rand" + + "github.com/soniakeys/bits" +) + +// ArcDensity returns density for an simple directed graph. +// +// See also ArcDensity function. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) ArcDensity() float64 { + return ArcDensity(len(g), g.ArcSize()) +} + +// ArcSize returns the number of arcs in g. +// +// Note that for an undirected graph without loops, the number of undirected +// edges -- the traditional meaning of graph size -- will be ArcSize()/2. +// On the other hand, if g is an undirected graph that has or may have loops, +// g.ArcSize()/2 is not a meaningful quantity. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) ArcSize() int { + m := 0 + for _, to := range g { + m += len(to) + } + return m +} + +// BoundsOk validates that all arcs in g stay within the slice bounds of g. +// +// BoundsOk returns true when no arcs point outside the bounds of g. +// Otherwise it returns false and an example arc that points outside of g. +// +// Most methods of this package assume the BoundsOk condition and may +// panic when they encounter an arc pointing outside of the graph. This +// function can be used to validate a graph when the BoundsOk condition +// is unknown. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) BoundsOk() (ok bool, fr NI, to NI) { + for fr, to := range g { + for _, to := range to { + if to < 0 || to >= NI(len(g)) { + return false, NI(fr), to + } + } + } + return true, -1, to +} + +// BreadthFirst traverses a directed or undirected graph in breadth +// first order. +// +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also alt.BreadthFirst, a variant with more options, and +// alt.BreadthFirst2, a direction optimizing variant. +func (g AdjacencyList) BreadthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + v.SetBit(int(start), 1) + visit(start) + var next []NI + for frontier := []NI{start}; len(frontier) > 0; { + for _, n := range frontier { + for _, nb := range g[n] { + if v.Bit(int(nb)) == 0 { + v.SetBit(int(nb), 1) + visit(nb) + next = append(next, nb) + } + } + } + frontier, next = next, frontier[:0] + } +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) Copy() (c AdjacencyList, ma int) { + c = make(AdjacencyList, len(g)) + for n, to := range g { + c[n] = append([]NI{}, to...) + ma += len(to) + } + return +} + +// DepthFirst traverses a directed or undirected graph in depth +// first order. +// +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also alt.DepthFirst, a variant with more options. +func (g AdjacencyList) DepthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + var f func(NI) + f = func(n NI) { + visit(n) + v.SetBit(int(n), 1) + for _, to := range g[n] { + if v.Bit(int(to)) == 0 { + f(to) + } + } + } + f(start) +} + +// HasArc returns true if g has any arc from node `fr` to node `to`. +// +// Also returned is the index within the slice of arcs from node `fr`. +// If no arc from `fr` to `to` is present, HasArc returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also the method ParallelArcs, which finds all parallel arcs from +// `fr` to `to`. +func (g AdjacencyList) HasArc(fr, to NI) (bool, int) { + for x, h := range g[fr] { + if h == to { + return true, x + } + } + return false, -1 +} + +// AnyLoop identifies if a graph contains a loop, an arc that leads from a +// a node back to the same node. +// +// If g contains a loop, the method returns true and an example of a node +// with a loop. If there are no loops in g, the method returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) AnyLoop() (bool, NI) { + for fr, to := range g { + for _, to := range to { + if NI(fr) == to { + return true, to + } + } + } + return false, -1 +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *Subgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.AdjacencyList + b = NI(len(a)) + s.AdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *Subgraph) AddArc(fr NI, to NI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to) < 0 || int(to) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.AdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } + } + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super)[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to = s.AddNode(to) + s.AdjacencyList[bf] = append(s.AdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +func (super AdjacencyList) induceArcs(sub map[NI]NI, sup []NI) AdjacencyList { + s := make(AdjacencyList, len(sup)) + for b, p := range sup { + var a []NI + for _, to := range super[p] { + if bt, ok := sub[to]; ok { + to = bt + a = append(a, to) + } + } + s[b] = a + } + return s +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *AdjacencyList) InduceList(l []NI) *Subgraph { + sub, sup := mapList(l) + return &Subgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + AdjacencyList: g.induceArcs(sub, sup)} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *AdjacencyList) InduceBits(t bits.Bits) *Subgraph { + sub, sup := mapBits(t) + return &Subgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + AdjacencyList: g.induceArcs(sub, sup)} +} + +// IsSimple checks for loops and parallel arcs. +// +// A graph is "simple" if it has no loops or parallel arcs. +// +// IsSimple returns true, -1 for simple graphs. If a loop or parallel arc is +// found, simple returns false and a node that represents a counterexample +// to the graph being simple. +// +// See also separate methods AnyLoop and AnyParallel. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) IsSimple() (ok bool, n NI) { + if lp, n := g.AnyLoop(); lp { + return false, n + } + if pa, n, _ := g.AnyParallel(); pa { + return false, n + } + return true, -1 +} + +// IsolatedNodes returns a bitmap of isolated nodes in receiver graph g. +// +// An isolated node is one with no arcs going to or from it. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) IsolatedNodes() (i bits.Bits) { + i = bits.New(len(g)) + i.SetAll() + for fr, to := range g { + if len(to) > 0 { + i.SetBit(fr, 0) + for _, to := range to { + i.SetBit(int(to), 0) + } + } + } + return +} + +// Order is the number of nodes in receiver g. +// +// It is simply a wrapper method for the Go builtin len(). +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) Order() int { + // Why a wrapper for len()? Mostly for Directed and Undirected. + // u.Order() is a little nicer than len(u.LabeledAdjacencyList). + return len(g) +} + +// ParallelArcs identifies all arcs from node `fr` to node `to`. +// +// The returned slice contains an element for each arc from node `fr` to node `to`. +// The element value is the index within the slice of arcs from node `fr`. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also the method HasArc, which stops after finding a single arc. +func (g AdjacencyList) ParallelArcs(fr, to NI) (p []int) { + for x, h := range g[fr] { + if h == to { + p = append(p, x) + } + } + return +} + +// Permute permutes the node labeling of receiver g. +// +// Argument p must be a permutation of the node numbers of the graph, +// 0 through len(g)-1. A permutation returned by rand.Perm(len(g)) for +// example is acceptable. +// +// The graph is permuted in place. The graph keeps the same underlying +// memory but values of the graph representation are permuted to produce +// an isomorphic graph. The node previously labeled 0 becomes p[0] and so on. +// See example (or the code) for clarification. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) Permute(p []int) { + old := append(AdjacencyList{}, g...) // shallow copy + for fr, arcs := range old { + for i, to := range arcs { + arcs[i] = NI(p[to]) + } + g[p[fr]] = arcs + } +} + +// ShuffleArcLists shuffles the arc lists of each node of receiver g. +// +// For example a node with arcs leading to nodes 3 and 7 might have an +// arc list of either [3 7] or [7 3] after calling this method. The +// connectivity of the graph is not changed. The resulting graph stays +// equivalent but a traversal will encounter arcs in a different +// order. +// +// If Rand r is nil, the rand package default shared source is used. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) ShuffleArcLists(r *rand.Rand) { + ri := rand.Intn + if r != nil { + ri = r.Intn + } + // Knuth-Fisher-Yates + for _, to := range g { + for i := len(to); i > 1; { + j := ri(i) + i-- + to[i], to[j] = to[j], to[i] + } + } +} diff --git a/vendor/github.com/soniakeys/graph/adj_cg.go b/vendor/github.com/soniakeys/graph/adj_cg.go new file mode 100644 index 0000000..796ced6 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/adj_cg.go @@ -0,0 +1,417 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// adj_RO.go is code generated from adj_cg.go by directives in graph.go. +// Editing adj_cg.go is okay. +// DO NOT EDIT adj_RO.go. The RO is for Read Only. + +import ( + "errors" + "fmt" + "math/rand" + + "github.com/soniakeys/bits" +) + +// ArcDensity returns density for an simple directed graph. +// +// See also ArcDensity function. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) ArcDensity() float64 { + return ArcDensity(len(g), g.ArcSize()) +} + +// ArcSize returns the number of arcs in g. +// +// Note that for an undirected graph without loops, the number of undirected +// edges -- the traditional meaning of graph size -- will be ArcSize()/2. +// On the other hand, if g is an undirected graph that has or may have loops, +// g.ArcSize()/2 is not a meaningful quantity. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) ArcSize() int { + m := 0 + for _, to := range g { + m += len(to) + } + return m +} + +// BoundsOk validates that all arcs in g stay within the slice bounds of g. +// +// BoundsOk returns true when no arcs point outside the bounds of g. +// Otherwise it returns false and an example arc that points outside of g. +// +// Most methods of this package assume the BoundsOk condition and may +// panic when they encounter an arc pointing outside of the graph. This +// function can be used to validate a graph when the BoundsOk condition +// is unknown. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) BoundsOk() (ok bool, fr NI, to Half) { + for fr, to := range g { + for _, to := range to { + if to.To < 0 || to.To >= NI(len(g)) { + return false, NI(fr), to + } + } + } + return true, -1, to +} + +// BreadthFirst traverses a directed or undirected graph in breadth +// first order. +// +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also alt.BreadthFirst, a variant with more options, and +// alt.BreadthFirst2, a direction optimizing variant. +func (g LabeledAdjacencyList) BreadthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + v.SetBit(int(start), 1) + visit(start) + var next []NI + for frontier := []NI{start}; len(frontier) > 0; { + for _, n := range frontier { + for _, nb := range g[n] { + if v.Bit(int(nb.To)) == 0 { + v.SetBit(int(nb.To), 1) + visit(nb.To) + next = append(next, nb.To) + } + } + } + frontier, next = next, frontier[:0] + } +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) Copy() (c LabeledAdjacencyList, ma int) { + c = make(LabeledAdjacencyList, len(g)) + for n, to := range g { + c[n] = append([]Half{}, to...) + ma += len(to) + } + return +} + +// DepthFirst traverses a directed or undirected graph in depth +// first order. +// +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also alt.DepthFirst, a variant with more options. +func (g LabeledAdjacencyList) DepthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + var f func(NI) + f = func(n NI) { + visit(n) + v.SetBit(int(n), 1) + for _, to := range g[n] { + if v.Bit(int(to.To)) == 0 { + f(to.To) + } + } + } + f(start) +} + +// HasArc returns true if g has any arc from node `fr` to node `to`. +// +// Also returned is the index within the slice of arcs from node `fr`. +// If no arc from `fr` to `to` is present, HasArc returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also the method ParallelArcs, which finds all parallel arcs from +// `fr` to `to`. +func (g LabeledAdjacencyList) HasArc(fr, to NI) (bool, int) { + for x, h := range g[fr] { + if h.To == to { + return true, x + } + } + return false, -1 +} + +// AnyLoop identifies if a graph contains a loop, an arc that leads from a +// a node back to the same node. +// +// If g contains a loop, the method returns true and an example of a node +// with a loop. If there are no loops in g, the method returns false, -1. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) AnyLoop() (bool, NI) { + for fr, to := range g { + for _, to := range to { + if NI(fr) == to.To { + return true, to.To + } + } + } + return false, -1 +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *LabeledSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.LabeledAdjacencyList + b = NI(len(a)) + s.LabeledAdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *LabeledSubgraph) AddArc(fr NI, to Half) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to.To) < 0 || int(to.To) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to.To, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.LabeledAdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to.To]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo.To = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } + } + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super)[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to.To = s.AddNode(to.To) + s.LabeledAdjacencyList[bf] = append(s.LabeledAdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +func (super LabeledAdjacencyList) induceArcs(sub map[NI]NI, sup []NI) LabeledAdjacencyList { + s := make(LabeledAdjacencyList, len(sup)) + for b, p := range sup { + var a []Half + for _, to := range super[p] { + if bt, ok := sub[to.To]; ok { + to.To = bt + a = append(a, to) + } + } + s[b] = a + } + return s +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledAdjacencyList) InduceList(l []NI) *LabeledSubgraph { + sub, sup := mapList(l) + return &LabeledSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + LabeledAdjacencyList: g.induceArcs(sub, sup)} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledAdjacencyList) InduceBits(t bits.Bits) *LabeledSubgraph { + sub, sup := mapBits(t) + return &LabeledSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + LabeledAdjacencyList: g.induceArcs(sub, sup)} +} + +// IsSimple checks for loops and parallel arcs. +// +// A graph is "simple" if it has no loops or parallel arcs. +// +// IsSimple returns true, -1 for simple graphs. If a loop or parallel arc is +// found, simple returns false and a node that represents a counterexample +// to the graph being simple. +// +// See also separate methods AnyLoop and AnyParallel. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) IsSimple() (ok bool, n NI) { + if lp, n := g.AnyLoop(); lp { + return false, n + } + if pa, n, _ := g.AnyParallel(); pa { + return false, n + } + return true, -1 +} + +// IsolatedNodes returns a bitmap of isolated nodes in receiver graph g. +// +// An isolated node is one with no arcs going to or from it. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) IsolatedNodes() (i bits.Bits) { + i = bits.New(len(g)) + i.SetAll() + for fr, to := range g { + if len(to) > 0 { + i.SetBit(fr, 0) + for _, to := range to { + i.SetBit(int(to.To), 0) + } + } + } + return +} + +// Order is the number of nodes in receiver g. +// +// It is simply a wrapper method for the Go builtin len(). +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) Order() int { + // Why a wrapper for len()? Mostly for Directed and Undirected. + // u.Order() is a little nicer than len(u.LabeledAdjacencyList). + return len(g) +} + +// ParallelArcs identifies all arcs from node `fr` to node `to`. +// +// The returned slice contains an element for each arc from node `fr` to node `to`. +// The element value is the index within the slice of arcs from node `fr`. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also the method HasArc, which stops after finding a single arc. +func (g LabeledAdjacencyList) ParallelArcs(fr, to NI) (p []int) { + for x, h := range g[fr] { + if h.To == to { + p = append(p, x) + } + } + return +} + +// Permute permutes the node labeling of receiver g. +// +// Argument p must be a permutation of the node numbers of the graph, +// 0 through len(g)-1. A permutation returned by rand.Perm(len(g)) for +// example is acceptable. +// +// The graph is permuted in place. The graph keeps the same underlying +// memory but values of the graph representation are permuted to produce +// an isomorphic graph. The node previously labeled 0 becomes p[0] and so on. +// See example (or the code) for clarification. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) Permute(p []int) { + old := append(LabeledAdjacencyList{}, g...) // shallow copy + for fr, arcs := range old { + for i, to := range arcs { + arcs[i].To = NI(p[to.To]) + } + g[p[fr]] = arcs + } +} + +// ShuffleArcLists shuffles the arc lists of each node of receiver g. +// +// For example a node with arcs leading to nodes 3 and 7 might have an +// arc list of either [3 7] or [7 3] after calling this method. The +// connectivity of the graph is not changed. The resulting graph stays +// equivalent but a traversal will encounter arcs in a different +// order. +// +// If Rand r is nil, the rand package default shared source is used. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) ShuffleArcLists(r *rand.Rand) { + ri := rand.Intn + if r != nil { + ri = r.Intn + } + // Knuth-Fisher-Yates + for _, to := range g { + for i := len(to); i > 1; { + j := ri(i) + i-- + to[i], to[j] = to[j], to[i] + } + } +} diff --git a/vendor/github.com/soniakeys/graph/dir.go b/vendor/github.com/soniakeys/graph/dir.go new file mode 100644 index 0000000..a9ce535 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/dir.go @@ -0,0 +1,1059 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "math" +) + +// dir.go has methods specific to directed graphs, types Directed and +// LabeledDirected, also Dominators. +// +// Methods on Directed are first, with exported methods alphabetized. +// Dominators type and methods are at the end. +//---------------------------- + +// Cycles emits all elementary cycles in a directed graph. +// +// The algorithm here is Johnson's. See also the equivalent but generally +// slower alt.TarjanCycles. +func (g Directed) Cycles(emit func([]NI) bool) { + // Johnsons "Finding all the elementary circuits of a directed graph", + // SIAM J. Comput. Vol. 4, No. 1, March 1975. + a := g.AdjacencyList + k := make(AdjacencyList, len(a)) + B := make([]map[NI]bool, len(a)) + blocked := make([]bool, len(a)) + for i := range a { + blocked[i] = true + B[i] = map[NI]bool{} + } + var s NI + var stack []NI + var unblock func(NI) + unblock = func(u NI) { + blocked[u] = false + for w := range B[u] { + delete(B[u], w) + if blocked[w] { + unblock(w) + } + } + } + var circuit func(NI) (bool, bool) + circuit = func(v NI) (found, ok bool) { + f := false + stack = append(stack, v) + blocked[v] = true + for _, w := range k[v] { + if w == s { + if !emit(stack) { + return + } + f = true + } else if !blocked[w] { + switch found, ok = circuit(w); { + case !ok: + return + case found: + f = true + } + } + } + if f { + unblock(v) + } else { + for _, w := range k[v] { + B[w][v] = true + } + } + stack = stack[:len(stack)-1] + return f, true + } + for s = 0; int(s) < len(a); s++ { + // (so there's a little extra n^2 component introduced here that + // comes from not making a proper subgraph but just removing arcs + // and leaving isolated nodes. Iterating over the isolated nodes + // should be very fast though. It seems like it would be a net win + // over creating a subgraph.) + // shallow subgraph + for z := NI(0); z < s; z++ { + k[z] = nil + } + for z := int(s); z < len(a); z++ { + k[z] = a[z] + } + // find scc in k with s + var scc []NI + Directed{k}.StronglyConnectedComponents(func(c []NI) bool { + for _, n := range c { + if n == s { // this is it + scc = c + return false // stop scc search + } + } + return true // keep looking + }) + // clear k + for n := range k { + k[n] = nil + } + // map component + for _, n := range scc { + blocked[n] = false + } + // copy component to k + for _, fr := range scc { + var kt []NI + for _, to := range a[fr] { + if !blocked[to] { + kt = append(kt, to) + } + } + k[fr] = kt + } + if _, ok := circuit(s); !ok { + return + } + // reblock component + for _, n := range scc { + blocked[n] = true + } + } +} + +// DAGMaxLenPath finds a maximum length path in a directed acyclic graph. +// +// Argument ordering must be a topological ordering of g. +func (g Directed) DAGMaxLenPath(ordering []NI) (path []NI) { + // dynamic programming. visit nodes in reverse order. for each, compute + // longest path as one plus longest of 'to' nodes. + // Visits each arc once. O(m). + // + // Similar code in label.go + var n NI + mlp := make([][]NI, g.Order()) // index by node number + for i := len(ordering) - 1; i >= 0; i-- { + fr := ordering[i] // node number + to := g.AdjacencyList[fr] + if len(to) == 0 { + continue + } + mt := to[0] + for _, to := range to[1:] { + if len(mlp[to]) > len(mlp[mt]) { + mt = to + } + } + p := append([]NI{mt}, mlp[mt]...) + mlp[fr] = p + if len(p) > len(path) { + n = fr + path = p + } + } + return append([]NI{n}, path...) +} + +// FromList creates a spanning forest of a graph. +// +// The method populates the From members in f.Paths and returns the FromList. +// Also returned is a bool, true if the receiver is found to be a simple graph +// representing a tree or forest. Loops, or any case of multiple arcs going to +// a node will cause simpleForest to be false. +// +// The FromList return value f will always be a spanning forest of the entire +// graph. The bool return value simpleForest tells if the receiver graph g +// was a simple forest to begin with. +// +// Other members of the FromList are left as zero values. +// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +func (g Directed) FromList() (f *FromList, simpleForest bool) { + paths := make([]PathEnd, g.Order()) + for i := range paths { + paths[i].From = -1 + } + simpleForest = true + for fr, to := range g.AdjacencyList { + for _, to := range to { + if int(to) == fr || paths[to].From >= 0 { + simpleForest = false + } else { + paths[to].From = NI(fr) + } + } + } + return &FromList{Paths: paths}, simpleForest +} + +// SpanTree builds a tree spanning nodes reachable from the given root. +// +// The component is spanned by breadth-first search from root. +// The resulting spanning tree in stored a FromList. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of the returned FromList is populated +// with both From and Len values. The MaxLen member will be updated but +// not Leaves. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// reachable from root, and a bool indicating if these nodes were found to be +// a simply connected tree in the receiver graph g. Any cycles, loops, +// or parallel arcs in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid spanning tree. +func (g Directed) SpanTree(root NI, f *FromList) (nSpanned int, simpleTree bool) { + a := g.AdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simpleTree = true + p[root].Len = 1 + type arc struct { + from, to NI + } + var next []arc + frontier := []arc{{-1, root}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.to].Len + 1 + for _, to := range a[fa.to] { + if p[to].Len > 0 { + simpleTree = false + continue + } + p[to] = PathEnd{From: fa.to, Len: l} + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.to, to}) + } + } + frontier, next = next, frontier[:0] + } + return +} + +// Undirected returns copy of g augmented as needed to make it undirected. +func (g Directed) Undirected() Undirected { + c, _ := g.AdjacencyList.Copy() // start with a copy + rw := make(AdjacencyList, g.Order()) // "reciprocals wanted" + for fr, to := range g.AdjacencyList { + arc: // for each arc in g + for _, to := range to { + if to == NI(fr) { + continue // loop + } + // search wanted arcs + wf := rw[fr] + for i, w := range wf { + if w == to { // found, remove + last := len(wf) - 1 + wf[i] = wf[last] + rw[fr] = wf[:last] + continue arc + } + } + // arc not found, add to reciprocal to wanted list + rw[to] = append(rw[to], NI(fr)) + } + } + // add missing reciprocals + for fr, to := range rw { + c[fr] = append(c[fr], to...) + } + return Undirected{c} +} + +// Transpose constructs a new adjacency list with all arcs reversed. +// +// For every arc from->to of g, the result will have an arc to->from. +// Transpose also counts arcs as it traverses and returns ma the number of arcs +// in g (equal to the number of arcs in the result.) +func (g Directed) Transpose() (t Directed, ma int) { + ta := make(AdjacencyList, g.Order()) + for n, nbs := range g.AdjacencyList { + for _, nb := range nbs { + ta[nb] = append(ta[nb], NI(n)) + ma++ + } + } + return Directed{ta}, ma +} + +// Cycles emits all elementary cycles in a directed graph. +// +// The algorithm here is Johnson's. See also the equivalent but generally +// slower alt.TarjanCycles. +func (g LabeledDirected) Cycles(emit func([]Half) bool) { + a := g.LabeledAdjacencyList + k := make(LabeledAdjacencyList, len(a)) + B := make([]map[NI]bool, len(a)) + blocked := make([]bool, len(a)) + for i := range a { + blocked[i] = true + B[i] = map[NI]bool{} + } + var s NI + var stack []Half + var unblock func(NI) + unblock = func(u NI) { + blocked[u] = false + for w := range B[u] { + delete(B[u], w) + if blocked[w] { + unblock(w) + } + } + } + var circuit func(NI) (bool, bool) + circuit = func(v NI) (found, ok bool) { + f := false + blocked[v] = true + for _, w := range k[v] { + if w.To == s { + if !emit(append(stack, w)) { + return + } + f = true + } else if !blocked[w.To] { + stack = append(stack, w) + switch found, ok = circuit(w.To); { + case !ok: + return + case found: + f = true + } + stack = stack[:len(stack)-1] + } + } + if f { + unblock(v) + } else { + for _, w := range k[v] { + B[w.To][v] = true + } + } + return f, true + } + for s = 0; int(s) < len(a); s++ { + for z := NI(0); z < s; z++ { + k[z] = nil + } + for z := int(s); z < len(a); z++ { + k[z] = a[z] + } + var scc []NI + LabeledDirected{k}.StronglyConnectedComponents(func(c []NI) bool { + for _, n := range c { + if n == s { + scc = c + return false + } + } + return true + }) + for n := range k { + k[n] = nil + } + for _, n := range scc { + blocked[n] = false + } + for _, fr := range scc { + var kt []Half + for _, to := range a[fr] { + if !blocked[to.To] { + kt = append(kt, to) + } + } + k[fr] = kt + } + if _, ok := circuit(s); !ok { + return + } + for _, n := range scc { + blocked[n] = true + } + } +} + +// DAGMaxLenPath finds a maximum length path in a directed acyclic graph. +// +// Length here means number of nodes or arcs, not a sum of arc weights. +// +// Argument ordering must be a topological ordering of g. +// +// Returned is a node beginning a maximum length path, and a path of arcs +// starting from that node. +func (g LabeledDirected) DAGMaxLenPath(ordering []NI) (n NI, path []Half) { + // dynamic programming. visit nodes in reverse order. for each, compute + // longest path as one plus longest of 'to' nodes. + // Visits each arc once. Time complexity O(m). + // + // Similar code in dir.go. + mlp := make([][]Half, g.Order()) // index by node number + for i := len(ordering) - 1; i >= 0; i-- { + fr := ordering[i] // node number + to := g.LabeledAdjacencyList[fr] + if len(to) == 0 { + continue + } + mt := to[0] + for _, to := range to[1:] { + if len(mlp[to.To]) > len(mlp[mt.To]) { + mt = to + } + } + p := append([]Half{mt}, mlp[mt.To]...) + mlp[fr] = p + if len(p) > len(path) { + n = fr + path = p + } + } + return +} + +// FromList creates a spanning forest of a graph. +// +// The method populates the From members in f.Paths and returns the FromList. +// Also returned is a list of labels corresponding to the from arcs, and a +// bool, true if the receiver is found to be a simple graph representing +// a tree or forest. Loops, or any case of multiple arcs going to a node +// will cause simpleForest to be false. +// +// The FromList return value f will always be a spanning forest of the entire +// graph. The bool return value simpleForest tells if the receiver graph g +// was a simple forest to begin with. +// +// Other members of the FromList are left as zero values. +// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +func (g LabeledDirected) FromList() (f *FromList, labels []LI, simpleForest bool) { + labels = make([]LI, g.Order()) + paths := make([]PathEnd, g.Order()) + for i := range paths { + paths[i].From = -1 + } + simpleForest = true + for fr, to := range g.LabeledAdjacencyList { + for _, to := range to { + if int(to.To) == fr || paths[to.To].From >= 0 { + simpleForest = false + } else { + paths[to.To].From = NI(fr) + labels[to.To] = to.Label + } + } + } + return &FromList{Paths: paths}, labels, simpleForest +} + +// NegativeCycles emits all cycles with negative cycle distance. +// +// The emit function is called for each cycle found. Emit must return true +// to continue cycle enumeration. If emit returns false, NegativeCycles +// stops and returns immediately. +// +// The method mutates receiver g while it runs. Access to g before +// NegativeCycles returns, such as during the emit callback, will find +// g altered. G is completely restored when NegativeCycles returns however, +// even if terminated early with a false return from emit. +// +// If mutations on g are unacceptable, use g.Copy and run NegativeCycles on +// the copy. +// +// See also: +// +// * NegativeCycle, which finds a single example of a negative cycle if +// one exists. +// +// * HasNegativeCycle, which detects if a negative cycle exists. +// +// * BellmanFord, which also detects negative cycles. +// +// * Cycles, from which negative cycles can be filtered. +// +// * alt.NegativeCycles, which uses less memory but is generally slower. +func (g LabeledDirected) NegativeCycles(w WeightFunc, emit func([]Half) bool) { + // Implementation of "Finding all the negative cycles in a directed graph" + // by Takeo Yamada and Harunobu Kinoshita, Discrete Applied Mathematics + // 118 (2002) 279–291. + newNegCyc(g, w, emit).all_nc(LabeledPath{}) +} + +type negCyc struct { + g LabeledDirected + w WeightFunc + emit func([]Half) bool + a LabeledAdjacencyList + tr AdjacencyList + d0, d1 []float64 + dc []float64 + bt [][]fromHalf + btLast []int +} + +func newNegCyc(g LabeledDirected, w WeightFunc, emit func([]Half) bool) *negCyc { + nc := &negCyc{g: g, w: w, emit: emit} + nc.a = g.LabeledAdjacencyList + // transpose to make it easier to find from-arcs. + lt, _ := g.UnlabeledTranspose() + nc.tr = lt.AdjacencyList + nc.d0 = make([]float64, len(nc.a)) + nc.d1 = make([]float64, len(nc.a)) + nc.dc = make([]float64, len(nc.a)) + nc.btLast = make([]int, len(nc.a)) + nc.bt = make([][]fromHalf, len(nc.a)) + for i := range nc.bt { + nc.bt[i] = make([]fromHalf, len(nc.a)) + } + return nc +} + +func (nc *negCyc) all_nc(F LabeledPath) bool { + var C []Half + var R LabeledPath + // Step 1 + if len(F.Path) != 0 { + return nc.step2(F) + } + C = nc.g.NegativeCycle(nc.w) + if len(C) == 0 { + return true + } + // prep step 4 with no F: + F.Start = C[len(C)-1].To + R = LabeledPath{F.Start, C} + return nc.step4(C, F, R) +} + +func (nc *negCyc) step2(F LabeledPath) bool { + fEnd := F.Path[len(F.Path)-1].To + wF := F.Distance(nc.w) + dL, πL := nc.zL(F, fEnd, wF) + if !(dL < 0) { + return true + } + if len(πL) > 0 { + C := append(F.Path, πL...) + R := LabeledPath{fEnd, πL} + return nc.step4(C, F, R) + } + return nc.step3(F, fEnd, wF) +} + +func (nc *negCyc) step3(F LabeledPath, fEnd NI, wF float64) bool { + πΓ := nc.zΓ(F, wF) + if len(πΓ) > 0 { + // prep for step 4 + C := append(F.Path, πΓ...) + R := LabeledPath{fEnd, πΓ} + return nc.step4(C, F, R) + } + return nc.step5(F, fEnd) +} + +func (nc *negCyc) step4(C []Half, F, R LabeledPath) (ok bool) { + // C is a new cycle. + // F is fixed path to be extended and is a prefix of C. + // R is the remainder of C + if ok = nc.emit(C); !ok { + return + } + // for each arc in R, if not the first arc, + // extend F by the arc of the previous iteration. + // remove arc from g, + // Then make the recursive call, then put the arc back in g. + // + // after loop, replace arcs from the two stacks. + type frto struct { + fr NI + to []Half + } + var frStack [][]arc + var toStack []frto + var fr0 NI + var to0 Half + for i, h := range R.Path { + if i > 0 { + // extend F by arc {fr0 to0}, the arc of the previous iteration. + // Remove arcs to to0.To and save on stack. + // Remove arcs from arc0.fr and save on stack. + F.Path = append(F.Path, to0) + frStack = append(frStack, nc.cutTo(to0.To)) + toStack = append(toStack, frto{fr0, nc.a[fr0]}) + nc.a[fr0] = nil + } + toList := nc.a[R.Start] + for j, to := range toList { + if to == h { + last := len(toList) - 1 + toList[j], toList[last] = toList[last], toList[j] + nc.a[R.Start] = toList[:last] + ok = nc.all_nc(F) // return value + toList[last], toList[j] = toList[j], toList[last] + nc.a[R.Start] = toList + break + } + } + if !ok { + break + } + fr0 = R.Start + to0 = h + R.Start = h.To + } + for i := len(frStack) - 1; i >= 0; i-- { + nc.a[toStack[i].fr] = toStack[i].to + nc.restore(frStack[i]) + } + return +} + +func (nc *negCyc) step5(F LabeledPath, fEnd NI) (ok bool) { + // Step 5 (uncertain case) + // + // For each arc from end of F, search each case of extending + // F by that arc. + // + // before loop: save arcs from current path end, + // replace them with room for a single arc. + // extend F by room for one more arc, + ok = true + save := nc.a[fEnd] + nc.a[fEnd] = []Half{{}} + last := len(F.Path) + F.Path = append(F.Path, Half{}) + for _, h := range save { + // in each iteration, set the final arc in F, and the single + // outgoing arc, and save and clear all inbound arcs to the + // new end node. make recursive call, then restore saved + // inbound arcs for the node. + F.Path[last] = h + nc.a[fEnd][0] = h + save := nc.cutTo(h.To) + ok = nc.all_nc(F) + nc.restore(save) + if !ok { + break + } + } + // after loop, restore saved outgoing arcs in g. + nc.a[fEnd] = save + return +} + +type arc struct { + n NI // node that had an arc cut from its toList + x int // index of arc that was swapped to the end of the list +} + +// modify a cutting all arcs to node n. return list of cut arcs than +// can be processed in reverse order to restore changes to a +func (nc *negCyc) cutTo(n NI) (c []arc) { + for _, fr := range nc.tr[n] { + toList := nc.a[fr] + for x := 0; x < len(toList); { + to := toList[x] + if to.To == n { + c = append(c, arc{fr, x}) + last := len(toList) - 1 + toList[x], toList[last] = toList[last], toList[x] + toList = toList[:last] + } else { + x++ + } + } + nc.a[fr] = toList + } + return +} + +func (nc *negCyc) restore(c []arc) { + for i := len(c) - 1; i >= 0; i-- { + r := c[i] + toList := nc.a[r.n] + last := len(toList) + toList = toList[:last+1] + toList[r.x], toList[last] = toList[last], toList[r.x] + nc.a[r.n] = toList + } +} + +func (nc *negCyc) zL(F LabeledPath, fEnd NI, wp float64) (float64, []Half) { + π, c, d := nc.πj(len(nc.a)-len(F.Path), F.Start, fEnd) + if c < 0 { + return d + wp, π + } + j := len(nc.a) - len(F.Path) - 1 + // G1: cut arcs going to c + saveFr := nc.cutTo(c) + for k := 1; k <= j; k++ { + nc.dc[k] = nc.dj(k, F.Start, c) + } + // G0: also cut arcs coming from c + saveTo := nc.a[c] + nc.a[c] = nil + min := nc.dj(j, F.Start, fEnd) + // G2: restore arcs going to c + nc.restore(saveFr) + for k := 1; k <= j; k++ { + d1 := nc.dc[k] + nc.dj(j+1-k, c, fEnd) + if d1 < min { + min = d1 + } + } + nc.a[c] = saveTo + return min + wp, nil +} + +func (nc *negCyc) dj(j int, v, v0 NI) float64 { + for i := range nc.d0 { + nc.d0[i] = math.Inf(1) + } + nc.d0[v0] = 0 + for ; j > 0; j-- { + for i, d := range nc.d0 { + nc.d1[i] = d + } + for vʹ, d0vʹ := range nc.d0 { + if d0vʹ < math.Inf(1) { + for _, to := range nc.a[vʹ] { + if sum := d0vʹ + nc.w(to.Label); sum < nc.d1[to.To] { + nc.d1[to.To] = sum + } + } + } + } + nc.d0, nc.d1 = nc.d1, nc.d0 + } + return nc.d0[v] +} + +func (nc *negCyc) πj(j int, v, v0 NI) ([]Half, NI, float64) { + for i := range nc.d0 { + nc.d0[i] = math.Inf(1) + nc.btLast[i] = -1 + } + nc.d0[v0] = 0 + for k := 0; k < j; k++ { + for i, d := range nc.d0 { + nc.d1[i] = d + } + btk := nc.bt[k] + for vʹ, d0vʹ := range nc.d0 { + if d0vʹ < math.Inf(1) { + for _, to := range nc.a[vʹ] { + if sum := d0vʹ + nc.w(to.Label); sum < nc.d1[to.To] { + nc.d1[to.To] = sum + btk[to.To] = fromHalf{NI(vʹ), to.Label} + nc.btLast[to.To] = k + } + } + } + } + nc.d0, nc.d1 = nc.d1, nc.d0 + } + p := make([]Half, nc.btLast[v]+1) + m := map[NI]bool{} + c := NI(-1) + to := v + for k := nc.btLast[v]; k >= 0; k-- { + fh := nc.bt[k][to] + p[k] = Half{to, fh.Label} + to = fh.From + if c < 0 { + if m[to] { + c = to + } else { + m[to] = true + } + } + } + return p, c, nc.d0[v] +} + +func (nc *negCyc) zΓ(F LabeledPath, wp float64) []Half { + p, d := nc.a.DijkstraPath(F.Path[len(F.Path)-1].To, F.Start, nc.w) + if !(wp+d < 0) { + return nil + } + return p.Path +} + +// SpanTree builds a tree spanning nodes reachable from the given root. +// +// The component is spanned by breadth-first search from root. +// The resulting spanning tree in stored a FromList, and arc labels optionally +// stored in a slice. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of the returned FromList is populated +// with both From and Len values. The MaxLen member will be updated but +// not Leaves. +// +// The labels slice will be populated only if it is same length as g. +// Nil can be passed for example if labels are not needed. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// reachable from root, and a bool indicating if these nodes were found to be +// a simply connected tree in the receiver graph g. Any cycles, loops, +// or parallel arcs in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid spanning tree. +func (g LabeledDirected) SpanTree(root NI, f *FromList, labels []LI) (nSpanned int, simpleTree bool) { + a := g.LabeledAdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simpleTree = true + p[root].Len = 1 + type arc struct { + from NI + half Half + } + var next []arc + frontier := []arc{{-1, Half{root, -1}}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.half.To].Len + 1 + for _, to := range a[fa.half.To] { + if p[to.To].Len > 0 { + simpleTree = false + continue + } + p[to.To] = PathEnd{From: fa.half.To, Len: l} + if len(labels) == len(p) { + labels[to.To] = to.Label + } + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.half.To, to}) + } + } + frontier, next = next, frontier[:0] + } + return +} + +// Transpose constructs a new adjacency list that is the transpose of g. +// +// For every arc from->to of g, the result will have an arc to->from. +// Transpose also counts arcs as it traverses and returns ma the number of +// arcs in g (equal to the number of arcs in the result.) +func (g LabeledDirected) Transpose() (t LabeledDirected, ma int) { + ta := make(LabeledAdjacencyList, g.Order()) + for n, nbs := range g.LabeledAdjacencyList { + for _, nb := range nbs { + ta[nb.To] = append(ta[nb.To], Half{To: NI(n), Label: nb.Label}) + ma++ + } + } + return LabeledDirected{ta}, ma +} + +// Undirected returns a new undirected graph derived from g, augmented as +// needed to make it undirected, with reciprocal arcs having matching labels. +func (g LabeledDirected) Undirected() LabeledUndirected { + c, _ := g.LabeledAdjacencyList.Copy() // start with a copy + // "reciprocals wanted" + rw := make(LabeledAdjacencyList, g.Order()) + for fr, to := range g.LabeledAdjacencyList { + arc: // for each arc in g + for _, to := range to { + if to.To == NI(fr) { + continue // arc is a loop + } + // search wanted arcs + wf := rw[fr] + for i, w := range wf { + if w == to { // found, remove + last := len(wf) - 1 + wf[i] = wf[last] + rw[fr] = wf[:last] + continue arc + } + } + // arc not found, add to reciprocal to wanted list + rw[to.To] = append(rw[to.To], Half{To: NI(fr), Label: to.Label}) + } + } + // add missing reciprocals + for fr, to := range rw { + c[fr] = append(c[fr], to...) + } + return LabeledUndirected{c} +} + +// Unlabeled constructs the unlabeled directed graph corresponding to g. +func (g LabeledDirected) Unlabeled() Directed { + return Directed{g.LabeledAdjacencyList.Unlabeled()} +} + +// UnlabeledTranspose constructs a new adjacency list that is the unlabeled +// transpose of g. +// +// For every arc from->to of g, the result will have an arc to->from. +// Transpose also counts arcs as it traverses and returns ma, the number of +// arcs in g (equal to the number of arcs in the result.) +// +// It is equivalent to g.Unlabeled().Transpose() but constructs the result +// directly. +func (g LabeledDirected) UnlabeledTranspose() (t Directed, ma int) { + ta := make(AdjacencyList, g.Order()) + for n, nbs := range g.LabeledAdjacencyList { + for _, nb := range nbs { + ta[nb.To] = append(ta[nb.To], NI(n)) + ma++ + } + } + return Directed{ta}, ma +} + +// DominanceFrontiers holds dominance frontiers for all nodes in some graph. +// The frontier for a given node is a set of nodes, represented here as a map. +type DominanceFrontiers []map[NI]struct{} + +// Frontier computes the dominance frontier for a node set. +func (d DominanceFrontiers) Frontier(s map[NI]struct{}) map[NI]struct{} { + fs := map[NI]struct{}{} + for n := range s { + for f := range d[n] { + fs[f] = struct{}{} + } + } + return fs +} + +// Closure computes the closure, or iterated dominance frontier for a node set. +func (d DominanceFrontiers) Closure(s map[NI]struct{}) map[NI]struct{} { + c := map[NI]struct{}{} + e := map[NI]struct{}{} + w := map[NI]struct{}{} + var n NI + for n = range s { + e[n] = struct{}{} + w[n] = struct{}{} + } + for len(w) > 0 { + for n = range w { + break + } + delete(w, n) + for f := range d[n] { + if _, ok := c[f]; !ok { + c[f] = struct{}{} + if _, ok := e[f]; !ok { + e[f] = struct{}{} + w[f] = struct{}{} + } + } + } + } + return c +} + +// Dominators holds immediate dominators. +// +// Dominators is a return type from methods Dominators, PostDominators, and +// Doms. See those methods for construction examples. +// +// The list of immediate dominators represents the "dominator tree" +// (in the same way a FromList represents a tree, but somewhat lighter weight.) +// +// In addition to the exported immediate dominators, the type also retains +// the transpose graph that was used to compute the dominators. +// See PostDominators and Doms for a caution about modifying the transpose +// graph. +type Dominators struct { + Immediate []NI + from interface { // either Directed or LabeledDirected + domFrontiers(Dominators) DominanceFrontiers + } +} + +// Frontiers constructs the dominator frontier for each node. +// +// The frontier for a node is a set of nodes, represented as a map. The +// returned slice has the length of d.Immediate, which is the length of +// the original graph. The frontier is valid however only for nodes of the +// reachable subgraph. Nodes not in the reachable subgraph, those with a +// d.Immediate value of -1, will have a nil map. +func (d Dominators) Frontiers() DominanceFrontiers { + return d.from.domFrontiers(d) +} + +// Set constructs the dominator set for a given node. +// +// The dominator set for a node always includes the node itself as the first +// node in the returned slice, as long as the node was in the subgraph +// reachable from the start node used to construct the dominators. +// If the argument n is a node not in the subgraph, Set returns nil. +func (d Dominators) Set(n NI) []NI { + im := d.Immediate + if im[n] < 0 { + return nil + } + for s := []NI{n}; ; { + if p := im[n]; p < 0 || p == n { + return s + } else { + s = append(s, p) + n = p + } + } +} + +// starting at the node on the top of the stack, follow arcs until stuck. +// mark nodes visited, push nodes on stack, remove arcs from g. +func (e *eulerian) push() { + for u := e.top(); ; { + e.uv.SetBit(int(u), 0) // reset unvisited bit + arcs := e.g[u] + if len(arcs) == 0 { + return // stuck + } + w := arcs[0] // follow first arc + e.s++ // push followed node on stack + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + u = w + } +} + +func (e *labEulerian) push() { + for u := e.top().To; ; { + e.uv.SetBit(int(u), 0) // reset unvisited bit + arcs := e.g[u] + if len(arcs) == 0 { + return // stuck + } + w := arcs[0] // follow first arc + e.s++ // push followed node on stack + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + u = w.To + } +} diff --git a/vendor/github.com/soniakeys/graph/dir_RO.go b/vendor/github.com/soniakeys/graph/dir_RO.go new file mode 100644 index 0000000..6d43d12 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/dir_RO.go @@ -0,0 +1,1091 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + +// dir_RO.go is code generated from dir_cg.go by directives in graph.go. +// Editing dir_cg.go is okay. It is the code generation source. +// DO NOT EDIT dir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. + +// Balanced returns true if for every node in g, in-degree equals out-degree. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Balanced() bool { + for n, in := range g.InDegree() { + if in != len(g.AdjacencyList[n]) { + return false + } + } + return true +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Copy() (c Directed, ma int) { + l, s := g.AdjacencyList.Copy() + return Directed{l}, s +} + +// Cyclic determines if g contains a cycle, a non-empty path from a node +// back to itself. +// +// Cyclic returns true if g contains at least one cycle. It also returns +// an example of an arc involved in a cycle. +// Cyclic returns false if g is acyclic. +// +// Also see Topological, which detects cycles. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Cyclic() (cyclic bool, fr NI, to NI) { + a := g.AdjacencyList + fr, to = -1, -1 + temp := bits.New(len(a)) + perm := bits.New(len(a)) + var df func(int) + df = func(n int) { + switch { + case temp.Bit(n) == 1: + cyclic = true + return + case perm.Bit(n) == 1: + return + } + temp.SetBit(n, 1) + for _, nb := range a[n] { + df(int(nb)) + if cyclic { + if fr < 0 { + fr, to = NI(n), nb + } + return + } + } + temp.SetBit(n, 0) + perm.SetBit(n, 1) + } + for n := range a { + if perm.Bit(n) == 1 { + continue + } + if df(n); cyclic { // short circuit as soon as a cycle is found + break + } + } + return +} + +// DegreeCentralization returns out-degree centralization. +// +// Out-degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple directed graphs of +// two or more nodes. As a special case, 0 is returned for graphs of 0 or 1 +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// In-degree centralization can be computed as DegreeCentralization of the +// transpose. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) DegreeCentralization() float64 { + a := g.AdjacencyList + if len(a) <= 1 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + l1 := len(a) - 1 + return float64(len(a)*max-sum) / float64(l1*l1) +} + +// Dominators computes the immediate dominator for each node reachable from +// start. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph reachable from start. If you happen to have either of these +// computed anyway, it can be more efficient to call Doms directly. +func (g Directed) Dominators(start NI) Dominators { + a := g.AdjacencyList + l := len(a) + // ExampleDoms shows traditional depth-first postorder, but it works to + // generate a reverse preorder. Also breadth-first works instead of + // depth-first and may allow Doms to run a little faster by presenting + // a shallower tree. + post := make([]NI, l) + a.BreadthFirst(start, func(n NI) { + l-- + post[l] = n + }) + tr, _ := g.Transpose() + return g.Doms(tr, post[l:]) +} + +// Doms computes either immediate dominators or postdominators. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// But see also the simpler methods Dominators and PostDominators. +// +// Doms requires argument tr to be the transpose graph of receiver g, +// and requres argument post to be a post ordering of receiver g. More +// specifically a post ordering of a spanning tree of the subgraph reachable +// from some start node in g. The start node will always be the last node in +// this postordering so it does not need to passed as a separate argument. +// +// Doms can be used to construct either dominators or postdominators. +// To construct dominators on a graph f, generate a postordering p on f +// and call f.Doms(f.Transpose(), p). To construct postdominators, generate +// the transpose t first, then a postordering p on t (not f), and call +// t.Doms(f, p). +// +// Caution: The argument tr is retained in the returned Dominators object +// and is used by the method Dominators.Frontier. It is not deep-copied +// so it is invalid to call Doms, modify the tr graph, and then call Frontier. +func (g Directed) Doms(tr Directed, post []NI) Dominators { + a := g.AdjacencyList + dom := make([]NI, len(a)) + pi := make([]int, len(a)) + for i, n := range post { + pi[n] = i + } + intersect := func(b1, b2 NI) NI { + for b1 != b2 { + for pi[b1] < pi[b2] { + b1 = dom[b1] + } + for pi[b2] < pi[b1] { + b2 = dom[b2] + } + } + return b1 + } + for n := range dom { + dom[n] = -1 + } + start := post[len(post)-1] + dom[start] = start + for changed := false; ; changed = false { + for i := len(post) - 2; i >= 0; i-- { + b := post[i] + var im NI + fr := tr.AdjacencyList[b] + var j int + var fp NI + for j, fp = range fr { + if dom[fp] >= 0 { + im = fp + break + } + } + for _, p := range fr[j:] { + if dom[p] >= 0 { + im = intersect(im, p) + } + } + if dom[b] != im { + dom[b] = im + changed = true + } + } + if !changed { + return Dominators{dom, tr} + } + } +} + +// PostDominators computes the immediate postdominator for each node that can +// reach node end. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph of the transpose reachable from end. If you happen to have either +// of these computed anyway, it can be more efficient to call Doms directly. +// +// See the method Doms anyway for the caution note. PostDominators calls +// Doms internally, passing receiver g as Doms argument tr. The caution means +// that it is invalid to call PostDominators, modify the graph g, then call +// Frontier. +func (g Directed) PostDominators(end NI) Dominators { + tr, _ := g.Transpose() + a := tr.AdjacencyList + l := len(a) + post := make([]NI, l) + a.BreadthFirst(end, func(n NI) { + l-- + post[l] = n + }) + return tr.Doms(g, post[l:]) +} + +// called from Dominators.Frontier via interface +func (from Directed) domFrontiers(d Dominators) DominanceFrontiers { + im := d.Immediate + f := make(DominanceFrontiers, len(im)) + for i := range f { + if im[i] >= 0 { + f[i] = map[NI]struct{}{} + } + } + for b, fr := range from.AdjacencyList { + if len(fr) < 2 { + continue + } + imb := im[b] + for _, p := range fr { + for runner := p; runner != imb; runner = im[runner] { + f[runner][NI(b)] = struct{}{} + } + } + } + return f +} + +// Eulerian scans a directed graph to determine if it is Eulerian. +// +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. +// +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the start and end nodes of the path, and nil. +// +// Otherwise it returns an error indicating a reason the graph is non-Eulerian. +// Also in this case it returns a relevant node in either start or end. +// +// See also method EulerianStart, which short-circuits when it finds a start +// node whereas this method completely validates a graph as Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Eulerian() (start, end NI, err error) { + ind := g.InDegree() + start = -1 + end = -1 + for n, to := range g.AdjacencyList { + switch { + case len(to) > ind[n]: + if start >= 0 { + return NI(n), -1, errors.New("multiple start candidates") + } + if len(to) > ind[n]+1 { + return NI(n), -1, errors.New("excessive out-degree") + } + start = NI(n) + case ind[n] > len(to): + if end >= 0 { + return -1, NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return -1, NI(n), errors.New("excessive in-degree") + } + end = NI(n) + } + } + return start, end, nil +} + +// EulerianCycle finds an Eulerian cycle in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are nearly equivalent labeled and unlabeled versions of this method. +// In the labeled version the first element of of the +func (g Directed) EulerianCycle() ([]NI, error) { + c, m := g.Copy() + return c.EulerianCycleD(m) +} + +// EulerianCycleD finds an Eulerian cycle in a directed multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianCycleD(ma int) ([]NI, error) { + // algorithm adapted from "Sketch of Eulerian Circuit Algorithm" by + // Carl Lee, accessed at http://www.ms.uky.edu/~lee/ma515fa10/euler.pdf. + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, ma) + e.p[0] = 0 + for e.s >= 0 { + v := e.top() // v is node that starts cycle + e.push() + // if Eulerian, we'll always come back to starting node + if e.top() != v { + return nil, errors.New("not Eulerian") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianPath() ([]NI, error) { + c, m := g.Copy() + start, err := c.EulerianStart() + if err != nil { + return nil, err + } + if start < 0 { + start = 0 + } + return c.EulerianPathD(m, start) +} + +// EulerianPathD finds an Eulerian path in a directed multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianPathD(ma int, start NI) ([]NI, error) { + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, ma) + e.p[0] = start + // unlike EulerianCycle, the first path doesn't have to be a cycle. + e.push() + e.keep() + for e.s >= 0 { + start = e.top() + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top() != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A candidate start node in the directed case has out-degree one greater then +// in-degree. EulerianStart scans the graph returning immediately with the +// node (and err == nil) when it finds such a candidate. +// +// EulerianStart also returns immediately with an error if it finds the graph +// cannot contain an Eulerian path. In this case it also returns a relevant +// node. +// +// If the scan completes without finding a candidate start node, the graph +// represents an Eulerian cycle. In this case it returns -1, nil, and any +// node can be chosen as a start node for an eulerian path. +// +// See also method Eulerian, which completely validates a graph as Eulerian +// whereas this method short-curcuits when it finds a start node. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianStart() (start NI, err error) { + ind := g.InDegree() + end := -1 + for n, to := range g.AdjacencyList { + switch { + case len(to) > ind[n]: + if len(to) == ind[n]+1 { + return NI(n), nil // candidate start + } + return -1, errors.New("excessive out-degree") + case ind[n] > len(to): + if end >= 0 { + return NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return NI(n), errors.New("excessive in-degree") + } + end = n + } + } + return -1, nil // cycle +} + +type eulerian struct { + g AdjacencyList // working copy of graph, it gets consumed + m int // number of arcs in g, updated as g is consumed + uv bits.Bits // unvisited + // low end of p is stack of unfinished nodes + // high end is finished path + p []NI // stack + path + s int // stack pointer +} + +func newEulerian(g AdjacencyList, m int) *eulerian { + e := &eulerian{ + g: g, + m: m, + uv: bits.New(len(g)), + p: make([]NI, m+1), + } + e.uv.SetAll() + return e +} + +// starting with the node on top of the stack, move nodes with no arcs. +func (e *eulerian) keep() { + for e.s >= 0 { + n := e.top() + if len(e.g[n]) > 0 { + break + } + e.p[e.m] = n + e.s-- + e.m-- + } +} + +func (e *eulerian) top() NI { + return e.p[e.s] +} + +// MaximalNonBranchingPaths finds all paths in a directed graph that are +// "maximal" and "non-branching". +// +// A non-branching path is one where path nodes other than the first and last +// have exactly one arc leading to the node and one arc leading from the node, +// thus there is no possibility to branch away to a different path. +// +// A maximal non-branching path cannot be extended to a longer non-branching +// path by including another node at either end. +// +// In the case of a cyclic non-branching path, the first and last nodes +// of the path will be the same node, indicating an isolated cycle. +// +// The method calls the emit argument for each path or isolated cycle in g, +// as long as emit returns true. If emit returns false, +// MaximalNonBranchingPaths returns immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) MaximalNonBranchingPaths(emit func([]NI) bool) { + a := g.AdjacencyList + ind := g.InDegree() + uv := bits.New(g.Order()) + uv.SetAll() + for v, vTo := range a { + if !(ind[v] == 1 && len(vTo) == 1) { + for _, w := range vTo { + n := []NI{NI(v), w} + uv.SetBit(v, 0) + uv.SetBit(int(w), 0) + wTo := a[w] + for ind[w] == 1 && len(wTo) == 1 { + u := wTo[0] + n = append(n, u) + uv.SetBit(int(u), 0) + w = u + wTo = a[w] + } + if !emit(n) { // n is a path + return + } + } + } + } + // use uv.From rather than uv.Iterate. + // Iterate doesn't work here because we're modifying uv + for b := uv.OneFrom(0); b >= 0; b = uv.OneFrom(b + 1) { + v := NI(b) + n := []NI{v} + for w := v; ; { + w = a[w][0] + uv.SetBit(int(w), 0) + n = append(n, w) + if w == v { + break + } + } + if !emit(n) { // n is an isolated cycle + return + } + } +} + +// InDegree computes the in-degree of each node in g +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) InDegree() []int { + ind := make([]int, g.Order()) + for _, nbs := range g.AdjacencyList { + for _, nb := range nbs { + ind[nb]++ + } + } + return ind +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *DirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.Directed.AdjacencyList + b = NI(len(a)) + s.Directed.AdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *DirectedSubgraph) AddArc(fr NI, to NI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to) < 0 || int(to) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.Directed.AdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } + } + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super).AdjacencyList[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to = s.AddNode(to) + s.Directed.AdjacencyList[bf] = + append(s.Directed.AdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Directed) InduceList(l []NI) *DirectedSubgraph { + sub, sup := mapList(l) + return &DirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Directed: Directed{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Directed) InduceBits(t bits.Bits) *DirectedSubgraph { + sub, sup := mapBits(t) + return &DirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Directed: Directed{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + +// IsTree identifies trees in directed graphs. +// +// Return value isTree is true if the subgraph reachable from root is a tree. +// Further, return value allTree is true if the entire graph g is reachable +// from root. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) IsTree(root NI) (isTree, allTree bool) { + a := g.AdjacencyList + v := bits.New(len(a)) + v.SetAll() + var df func(NI) bool + df = func(n NI) bool { + if v.Bit(int(n)) == 0 { + return false + } + v.SetBit(int(n), 0) + for _, to := range a[n] { + if !df(to) { + return false + } + } + return true + } + isTree = df(root) + return isTree, isTree && v.AllZeros() +} + +// PageRank computes a significance score for each node of a graph. +// +// The algorithm is credited to Google founders Brin and Lawrence. +// +// Argument d is a damping factor. Reportedly a value of .85 works well. +// Argument n is a number of iterations. Reportedly values of 20 to 50 +// work well. +// +// Returned is the PageRank score for each node of g. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) PageRank(d float64, n int) []float64 { + // Following "PageRank Explained" by Ian Rogers, accessed at + // http://www.cs.princeton.edu/~chazelle/courses/BIB/pagerank.htm + a := g.AdjacencyList + p0 := make([]float64, len(a)) + p1 := make([]float64, len(a)) + for i := range p0 { + p0[i] = 1 + } + d1 := 1 - d + for ; n > 0; n-- { + for i := range p1 { + p1[i] = d1 + } + for fr, to := range a { + f := d / float64(len(to)) + for _, to := range to { + p1[to] += p0[fr] * f + } + } + p0, p1 = p1, p0 + } + return p0 +} + +// StronglyConnectedComponents identifies strongly connected components in +// a directed graph. +// +// The method calls the emit function for each component identified. The +// argument to emit is the node list of a component. The emit function must +// return true for the method to continue identifying components. If emit +// returns false, the method returns immediately. +// +// Note well: The backing slice for the node list passed to emit is reused +// across emit calls. If you need to retain the node list you must copy it. +// +// The components emitted represent a partition of the nodes in g. +// So for example, if the first component emitted has the same length as g +// then it will be the only component and it means the entire graph g is +// strongly connected. +// +// See also Condensation which returns a condensation graph in addition +// to the strongly connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// The algorithm here is by David Pearce. See also alt.SCCPathBased and +// alt.SCCTarjan. +func (g Directed) StronglyConnectedComponents(emit func([]NI) bool) { + // See Algorithm 3 PEA FIND SCC2(V,E) in "An Improved Algorithm for + // Finding the Strongly Connected Components of a Directed Graph" + // by David J. Pearce. + a := g.AdjacencyList + rindex := make([]int, len(a)) + var S, scc []NI + index := 1 + c := len(a) - 1 + var visit func(NI) bool + visit = func(v NI) bool { + root := true + rindex[v] = index + index++ + for _, w := range a[v] { + if rindex[w] == 0 { + if !visit(w) { + return false + } + } + if rindex[w] < rindex[v] { + rindex[v] = rindex[w] + root = false + } + } + if !root { + S = append(S, v) + return true + } + scc = scc[:0] + index-- + for last := len(S) - 1; last >= 0; last-- { + w := S[last] + if rindex[v] > rindex[w] { + break + } + S = S[:last] + rindex[w] = c + scc = append(scc, w) + index-- + } + rindex[v] = c + c-- + return emit(append(scc, v)) + } + for v := range a { + if rindex[v] == 0 && !visit(NI(v)) { + break + } + } +} + +// Condensation returns strongly connected components and their +// condensation graph. +// +// A condensation represents a directed acyclic graph. +// Components are ordered in a reverse topological ordering. +// +// See also StronglyConnectedComponents, which returns the components only. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Condensation() (scc [][]NI, cd AdjacencyList) { + a := g.AdjacencyList + b := make([]NI, len(a)) // backing slice for scc + g.StronglyConnectedComponents(func(c []NI) bool { + n := copy(b, c) + scc = append(scc, b[:n]) + b = b[n:] + return true + }) + cd = make(AdjacencyList, len(scc)) // return value + cond := make([]NI, len(a)) // mapping from g node to cd node + for cn, c := range scc { + for _, n := range c { + cond[n] = NI(cn) // map g node to cd node + } + var tos []NI // list of 'to' nodes + m := bits.New(len(cd)) // tos map + m.SetBit(cn, 1) + for _, n := range c { + for _, to := range a[n] { + if ct := cond[to]; m.Bit(int(ct)) == 0 { + m.SetBit(int(ct), 1) + tos = append(tos, ct) + } + } + } + cd[cn] = tos + } + return +} + +// Topological computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Topological() (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < g.Order() { + return NI(i) + } + return -1 + }) +} + +func (g Directed) dfTopo(f func() NI) (ordering, cycle []NI) { + a := g.AdjacencyList + ordering = make([]NI, len(a)) + i := len(ordering) + temp := bits.New(len(a)) + perm := bits.New(len(a)) + var cycleFound bool + var cycleStart NI + var df func(NI) + df = func(n NI) { + switch { + case temp.Bit(int(n)) == 1: + cycleFound = true + cycleStart = n + return + case perm.Bit(int(n)) == 1: + return + } + temp.SetBit(int(n), 1) + for _, nb := range a[n] { + df(nb) + if cycleFound { + if cycleStart >= 0 { + // a little hack: orderng won't be needed so repurpose the + // slice as cycle. this is read out in reverse order + // as the recursion unwinds. + x := len(ordering) - 1 - len(cycle) + ordering[x] = n + cycle = ordering[x:] + if n == cycleStart { + cycleStart = -1 + } + } + return + } + } + temp.SetBit(int(n), 0) + perm.SetBit(int(n), 1) + i-- + ordering[i] = n + } + for { + n := f() + if n < 0 { + return ordering[i:], nil + } + if perm.Bit(int(n)) == 1 { + continue + } + df(n) + if cycleFound { + return nil, cycle + } + } +} + +// TopologicalKahn computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// This function is based on the algorithm by Arthur Kahn and requires the +// transpose of g be passed as the argument. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) TopologicalKahn(tr Directed) (ordering, cycle []NI) { + // code follows Wikipedia pseudocode. + var L, S []NI + // rem for "remaining edges," this function makes a local copy of the + // in-degrees and consumes that instead of consuming an input. + rem := make([]int, g.Order()) + for n, fr := range tr.AdjacencyList { + if len(fr) == 0 { + // accumulate "set of all nodes with no incoming edges" + S = append(S, NI(n)) + } else { + // initialize rem from in-degree + rem[n] = len(fr) + } + } + for len(S) > 0 { + last := len(S) - 1 // "remove a node n from S" + n := S[last] + S = S[:last] + L = append(L, n) // "add n to tail of L" + for _, m := range g.AdjacencyList[n] { + // WP pseudo code reads "for each node m..." but it means for each + // node m *remaining in the graph.* We consume rem rather than + // the graph, so "remaining in the graph" for us means rem[m] > 0. + if rem[m] > 0 { + rem[m]-- // "remove edge from the graph" + if rem[m] == 0 { // if "m has no other incoming edges" + S = append(S, m) // "insert m into S" + } + } + } + } + // "If graph has edges," for us means a value in rem is > 0. + for c, in := range rem { + if in > 0 { + // recover cyclic nodes + for _, nb := range g.AdjacencyList[c] { + if rem[nb] > 0 { + cycle = append(cycle, NI(c)) + break + } + } + } + } + if len(cycle) > 0 { + return nil, cycle + } + return L, nil +} + +// TopologicalSubgraph computes a topological ordering of a subgraph of a +// directed acyclic graph. +// +// The subgraph considered is that reachable from the specified node list. +// +// For an acyclic subgraph, return value ordering is a permutation of reachable +// node numbers in topologically sorted order and cycle will be nil. If the +// subgraph is found to be cyclic, ordering will be nil and cycle will be +// the path of a found cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) TopologicalSubgraph(nodes []NI) (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < len(nodes) { + return nodes[i] + } + return -1 + }) +} + +// TransitiveClosure returns the transitive closure of directed graph g. +// +// The algorithm is Warren's, which works most naturally with an adjacency +// matrix representation. The returned transitive closure is left in this +// adjacency matrix representation. For a graph g of order n, matrix tc +// is returned as a length n slice of length n bits.Bits values, where +// tc[from].Bit(to) == 1 represents an arc of the transitive closure. +func (g Directed) TransitiveClosure() []bits.Bits { + // construct adjacency matrix + a := g.AdjacencyList + t := make([]bits.Bits, len(a)) + for n := range t { + tn := bits.New(len(a)) + for _, to := range a[n] { + tn.SetBit(int(to), 1) + } + t[n] = tn + } + // above diagonal + for i := 1; i < len(a); i++ { + ti := t[i] + for k := 0; k < i; k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + // below diagonal + for i, ti := range t[:len(a)-1] { + for k := i + 1; k < len(a); k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + return t +} diff --git a/vendor/github.com/soniakeys/graph/dir_cg.go b/vendor/github.com/soniakeys/graph/dir_cg.go new file mode 100644 index 0000000..07cc965 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/dir_cg.go @@ -0,0 +1,1091 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + +// dir_RO.go is code generated from dir_cg.go by directives in graph.go. +// Editing dir_cg.go is okay. It is the code generation source. +// DO NOT EDIT dir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. + +// Balanced returns true if for every node in g, in-degree equals out-degree. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Balanced() bool { + for n, in := range g.InDegree() { + if in != len(g.LabeledAdjacencyList[n]) { + return false + } + } + return true +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Copy() (c LabeledDirected, ma int) { + l, s := g.LabeledAdjacencyList.Copy() + return LabeledDirected{l}, s +} + +// Cyclic determines if g contains a cycle, a non-empty path from a node +// back to itself. +// +// Cyclic returns true if g contains at least one cycle. It also returns +// an example of an arc involved in a cycle. +// Cyclic returns false if g is acyclic. +// +// Also see Topological, which detects cycles. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Cyclic() (cyclic bool, fr NI, to Half) { + a := g.LabeledAdjacencyList + fr, to.To = -1, -1 + temp := bits.New(len(a)) + perm := bits.New(len(a)) + var df func(int) + df = func(n int) { + switch { + case temp.Bit(n) == 1: + cyclic = true + return + case perm.Bit(n) == 1: + return + } + temp.SetBit(n, 1) + for _, nb := range a[n] { + df(int(nb.To)) + if cyclic { + if fr < 0 { + fr, to = NI(n), nb + } + return + } + } + temp.SetBit(n, 0) + perm.SetBit(n, 1) + } + for n := range a { + if perm.Bit(n) == 1 { + continue + } + if df(n); cyclic { // short circuit as soon as a cycle is found + break + } + } + return +} + +// DegreeCentralization returns out-degree centralization. +// +// Out-degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple directed graphs of +// two or more nodes. As a special case, 0 is returned for graphs of 0 or 1 +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// In-degree centralization can be computed as DegreeCentralization of the +// transpose. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) DegreeCentralization() float64 { + a := g.LabeledAdjacencyList + if len(a) <= 1 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + l1 := len(a) - 1 + return float64(len(a)*max-sum) / float64(l1*l1) +} + +// Dominators computes the immediate dominator for each node reachable from +// start. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph reachable from start. If you happen to have either of these +// computed anyway, it can be more efficient to call Doms directly. +func (g LabeledDirected) Dominators(start NI) Dominators { + a := g.LabeledAdjacencyList + l := len(a) + // ExampleDoms shows traditional depth-first postorder, but it works to + // generate a reverse preorder. Also breadth-first works instead of + // depth-first and may allow Doms to run a little faster by presenting + // a shallower tree. + post := make([]NI, l) + a.BreadthFirst(start, func(n NI) { + l-- + post[l] = n + }) + tr, _ := g.Transpose() + return g.Doms(tr, post[l:]) +} + +// Doms computes either immediate dominators or postdominators. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// But see also the simpler methods Dominators and PostDominators. +// +// Doms requires argument tr to be the transpose graph of receiver g, +// and requres argument post to be a post ordering of receiver g. More +// specifically a post ordering of a spanning tree of the subgraph reachable +// from some start node in g. The start node will always be the last node in +// this postordering so it does not need to passed as a separate argument. +// +// Doms can be used to construct either dominators or postdominators. +// To construct dominators on a graph f, generate a postordering p on f +// and call f.Doms(f.Transpose(), p). To construct postdominators, generate +// the transpose t first, then a postordering p on t (not f), and call +// t.Doms(f, p). +// +// Caution: The argument tr is retained in the returned Dominators object +// and is used by the method Dominators.Frontier. It is not deep-copied +// so it is invalid to call Doms, modify the tr graph, and then call Frontier. +func (g LabeledDirected) Doms(tr LabeledDirected, post []NI) Dominators { + a := g.LabeledAdjacencyList + dom := make([]NI, len(a)) + pi := make([]int, len(a)) + for i, n := range post { + pi[n] = i + } + intersect := func(b1, b2 NI) NI { + for b1 != b2 { + for pi[b1] < pi[b2] { + b1 = dom[b1] + } + for pi[b2] < pi[b1] { + b2 = dom[b2] + } + } + return b1 + } + for n := range dom { + dom[n] = -1 + } + start := post[len(post)-1] + dom[start] = start + for changed := false; ; changed = false { + for i := len(post) - 2; i >= 0; i-- { + b := post[i] + var im NI + fr := tr.LabeledAdjacencyList[b] + var j int + var fp Half + for j, fp = range fr { + if dom[fp.To] >= 0 { + im = fp.To + break + } + } + for _, p := range fr[j:] { + if dom[p.To] >= 0 { + im = intersect(im, p.To) + } + } + if dom[b] != im { + dom[b] = im + changed = true + } + } + if !changed { + return Dominators{dom, tr} + } + } +} + +// PostDominators computes the immediate postdominator for each node that can +// reach node end. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph of the transpose reachable from end. If you happen to have either +// of these computed anyway, it can be more efficient to call Doms directly. +// +// See the method Doms anyway for the caution note. PostDominators calls +// Doms internally, passing receiver g as Doms argument tr. The caution means +// that it is invalid to call PostDominators, modify the graph g, then call +// Frontier. +func (g LabeledDirected) PostDominators(end NI) Dominators { + tr, _ := g.Transpose() + a := tr.LabeledAdjacencyList + l := len(a) + post := make([]NI, l) + a.BreadthFirst(end, func(n NI) { + l-- + post[l] = n + }) + return tr.Doms(g, post[l:]) +} + +// called from Dominators.Frontier via interface +func (from LabeledDirected) domFrontiers(d Dominators) DominanceFrontiers { + im := d.Immediate + f := make(DominanceFrontiers, len(im)) + for i := range f { + if im[i] >= 0 { + f[i] = map[NI]struct{}{} + } + } + for b, fr := range from.LabeledAdjacencyList { + if len(fr) < 2 { + continue + } + imb := im[b] + for _, p := range fr { + for runner := p.To; runner != imb; runner = im[runner] { + f[runner][NI(b)] = struct{}{} + } + } + } + return f +} + +// Eulerian scans a directed graph to determine if it is Eulerian. +// +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. +// +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the start and end nodes of the path, and nil. +// +// Otherwise it returns an error indicating a reason the graph is non-Eulerian. +// Also in this case it returns a relevant node in either start or end. +// +// See also method EulerianStart, which short-circuits when it finds a start +// node whereas this method completely validates a graph as Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Eulerian() (start, end NI, err error) { + ind := g.InDegree() + start = -1 + end = -1 + for n, to := range g.LabeledAdjacencyList { + switch { + case len(to) > ind[n]: + if start >= 0 { + return NI(n), -1, errors.New("multiple start candidates") + } + if len(to) > ind[n]+1 { + return NI(n), -1, errors.New("excessive out-degree") + } + start = NI(n) + case ind[n] > len(to): + if end >= 0 { + return -1, NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return -1, NI(n), errors.New("excessive in-degree") + } + end = NI(n) + } + } + return start, end, nil +} + +// EulerianCycle finds an Eulerian cycle in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are nearly equivalent labeled and unlabeled versions of this method. +// In the labeled version the first element of of the +func (g LabeledDirected) EulerianCycle() ([]Half, error) { + c, m := g.Copy() + return c.EulerianCycleD(m) +} + +// EulerianCycleD finds an Eulerian cycle in a directed multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianCycleD(ma int) ([]Half, error) { + // algorithm adapted from "Sketch of Eulerian Circuit Algorithm" by + // Carl Lee, accessed at http://www.ms.uky.edu/~lee/ma515fa10/euler.pdf. + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, ma) + e.p[0] = Half{0, -1} + for e.s >= 0 { + v := e.top() // v is node that starts cycle + e.push() + // if Eulerian, we'll always come back to starting node + if e.top().To != v.To { + return nil, errors.New("not Eulerian") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianPath() ([]Half, error) { + c, m := g.Copy() + start, err := c.EulerianStart() + if err != nil { + return nil, err + } + if start < 0 { + start = 0 + } + return c.EulerianPathD(m, start) +} + +// EulerianPathD finds an Eulerian path in a directed multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianPathD(ma int, start NI) ([]Half, error) { + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, ma) + e.p[0] = Half{start, -1} + // unlike EulerianCycle, the first path doesn't have to be a cycle. + e.push() + e.keep() + for e.s >= 0 { + start = e.top().To + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top().To != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A candidate start node in the directed case has out-degree one greater then +// in-degree. EulerianStart scans the graph returning immediately with the +// node (and err == nil) when it finds such a candidate. +// +// EulerianStart also returns immediately with an error if it finds the graph +// cannot contain an Eulerian path. In this case it also returns a relevant +// node. +// +// If the scan completes without finding a candidate start node, the graph +// represents an Eulerian cycle. In this case it returns -1, nil, and any +// node can be chosen as a start node for an eulerian path. +// +// See also method Eulerian, which completely validates a graph as Eulerian +// whereas this method short-curcuits when it finds a start node. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianStart() (start NI, err error) { + ind := g.InDegree() + end := -1 + for n, to := range g.LabeledAdjacencyList { + switch { + case len(to) > ind[n]: + if len(to) == ind[n]+1 { + return NI(n), nil // candidate start + } + return -1, errors.New("excessive out-degree") + case ind[n] > len(to): + if end >= 0 { + return NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return NI(n), errors.New("excessive in-degree") + } + end = n + } + } + return -1, nil // cycle +} + +type labEulerian struct { + g LabeledAdjacencyList // working copy of graph, it gets consumed + m int // number of arcs in g, updated as g is consumed + uv bits.Bits // unvisited + // low end of p is stack of unfinished nodes + // high end is finished path + p []Half // stack + path + s int // stack pointer +} + +func newLabEulerian(g LabeledAdjacencyList, m int) *labEulerian { + e := &labEulerian{ + g: g, + m: m, + uv: bits.New(len(g)), + p: make([]Half, m+1), + } + e.uv.SetAll() + return e +} + +// starting with the node on top of the stack, move nodes with no arcs. +func (e *labEulerian) keep() { + for e.s >= 0 { + n := e.top() + if len(e.g[n.To]) > 0 { + break + } + e.p[e.m] = n + e.s-- + e.m-- + } +} + +func (e *labEulerian) top() Half { + return e.p[e.s] +} + +// MaximalNonBranchingPaths finds all paths in a directed graph that are +// "maximal" and "non-branching". +// +// A non-branching path is one where path nodes other than the first and last +// have exactly one arc leading to the node and one arc leading from the node, +// thus there is no possibility to branch away to a different path. +// +// A maximal non-branching path cannot be extended to a longer non-branching +// path by including another node at either end. +// +// In the case of a cyclic non-branching path, the first and last nodes +// of the path will be the same node, indicating an isolated cycle. +// +// The method calls the emit argument for each path or isolated cycle in g, +// as long as emit returns true. If emit returns false, +// MaximalNonBranchingPaths returns immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) MaximalNonBranchingPaths(emit func([]Half) bool) { + a := g.LabeledAdjacencyList + ind := g.InDegree() + uv := bits.New(g.Order()) + uv.SetAll() + for v, vTo := range a { + if !(ind[v] == 1 && len(vTo) == 1) { + for _, w := range vTo { + n := []Half{Half{NI(v), -1}, w} + uv.SetBit(v, 0) + uv.SetBit(int(w.To), 0) + wTo := a[w.To] + for ind[w.To] == 1 && len(wTo) == 1 { + u := wTo[0] + n = append(n, u) + uv.SetBit(int(u.To), 0) + w = u + wTo = a[w.To] + } + if !emit(n) { // n is a path + return + } + } + } + } + // use uv.From rather than uv.Iterate. + // Iterate doesn't work here because we're modifying uv + for b := uv.OneFrom(0); b >= 0; b = uv.OneFrom(b + 1) { + v := Half{NI(b), -1} + n := []Half{v} + for w := v; ; { + w = a[w.To][0] + uv.SetBit(int(w.To), 0) + n = append(n, w) + if w.To == v.To { + break + } + } + if !emit(n) { // n is an isolated cycle + return + } + } +} + +// InDegree computes the in-degree of each node in g +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) InDegree() []int { + ind := make([]int, g.Order()) + for _, nbs := range g.LabeledAdjacencyList { + for _, nb := range nbs { + ind[nb.To]++ + } + } + return ind +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *LabeledDirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.LabeledDirected.LabeledAdjacencyList + b = NI(len(a)) + s.LabeledDirected.LabeledAdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *LabeledDirectedSubgraph) AddArc(fr NI, to Half) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to.To) < 0 || int(to.To) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to.To, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.LabeledDirected.LabeledAdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to.To]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo.To = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } + } + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super).LabeledAdjacencyList[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to.To = s.AddNode(to.To) + s.LabeledDirected.LabeledAdjacencyList[bf] = + append(s.LabeledDirected.LabeledAdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledDirected) InduceList(l []NI) *LabeledDirectedSubgraph { + sub, sup := mapList(l) + return &LabeledDirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledDirected: LabeledDirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledDirected) InduceBits(t bits.Bits) *LabeledDirectedSubgraph { + sub, sup := mapBits(t) + return &LabeledDirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledDirected: LabeledDirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + +// IsTree identifies trees in directed graphs. +// +// Return value isTree is true if the subgraph reachable from root is a tree. +// Further, return value allTree is true if the entire graph g is reachable +// from root. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) IsTree(root NI) (isTree, allTree bool) { + a := g.LabeledAdjacencyList + v := bits.New(len(a)) + v.SetAll() + var df func(NI) bool + df = func(n NI) bool { + if v.Bit(int(n)) == 0 { + return false + } + v.SetBit(int(n), 0) + for _, to := range a[n] { + if !df(to.To) { + return false + } + } + return true + } + isTree = df(root) + return isTree, isTree && v.AllZeros() +} + +// PageRank computes a significance score for each node of a graph. +// +// The algorithm is credited to Google founders Brin and Lawrence. +// +// Argument d is a damping factor. Reportedly a value of .85 works well. +// Argument n is a number of iterations. Reportedly values of 20 to 50 +// work well. +// +// Returned is the PageRank score for each node of g. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) PageRank(d float64, n int) []float64 { + // Following "PageRank Explained" by Ian Rogers, accessed at + // http://www.cs.princeton.edu/~chazelle/courses/BIB/pagerank.htm + a := g.LabeledAdjacencyList + p0 := make([]float64, len(a)) + p1 := make([]float64, len(a)) + for i := range p0 { + p0[i] = 1 + } + d1 := 1 - d + for ; n > 0; n-- { + for i := range p1 { + p1[i] = d1 + } + for fr, to := range a { + f := d / float64(len(to)) + for _, to := range to { + p1[to.To] += p0[fr] * f + } + } + p0, p1 = p1, p0 + } + return p0 +} + +// StronglyConnectedComponents identifies strongly connected components in +// a directed graph. +// +// The method calls the emit function for each component identified. The +// argument to emit is the node list of a component. The emit function must +// return true for the method to continue identifying components. If emit +// returns false, the method returns immediately. +// +// Note well: The backing slice for the node list passed to emit is reused +// across emit calls. If you need to retain the node list you must copy it. +// +// The components emitted represent a partition of the nodes in g. +// So for example, if the first component emitted has the same length as g +// then it will be the only component and it means the entire graph g is +// strongly connected. +// +// See also Condensation which returns a condensation graph in addition +// to the strongly connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// The algorithm here is by David Pearce. See also alt.SCCPathBased and +// alt.SCCTarjan. +func (g LabeledDirected) StronglyConnectedComponents(emit func([]NI) bool) { + // See Algorithm 3 PEA FIND SCC2(V,E) in "An Improved Algorithm for + // Finding the Strongly Connected Components of a Directed Graph" + // by David J. Pearce. + a := g.LabeledAdjacencyList + rindex := make([]int, len(a)) + var S, scc []NI + index := 1 + c := len(a) - 1 + var visit func(NI) bool + visit = func(v NI) bool { + root := true + rindex[v] = index + index++ + for _, w := range a[v] { + if rindex[w.To] == 0 { + if !visit(w.To) { + return false + } + } + if rindex[w.To] < rindex[v] { + rindex[v] = rindex[w.To] + root = false + } + } + if !root { + S = append(S, v) + return true + } + scc = scc[:0] + index-- + for last := len(S) - 1; last >= 0; last-- { + w := S[last] + if rindex[v] > rindex[w] { + break + } + S = S[:last] + rindex[w] = c + scc = append(scc, w) + index-- + } + rindex[v] = c + c-- + return emit(append(scc, v)) + } + for v := range a { + if rindex[v] == 0 && !visit(NI(v)) { + break + } + } +} + +// Condensation returns strongly connected components and their +// condensation graph. +// +// A condensation represents a directed acyclic graph. +// Components are ordered in a reverse topological ordering. +// +// See also StronglyConnectedComponents, which returns the components only. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Condensation() (scc [][]NI, cd AdjacencyList) { + a := g.LabeledAdjacencyList + b := make([]NI, len(a)) // backing slice for scc + g.StronglyConnectedComponents(func(c []NI) bool { + n := copy(b, c) + scc = append(scc, b[:n]) + b = b[n:] + return true + }) + cd = make(AdjacencyList, len(scc)) // return value + cond := make([]NI, len(a)) // mapping from g node to cd node + for cn, c := range scc { + for _, n := range c { + cond[n] = NI(cn) // map g node to cd node + } + var tos []NI // list of 'to' nodes + m := bits.New(len(cd)) // tos map + m.SetBit(cn, 1) + for _, n := range c { + for _, to := range a[n] { + if ct := cond[to.To]; m.Bit(int(ct)) == 0 { + m.SetBit(int(ct), 1) + tos = append(tos, ct) + } + } + } + cd[cn] = tos + } + return +} + +// Topological computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Topological() (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < g.Order() { + return NI(i) + } + return -1 + }) +} + +func (g LabeledDirected) dfTopo(f func() NI) (ordering, cycle []NI) { + a := g.LabeledAdjacencyList + ordering = make([]NI, len(a)) + i := len(ordering) + temp := bits.New(len(a)) + perm := bits.New(len(a)) + var cycleFound bool + var cycleStart NI + var df func(NI) + df = func(n NI) { + switch { + case temp.Bit(int(n)) == 1: + cycleFound = true + cycleStart = n + return + case perm.Bit(int(n)) == 1: + return + } + temp.SetBit(int(n), 1) + for _, nb := range a[n] { + df(nb.To) + if cycleFound { + if cycleStart >= 0 { + // a little hack: orderng won't be needed so repurpose the + // slice as cycle. this is read out in reverse order + // as the recursion unwinds. + x := len(ordering) - 1 - len(cycle) + ordering[x] = n + cycle = ordering[x:] + if n == cycleStart { + cycleStart = -1 + } + } + return + } + } + temp.SetBit(int(n), 0) + perm.SetBit(int(n), 1) + i-- + ordering[i] = n + } + for { + n := f() + if n < 0 { + return ordering[i:], nil + } + if perm.Bit(int(n)) == 1 { + continue + } + df(n) + if cycleFound { + return nil, cycle + } + } +} + +// TopologicalKahn computes a topological ordering of a directed acyclic graph. +// +// For an acyclic graph, return value ordering is a permutation of node numbers +// in topologically sorted order and cycle will be nil. If the graph is found +// to be cyclic, ordering will be nil and cycle will be the path of a found +// cycle. +// +// This function is based on the algorithm by Arthur Kahn and requires the +// transpose of g be passed as the argument. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) TopologicalKahn(tr Directed) (ordering, cycle []NI) { + // code follows Wikipedia pseudocode. + var L, S []NI + // rem for "remaining edges," this function makes a local copy of the + // in-degrees and consumes that instead of consuming an input. + rem := make([]int, g.Order()) + for n, fr := range tr.AdjacencyList { + if len(fr) == 0 { + // accumulate "set of all nodes with no incoming edges" + S = append(S, NI(n)) + } else { + // initialize rem from in-degree + rem[n] = len(fr) + } + } + for len(S) > 0 { + last := len(S) - 1 // "remove a node n from S" + n := S[last] + S = S[:last] + L = append(L, n) // "add n to tail of L" + for _, m := range g.LabeledAdjacencyList[n] { + // WP pseudo code reads "for each node m..." but it means for each + // node m *remaining in the graph.* We consume rem rather than + // the graph, so "remaining in the graph" for us means rem[m] > 0. + if rem[m.To] > 0 { + rem[m.To]-- // "remove edge from the graph" + if rem[m.To] == 0 { // if "m has no other incoming edges" + S = append(S, m.To) // "insert m into S" + } + } + } + } + // "If graph has edges," for us means a value in rem is > 0. + for c, in := range rem { + if in > 0 { + // recover cyclic nodes + for _, nb := range g.LabeledAdjacencyList[c] { + if rem[nb.To] > 0 { + cycle = append(cycle, NI(c)) + break + } + } + } + } + if len(cycle) > 0 { + return nil, cycle + } + return L, nil +} + +// TopologicalSubgraph computes a topological ordering of a subgraph of a +// directed acyclic graph. +// +// The subgraph considered is that reachable from the specified node list. +// +// For an acyclic subgraph, return value ordering is a permutation of reachable +// node numbers in topologically sorted order and cycle will be nil. If the +// subgraph is found to be cyclic, ordering will be nil and cycle will be +// the path of a found cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) TopologicalSubgraph(nodes []NI) (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < len(nodes) { + return nodes[i] + } + return -1 + }) +} + +// TransitiveClosure returns the transitive closure of directed graph g. +// +// The algorithm is Warren's, which works most naturally with an adjacency +// matrix representation. The returned transitive closure is left in this +// adjacency matrix representation. For a graph g of order n, matrix tc +// is returned as a length n slice of length n bits.Bits values, where +// tc[from].Bit(to) == 1 represents an arc of the transitive closure. +func (g LabeledDirected) TransitiveClosure() []bits.Bits { + // construct adjacency matrix + a := g.LabeledAdjacencyList + t := make([]bits.Bits, len(a)) + for n := range t { + tn := bits.New(len(a)) + for _, to := range a[n] { + tn.SetBit(int(to.To), 1) + } + t[n] = tn + } + // above diagonal + for i := 1; i < len(a); i++ { + ti := t[i] + for k := 0; k < i; k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + // below diagonal + for i, ti := range t[:len(a)-1] { + for k := i + 1; k < len(a); k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + return t +} diff --git a/vendor/github.com/soniakeys/graph/doc.go b/vendor/github.com/soniakeys/graph/doc.go new file mode 100644 index 0000000..a30b589 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/doc.go @@ -0,0 +1,122 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +// Graph algorithms: Dijkstra, A*, Bellman Ford, Floyd Warshall; +// Kruskal and Prim minimal spanning tree; topological sort and DAG longest +// and shortest paths; Eulerian cycle and path; degeneracy and k-cores; +// Bron Kerbosch clique finding; connected components; dominance; and others. +// +// This is a graph library of integer indexes. To use it with application +// data, you associate data with integer indexes, perform searches or other +// operations with the library, and then use the integer index results to refer +// back to your application data. +// +// Thus it does not store application data, pointers to application data, +// or require you to implement an interface on your application data. +// The idea is to keep the library methods fast and lean. +// +// Representation overview +// +// The package defines a type for a node index (NI) which is just an integer +// type. It defines types for a number of number graph representations using +// NI. The fundamental graph type is AdjacencyList, which is the +// common "list of lists" graph representation. It is a list as a slice +// with one element for each node of the graph. Each element is a list +// itself, a list of neighbor nodes, implemented as an NI slice. Methods +// on an AdjacencyList generally work on any representable graph, including +// directed or undirected graphs, simple graphs or multigraphs. +// +// The type Undirected embeds an AdjacencyList adding methods specific to +// undirected graphs. Similarly the type Directed adds methods meaningful +// for directed graphs. +// +// Similar to NI, the type LI is a "label index" which labels a +// node-to-neighbor "arc" or edge. Just as an NI can index arbitrary node +// data, an LI can index arbitrary arc or edge data. A number of algorithms +// use a "weight" associated with an arc. This package does not represent +// weighted arcs explicitly, but instead uses the LI as a more general +// mechanism allowing not only weights but arbitrary data to be associated +// with arcs. While AdjacencyList represents an arc with simply an NI, +// the type LabeledAdjacencyList uses a type that pairs an NI with an LI. +// This type is named Half, for half-arc. (A full arc would represent +// both ends.) Types LabeledDirected and LabeledUndirected embed a +// LabeledAdjacencyList. +// +// In contrast to Half, the type Edge represents both ends of an edge (but +// no label.) The type LabeledEdge adds the label. The type WeightedEdgeList +// bundles a list of LabeledEdges with a WeightFunc. (WeightedEdgeList has +// few methods. It exists primarily to support the Kruskal algorithm.) +// +// FromList is a compact rooted tree (or forest) respresentation. Like +// AdjacencyList and LabeledAdjacencyList, it is a list with one element for +// each node of the graph. Each element contains only a single neighbor +// however, its parent in the tree, the "from" node. +// +// Code generation +// +// A number of methods on AdjacencyList, Directed, and Undirected are +// applicable to LabeledAdjacencyList, LabeledDirected, and LabeledUndirected +// simply by ignoring the label. In these cases code generation provides +// methods on both types from a single source implementation. These methods +// are documented with the sentence "There are equivalent labeled and unlabeled +// versions of this method." +// +// Terminology +// +// This package uses the term "node" rather than "vertex." It uses "arc" +// to mean a directed edge, and uses "from" and "to" to refer to the ends +// of an arc. It uses "start" and "end" to refer to endpoints of a search +// or traversal. +// +// The usage of "to" and "from" is perhaps most strange. In common speech +// they are prepositions, but throughout this package they are used as +// adjectives, for example to refer to the "from node" of an arc or the +// "to node". The type "FromList" is named to indicate it stores a list of +// "from" values. +// +// A "half arc" refers to just one end of an arc, either the to or from end. +// +// Two arcs are "reciprocal" if they connect two distinct nodes n1 and n2, +// one arc leading from n1 to n2 and the other arc leading from n2 to n1. +// Undirected graphs are represented with reciprocal arcs. +// +// A node with an arc to itself represents a "loop." Duplicate arcs, where +// a node has multiple arcs to another node, are termed "parallel arcs." +// A graph with no loops or parallel arcs is "simple." A graph that allows +// parallel arcs is a "multigraph" +// +// The "size" of a graph traditionally means the number of undirected edges. +// This package uses "arc size" to mean the number of arcs in a graph. For an +// undirected graph without loops, arc size is 2 * size. +// +// The "order" of a graph is the number of nodes. An "ordering" though means +// an ordered list of nodes. +// +// A number of graph search algorithms use a concept of arc "weights." +// The sum of arc weights along a path is a "distance." In contrast, the +// number of nodes in a path, including start and end nodes, is the path's +// "length." (Yes, mixing weights and lengths would be nonsense physically, +// but the terms used here are just distinct terms for abstract values. +// The actual meaning to an application is likely to be something else +// entirely and is not relevant within this package.) +// +// Finally, this package documentation takes back the word "object" in some +// places to refer to a Go value, especially a value of a type with methods. +// +// Shortest path searches +// +// This package implements a number of shortest path searches. Most work +// with weighted graphs that are directed or undirected, and with graphs +// that may have loops or parallel arcs. For weighted graphs, "shortest" +// is defined as the path distance (sum of arc weights) with path length +// (number of nodes) breaking ties. If multiple paths have the same minimum +// distance with the same minimum length, search methods are free to return +// any of them. +// +// Algorithm Description +// Dijkstra Non-negative arc weights, single or all paths. +// AStar Non-negative arc weights, heuristic guided, single path. +// BellmanFord Negative arc weights allowed, no negative cycles, all paths. +// DAGPath O(n) algorithm for DAGs, arc weights of any sign. +// FloydWarshall all pairs distances, no negative cycles. +package graph diff --git a/vendor/github.com/soniakeys/graph/fromlist.go b/vendor/github.com/soniakeys/graph/fromlist.go new file mode 100644 index 0000000..ce8c27f --- /dev/null +++ b/vendor/github.com/soniakeys/graph/fromlist.go @@ -0,0 +1,498 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import "github.com/soniakeys/bits" + +// FromList represents a rooted tree (or forest) where each node is associated +// with a half arc identifying an arc "from" another node. +// +// Other terms for this data structure include "parent list", +// "predecessor list", "in-tree", "inverse arborescence", and +// "spaghetti stack." +// +// The Paths member represents the tree structure. Leaves and MaxLen are +// not always needed. Where Leaves is used it serves as a bitmap where +// Leaves.Bit(n) == 1 for each leaf n of the tree. Where MaxLen is used it is +// provided primarily as a convenience for functions that might want to +// anticipate the maximum path length that would be encountered traversing +// the tree. +// +// Various graph search methods use a FromList to returns search results. +// For a start node of a search, From will be -1 and Len will be 1. For other +// nodes reached by the search, From represents a half arc in a path back to +// start and Len represents the number of nodes in the path. For nodes not +// reached by the search, From will be -1 and Len will be 0. +// +// A single FromList can also represent a forest. In this case paths from +// all leaves do not return to a single root node, but multiple root nodes. +// +// While a FromList generally encodes a tree or forest, it is technically +// possible to encode a cyclic graph. A number of FromList methods require +// the receiver to be acyclic. Graph methods documented to return a tree or +// forest will never return a cyclic FromList. In other cases however, +// where a FromList is not known to by cyclic, the Cyclic method can be +// useful to validate the acyclic property. +type FromList struct { + Paths []PathEnd // tree representation + Leaves bits.Bits // leaves of tree + MaxLen int // length of longest path, max of all PathEnd.Len values +} + +// PathEnd associates a half arc and a path length. +// +// A PathEnd list is an element type of FromList. +type PathEnd struct { + From NI // a "from" half arc, the node the arc comes from + Len int // number of nodes in path from start +} + +/* NewFromList could be confusing now with bits also needing allocation. +maybe best to not have this function. Maybe a more useful new would be +one that took a PathEnd slice and intitialized everything including roots +and max len. Maybe its time for a separate []PathEnd type when that's +all that's needed. (and reconsider the name PathEnd) +*/ + +// NewFromList creates a FromList object of given order. +// +// The Paths member is allocated to the specified order n but other members +// are left as zero values. +func NewFromList(n int) FromList { + return FromList{Paths: make([]PathEnd, n)} +} + +// BoundsOk validates the "from" values in the list. +// +// Negative values are allowed as they indicate root nodes. +// +// BoundsOk returns true when all from values are less than len(t). +// Otherwise it returns false and a node with a from value >= len(t). +func (f FromList) BoundsOk() (ok bool, n NI) { + for n, e := range f.Paths { + if int(e.From) >= len(f.Paths) { + return false, NI(n) + } + } + return true, -1 +} + +// CommonStart returns the common start node of minimal paths to a and b. +// +// It returns -1 if a and b cannot be traced back to a common node. +// +// The method relies on populated PathEnd.Len members. Use RecalcLen if +// the Len members are not known to be present and correct. +func (f FromList) CommonStart(a, b NI) NI { + p := f.Paths + if p[a].Len < p[b].Len { + a, b = b, a + } + for bl := p[b].Len; p[a].Len > bl; { + a = p[a].From + if a < 0 { + return -1 + } + } + for a != b { + a = p[a].From + if a < 0 { + return -1 + } + b = p[b].From + } + return a +} + +// Cyclic determines if f contains a cycle, a non-empty path from a node +// back to itself. +// +// Cyclic returns true if g contains at least one cycle. It also returns +// an example of a node involved in a cycle. +// +// Cyclic returns (false, -1) in the normal case where f is acyclic. +// Note that the bool is not an "ok" return. A cyclic FromList is usually +// not okay. +func (f FromList) Cyclic() (cyclic bool, n NI) { + p := f.Paths + vis := bits.New(len(p)) + for i := range p { + path := bits.New(len(p)) + for n := i; vis.Bit(n) == 0; { + vis.SetBit(n, 1) + path.SetBit(n, 1) + if n = int(p[n].From); n < 0 { + break + } + if path.Bit(n) == 1 { + return true, NI(n) + } + } + } + return false, -1 +} + +// IsolatedNodeBits returns a bitmap of isolated nodes in receiver graph f. +// +// An isolated node is one with no arcs going to or from it. +func (f FromList) IsolatedNodes() (iso bits.Bits) { + p := f.Paths + iso = bits.New(len(p)) + iso.SetAll() + for n, e := range p { + if e.From >= 0 { + iso.SetBit(n, 0) + iso.SetBit(int(e.From), 0) + } + } + return +} + +// PathTo decodes a FromList, recovering a single path. +// +// The path is returned as a list of nodes where the first element will be +// a root node and the last element will be the specified end node. +// +// Only the Paths member of the receiver is used. Other members of the +// FromList do not need to be valid, however the MaxLen member can be useful +// for allocating argument p. +// +// Argument p can provide the result slice. If p has capacity for the result +// it will be used, otherwise a new slice is created for the result. +// +// See also function PathTo. +func (f FromList) PathTo(end NI, p []NI) []NI { + return PathTo(f.Paths, end, p) +} + +// PathTo decodes a single path from a PathEnd list. +// +// A PathEnd list is the main data representation in a FromList. See FromList. +// +// PathTo returns a list of nodes where the first element will be +// a root node and the last element will be the specified end node. +// +// Argument p can provide the result slice. If p has capacity for the result +// it will be used, otherwise a new slice is created for the result. +// +// See also method FromList.PathTo. +func PathTo(paths []PathEnd, end NI, p []NI) []NI { + n := paths[end].Len + if n == 0 { + return p[:0] + } + if cap(p) >= n { + p = p[:n] + } else { + p = make([]NI, n) + } + for { + n-- + p[n] = end + if n == 0 { + return p + } + end = paths[end].From + } +} + +// PathToLabeled decodes a FromList, recovering a single path. +// +// The start of the returned path will be a root node of the FromList. +// +// Only the Paths member of the receiver is used. Other members of the +// FromList do not need to be valid, however the MaxLen member can be useful +// for allocating argument p. +// +// Argument p can provide the result slice. If p has capacity for the result +// it will be used, otherwise a new slice is created for the result. +// +// See also function PathTo. +func (f FromList) PathToLabeled(end NI, labels []LI, p []Half) LabeledPath { + n := f.Paths[end].Len - 1 + if n <= 0 { + return LabeledPath{end, p[:0]} + } + if cap(p) >= n { + p = p[:n] + } else { + p = make([]Half, n) + } + for { + n-- + p[n] = Half{To: end, Label: labels[end]} + end = f.Paths[end].From + if n == 0 { + return LabeledPath{end, p} + } + } +} + +// Preorder traverses a FromList in preorder. +// +// Nodes are visited in order such that for any node n with from node fr, +// fr is visited before n. Where f represents a tree, the visit ordering +// corresponds to a preordering, or depth first traversal of the tree. +// Where f represents a forest, the preorderings of the trees can be +// intermingled. +// +// Leaves must be set correctly first. Use RecalcLeaves if leaves are not +// known to be set correctly. FromList f cannot be cyclic. +// +// Traversal continues while visitor function v returns true. It terminates +// if v returns false. Preorder returns true if it completes without v +// returning false. Preorder returns false if traversal is terminated by v +// returning false. +func (f FromList) Preorder(v func(NI) bool) bool { + p := f.Paths + done := bits.New(len(p)) + var df func(NI) bool + df = func(n NI) bool { + done.SetBit(int(n), 1) + if fr := p[n].From; fr >= 0 && done.Bit(int(fr)) == 0 { + df(fr) + } + return v(n) + } + for n := range f.Paths { + p[n].Len = 0 + } + return f.Leaves.IterateOnes(func(n int) bool { + return df(NI(n)) + }) +} + +// RecalcLeaves recomputes the Leaves member of f. +func (f *FromList) RecalcLeaves() { + p := f.Paths + lv := &f.Leaves + if lv.Num != len(p) { + *lv = bits.New(len(p)) + } + lv.SetAll() + for n := range f.Paths { + if fr := p[n].From; fr >= 0 { + lv.SetBit(int(fr), 0) + } + } +} + +// RecalcLen recomputes Len for each path end, and recomputes MaxLen. +// +// RecalcLen relies on the Leaves member being valid. If it is not known +// to be valid, call RecalcLeaves before calling RecalcLen. +// +// RecalcLen will panic if the FromList is cyclic. Use the Cyclic method +// if needed to verify that the FromList is acyclic. +func (f *FromList) RecalcLen() { + p := f.Paths + var setLen func(NI) int + setLen = func(n NI) int { + switch { + case p[n].Len > 0: + return p[n].Len + case p[n].From < 0: + p[n].Len = 1 + return 1 + } + l := 1 + setLen(p[n].From) + p[n].Len = l + return l + } + for n := range f.Paths { + p[n].Len = 0 + } + f.MaxLen = 0 + f.Leaves.IterateOnes(func(n int) bool { + if l := setLen(NI(n)); l > f.MaxLen { + f.MaxLen = l + } + return true + }) +} + +// ReRoot reorients the tree containing n to make n the root node. +// +// It keeps the tree connected by "reversing" the path from n to the old root. +// +// After ReRoot, the Leaves and Len members are invalid. +// Call RecalcLeaves or RecalcLen as needed. +func (f *FromList) ReRoot(n NI) { + p := f.Paths + fr := p[n].From + if fr < 0 { + return + } + p[n].From = -1 + for { + ff := p[fr].From + p[fr].From = n + if ff < 0 { + return + } + n = fr + fr = ff + } +} + +// Root finds the root of a node in a FromList. +func (f FromList) Root(n NI) NI { + for p := f.Paths; ; { + fr := p[n].From + if fr < 0 { + return n + } + n = fr + } +} + +// Transpose constructs the directed graph corresponding to FromList f +// but with arcs in the opposite direction. That is, from roots toward leaves. +// +// If non-nil argrument roots is passed, Transpose populates it as roots of +// the resulting forest and returns nRoots as a count of the roots. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +func (f FromList) Transpose(roots *bits.Bits) (forest Directed, nRoots int) { + p := f.Paths + g := make(AdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } + for i, e := range p { + if e.From == -1 { + continue + } + g[e.From] = append(g[e.From], NI(i)) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) + nRoots-- + } + } + return Directed{g}, nRoots +} + +// TransposeLabeled constructs the labeled directed graph corresponding +// to FromList f but with arcs in the opposite direction. That is, from +// roots toward leaves. +// +// The argument labels can be nil. In this case labels are generated matching +// the path indexes. This corresponds to the "to", or child node. +// +// If labels is non-nil, it must be the same length as t.Paths and is used +// to look up label numbers by the path index. +// +// If non-nil argrument roots is passed, Transpose populates it as roots of +// the resulting forest and returns nRoots as a count of the roots. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +func (f FromList) TransposeLabeled(labels []LI, roots *bits.Bits) (forest LabeledDirected, nRoots int) { + p := f.Paths + g := make(LabeledAdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } + for i, p := range f.Paths { + if p.From == -1 { + continue + } + l := LI(i) + if labels != nil { + l = labels[i] + } + g[p.From] = append(g[p.From], Half{NI(i), l}) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) + nRoots-- + } + } + return LabeledDirected{g}, nRoots +} + +// Undirected constructs the undirected graph corresponding to FromList f. +// +// The resulting graph will be a tree or forest. +// +// If non-nil argrument roots is passed, Transpose populates it as roots of +// the resulting forest and returns nRoots as a count of the roots. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +func (f FromList) Undirected(roots *bits.Bits) (forest Undirected, nRoots int) { + p := f.Paths + g := make(AdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } + for i, e := range p { + if e.From == -1 { + continue + } + g[i] = append(g[i], e.From) + g[e.From] = append(g[e.From], NI(i)) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) + nRoots-- + } + } + return Undirected{g}, nRoots +} + +// LabeledUndirected constructs the labeled undirected graph corresponding +// to FromList f. +// +// The resulting graph will be a tree or forest. +// +// The argument labels can be nil. In this case labels are generated matching +// the path indexes. This corresponds to the "to", or child node. +// +// If labels is non-nil, it must be the same length as t.Paths and is used +// to look up label numbers by the path index. +// +// If non-nil argrument roots is passed, LabeledUndirected populates it as +// roots of the resulting forest and returns nRoots as a count of the roots. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +func (f FromList) LabeledUndirected(labels []LI, roots *bits.Bits) (forest LabeledUndirected, nRoots int) { + p := f.Paths + g := make(LabeledAdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } + for i, p := range f.Paths { + if p.From == -1 { + continue + } + l := LI(i) + if labels != nil { + l = labels[i] + } + g[i] = append(g[i], Half{p.From, l}) + g[p.From] = append(g[p.From], Half{NI(i), l}) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) + nRoots-- + } + } + return LabeledUndirected{g}, nRoots +} diff --git a/vendor/github.com/soniakeys/graph/go.mod b/vendor/github.com/soniakeys/graph/go.mod new file mode 100644 index 0000000..67bf8e0 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/go.mod @@ -0,0 +1,3 @@ +module "github.com/soniakeys/graph" + +require "github.com/soniakeys/bits" v1.0.0 diff --git a/vendor/github.com/soniakeys/graph/graph.go b/vendor/github.com/soniakeys/graph/graph.go new file mode 100644 index 0000000..c21e48a --- /dev/null +++ b/vendor/github.com/soniakeys/graph/graph.go @@ -0,0 +1,767 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "bytes" + "errors" + "fmt" + "math" + "reflect" + "text/template" + + "github.com/soniakeys/bits" +) + +// graph.go contains type definitions for all graph types and components. +// Also, go generate directives for source transformations. +// +// For readability, the types are defined in a dependency order: +// +// NI +// AdjacencyList +// Directed +// Undirected +// Bipartite +// Subgraph +// DirectedSubgraph +// UndirectedSubgraph +// LI +// Half +// fromHalf +// LabeledAdjacencyList +// LabeledDirected +// LabeledUndirected +// LabeledBipartite +// LabeledSubgraph +// LabeledDirectedSubgraph +// LabeledUndirectedSubgraph +// Edge +// LabeledEdge +// LabeledPath +// WeightFunc +// WeightedEdgeList +// TraverseOption + +//go:generate cp adj_cg.go adj_RO.go +//go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w adj_RO.go +//go:generate gofmt -r "n.To -> n" -w adj_RO.go +//go:generate gofmt -r "Half -> NI" -w adj_RO.go +//go:generate gofmt -r "LabeledSubgraph -> Subgraph" -w adj_RO.go + +//go:generate cp dir_cg.go dir_RO.go +//go:generate gofmt -r "LabeledDirected -> Directed" -w dir_RO.go +//go:generate gofmt -r "LabeledDirectedSubgraph -> DirectedSubgraph" -w dir_RO.go +//go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w dir_RO.go +//go:generate gofmt -r "labEulerian -> eulerian" -w dir_RO.go +//go:generate gofmt -r "newLabEulerian -> newEulerian" -w dir_RO.go +//go:generate gofmt -r "Half{n, -1} -> n" -w dir_RO.go +//go:generate gofmt -r "n.To -> n" -w dir_RO.go +//go:generate gofmt -r "Half -> NI" -w dir_RO.go + +//go:generate cp undir_cg.go undir_RO.go +//go:generate gofmt -r "LabeledUndirected -> Undirected" -w undir_RO.go +//go:generate gofmt -r "LabeledBipartite -> Bipartite" -w undir_RO.go +//go:generate gofmt -r "LabeledUndirectedSubgraph -> UndirectedSubgraph" -w undir_RO.go +//go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w undir_RO.go +//go:generate gofmt -r "newLabEulerian -> newEulerian" -w undir_RO.go +//go:generate gofmt -r "Half{n, -1} -> n" -w undir_RO.go +//go:generate gofmt -r "n.To -> n" -w undir_RO.go +//go:generate gofmt -r "Half -> NI" -w undir_RO.go + +// An AdjacencyList represents a graph as a list of neighbors for each node. +// The "node ID" of a node is simply it's slice index in the AdjacencyList. +// For an AdjacencyList g, g[n] represents arcs going from node n to nodes +// g[n]. +// +// Adjacency lists are inherently directed but can be used to represent +// directed or undirected graphs. See types Directed and Undirected. +type AdjacencyList [][]NI + +// Directed represents a directed graph. +// +// Directed methods generally rely on the graph being directed, specifically +// that arcs do not have reciprocals. +type Directed struct { + AdjacencyList // embedded to include AdjacencyList methods +} + +// Undirected represents an undirected graph. +// +// In an undirected graph, for each arc between distinct nodes there is also +// a reciprocal arc, an arc in the opposite direction. Loops do not have +// reciprocals. +// +// Undirected methods generally rely on the graph being undirected, +// specifically that every arc between distinct nodes has a reciprocal. +type Undirected struct { + AdjacencyList // embedded to include AdjacencyList methods +} + +// Bipartite represents a bipartite graph. +// +// In a bipartite graph, nodes are partitioned into two sets, or +// "colors," such that every edge in the graph goes from one set to the +// other. +// +// Member Color represents the partition with a bitmap of length the same +// as the number of nodes in the graph. For convenience N0 stores the number +// of zero bits in Color. +// +// To construct a Bipartite object, if you can easily or efficiently use +// available information to construct the Color member, then you should do +// this and construct a Bipartite object with a Go struct literal. +// +// If partition information is not readily available, see the constructor +// Undirected.Bipartite. +// +// Alternatively, in some cases where the graph may have multiple connected +// components, the lower level Undirected.BipartiteComponent can be used to +// control color assignment by component. +type Bipartite struct { + Undirected + Color bits.Bits + N0 int +} + +// Subgraph represents a subgraph mapped to a supergraph. +// +// The subgraph is the embedded AdjacencyList and so the Subgraph type inherits +// all methods of Adjacency list. +// +// The embedded subgraph mapped relative to a specific supergraph, member +// Super. A subgraph may have fewer nodes than its supergraph. +// Each node of the subgraph must map to a distinct node of the supergraph. +// +// The mapping giving the supergraph node for a given subgraph node is +// represented by member SuperNI, a slice parallel to the the subgraph. +// +// The mapping in the other direction, giving a subgraph NI for a given +// supergraph NI, is represented with map SubNI. +// +// Multiple Subgraphs can be created relative to a single supergraph. +// The Subgraph type represents a mapping to only a single supergraph however. +// +// See graph methods InduceList and InduceBits for construction of +// node-induced subgraphs. +// +// Alternatively an empty subgraph can be constructed with InduceList(nil). +// Arbitrary subgraphs can then be built up with methods AddNode and AddArc. +type Subgraph struct { + AdjacencyList // the subgraph + Super *AdjacencyList // the supergraph + SubNI map[NI]NI // subgraph NIs, indexed by supergraph NIs + SuperNI []NI // supergraph NIs indexed by subgraph NIs +} + +// DirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type DirectedSubgraph struct { + Directed + Super *Directed + SubNI map[NI]NI + SuperNI []NI +} + +// UndirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type UndirectedSubgraph struct { + Undirected + Super *Undirected + SubNI map[NI]NI + SuperNI []NI +} + +// LI is a label integer, used for associating labels with arcs. +type LI int32 + +// Half is a half arc, representing a labeled arc and the "neighbor" node +// that the arc leads to. +// +// Halfs can be composed to form a labeled adjacency list. +type Half struct { + To NI // node ID, usable as a slice index + Label LI // half-arc ID for application data, often a weight +} + +// fromHalf is a half arc, representing a labeled arc and the "neighbor" node +// that the arc originates from. +// +// This used internally in a couple of places. It used to be exported but is +// not currently needed anwhere in the API. +type fromHalf struct { + From NI + Label LI +} + +// A LabeledAdjacencyList represents a graph as a list of neighbors for each +// node, connected by labeled arcs. +// +// Arc labels are not necessarily unique arc IDs. Different arcs can have +// the same label. +// +// Arc labels are commonly used to assocate a weight with an arc. Arc labels +// are general purpose however and can be used to associate arbitrary +// information with an arc. +// +// Methods implementing weighted graph algorithms will commonly take a +// weight function that turns a label int into a float64 weight. +// +// If only a small amount of information -- such as an integer weight or +// a single printable character -- needs to be associated, it can sometimes +// be possible to encode the information directly into the label int. For +// more generality, some lookup scheme will be needed. +// +// In an undirected labeled graph, reciprocal arcs must have identical labels. +// Note this does not preclude parallel arcs with different labels. +type LabeledAdjacencyList [][]Half + +// LabeledDirected represents a directed labeled graph. +// +// This is the labeled version of Directed. See types LabeledAdjacencyList +// and Directed. +type LabeledDirected struct { + LabeledAdjacencyList // embedded to include LabeledAdjacencyList methods +} + +// LabeledUndirected represents an undirected labeled graph. +// +// This is the labeled version of Undirected. See types LabeledAdjacencyList +// and Undirected. +type LabeledUndirected struct { + LabeledAdjacencyList // embedded to include LabeledAdjacencyList methods +} + +// LabeledBipartite represents a bipartite graph. +// +// In a bipartite graph, nodes are partitioned into two sets, or +// "colors," such that every edge in the graph goes from one set to the +// other. +// +// Member Color represents the partition with a bitmap of length the same +// as the number of nodes in the graph. For convenience N0 stores the number +// of zero bits in Color. +// +// To construct a LabeledBipartite object, if you can easily or efficiently use +// available information to construct the Color member, then you should do +// this and construct a LabeledBipartite object with a Go struct literal. +// +// If partition information is not readily available, see the constructor +// Undirected.LabeledBipartite. +// +// Alternatively, in some cases where the graph may have multiple connected +// components, the lower level LabeledUndirected.BipartiteComponent can be used +// to control color assignment by component. +type LabeledBipartite struct { + LabeledUndirected + Color bits.Bits + N0 int +} + +// LabeledSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type LabeledSubgraph struct { + LabeledAdjacencyList + Super *LabeledAdjacencyList + SubNI map[NI]NI + SuperNI []NI +} + +// LabeledDirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type LabeledDirectedSubgraph struct { + LabeledDirected + Super *LabeledDirected + SubNI map[NI]NI + SuperNI []NI +} + +// LabeledUndirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type LabeledUndirectedSubgraph struct { + LabeledUndirected + Super *LabeledUndirected + SubNI map[NI]NI + SuperNI []NI +} + +// Edge is an undirected edge between nodes N1 and N2. +type Edge struct{ N1, N2 NI } + +// LabeledEdge is an undirected edge with an associated label. +type LabeledEdge struct { + Edge + LI +} + +// LabeledPath is a start node and a path of half arcs leading from start. +type LabeledPath struct { + Start NI + Path []Half +} + +// Distance returns total path distance given WeightFunc w. +func (p LabeledPath) Distance(w WeightFunc) float64 { + d := 0. + for _, h := range p.Path { + d += w(h.Label) + } + return d +} + +// WeightFunc returns a weight for a given label. +// +// WeightFunc is a parameter type for various search functions. The intent +// is to return a weight corresponding to an arc label. The name "weight" +// is an abstract term. An arc "weight" will typically have some application +// specific meaning other than physical weight. +type WeightFunc func(label LI) (weight float64) + +// WeightedEdgeList is a graph representation. +// +// It is a labeled edge list, with an associated weight function to return +// a weight given an edge label. +// +// Also associated is the order, or number of nodes of the graph. +// All nodes occurring in the edge list must be strictly less than Order. +// +// WeigtedEdgeList sorts by weight, obtained by calling the weight function. +// If weight computation is expensive, consider supplying a cached or +// memoized version. +type WeightedEdgeList struct { + Order int + WeightFunc + Edges []LabeledEdge +} + +// DistanceMatrix constructs a distance matrix corresponding to the weighted +// edges of l. +// +// An edge n1, n2 with WeightFunc return w is represented by both +// d[n1][n2] == w and d[n2][n1] = w. In case of parallel edges, the lowest +// weight is stored. The distance from any node to itself d[n][n] is 0, unless +// the node has a loop with a negative weight. If g has no edge between n1 and +// distinct n2, +Inf is stored for d[n1][n2] and d[n2][n1]. +// +// The returned DistanceMatrix is suitable for DistanceMatrix.FloydWarshall. +func (l WeightedEdgeList) DistanceMatrix() (d DistanceMatrix) { + d = newDM(l.Order) + for _, e := range l.Edges { + n1 := e.Edge.N1 + n2 := e.Edge.N2 + wt := l.WeightFunc(e.LI) + // < to pick min of parallel arcs (also nicely ignores NaN) + if wt < d[n1][n2] { + d[n1][n2] = wt + d[n2][n1] = wt + } + } + return +} + +// A DistanceMatrix is a square matrix representing some distance between +// nodes of a graph. If the graph is directected, d[from][to] represents +// some distance from node 'from' to node 'to'. Depending on context, the +// distance may be an arc weight or path distance. A value of +Inf typically +// means no arc or no path between the nodes. +type DistanceMatrix [][]float64 + +// little helper function, makes a blank distance matrix for FloydWarshall. +// could be exported? +func newDM(n int) DistanceMatrix { + inf := math.Inf(1) + d := make(DistanceMatrix, n) + for i := range d { + di := make([]float64, n) + for j := range di { + di[j] = inf + } + di[i] = 0 + d[i] = di + } + return d +} + +// FloydWarshall finds all pairs shortest distances for a weighted graph +// without negative cycles. +// +// It operates on a distance matrix representing arcs of a graph and +// destructively replaces arc weights with shortest path distances. +// +// In receiver d, d[fr][to] will be the shortest distance from node +// 'fr' to node 'to'. An element value of +Inf means no path exists. +// Any diagonal element < 0 indicates a negative cycle exists. +// +// See DistanceMatrix constructor methods of LabeledAdjacencyList and +// WeightedEdgeList for suitable inputs. +func (d DistanceMatrix) FloydWarshall() { + for k, dk := range d { + for _, di := range d { + dik := di[k] + for j := range d { + if d2 := dik + dk[j]; d2 < di[j] { + di[j] = d2 + } + } + } + } +} + +// PathMatrix is a return type for FloydWarshallPaths. +// +// It encodes all pairs shortest paths. +type PathMatrix [][]NI + +// Path returns a shortest path from node start to end. +// +// Argument p is truncated, appended to, and returned as the result. +// Thus the underlying allocation is reused if possible. +// If there is no path from start to end, p is returned truncated to +// zero length. +// +// If receiver m is not a valid populated PathMatrix as returned by +// FloydWarshallPaths, behavior is undefined and a panic is likely. +func (m PathMatrix) Path(start, end NI, p []NI) []NI { + p = p[:0] + for { + p = append(p, start) + if start == end { + return p + } + start = m[start][end] + if start < 0 { + return p[:0] + } + } +} + +// FloydWarshallPaths finds all pairs shortest paths for a weighted graph +// without negative cycles. +// +// It operates on a distance matrix representing arcs of a graph and +// destructively replaces arc weights with shortest path distances. +// +// In receiver d, d[fr][to] will be the shortest distance from node +// 'fr' to node 'to'. An element value of +Inf means no path exists. +// Any diagonal element < 0 indicates a negative cycle exists. +// +// The return value encodes the paths. See PathMatrix.Path. +// +// See DistanceMatrix constructor methods of LabeledAdjacencyList and +// WeightedEdgeList for suitable inputs. +// +// See also similar method FloydWarshallFromLists which has a richer +// return value. +func (d DistanceMatrix) FloydWarshallPaths() PathMatrix { + m := make(PathMatrix, len(d)) + inf := math.Inf(1) + for i, di := range d { + mi := make([]NI, len(d)) + for j, dij := range di { + if dij == inf { + mi[j] = -1 + } else { + mi[j] = NI(j) + } + } + m[i] = mi + } + for k, dk := range d { + for i, di := range d { + mi := m[i] + dik := di[k] + for j := range d { + if d2 := dik + dk[j]; d2 < di[j] { + di[j] = d2 + mi[j] = mi[k] + } + } + } + } + return m +} + +// FloydWarshallFromLists finds all pairs shortest paths for a weighted +// graph without negative cycles. +// +// It operates on a distance matrix representing arcs of a graph and +// destructively replaces arc weights with shortest path distances. +// +// In receiver d, d[fr][to] will be the shortest distance from node +// 'fr' to node 'to'. An element value of +Inf means no path exists. +// Any diagonal element < 0 indicates a negative cycle exists. +// +// The return value encodes the paths. The FromLists are fully populated +// with Leaves and Len values. See for example FromList.PathTo for +// extracting paths. Note though that for i'th FromList of the return +// value, PathTo(j) will return the path from j's root, which will not +// be i in the case that there is no path from i to j. You must check +// the first node of the path to see if it is i. If not, there is no +// path from i to j. See example. +// +// See DistanceMatrix constructor methods of LabeledAdjacencyList and +// WeightedEdgeList for suitable inputs. +// +// See also similar method FloydWarshallPaths, which has a lighter +// weight return value. +func (d DistanceMatrix) FloydWarshallFromLists() []FromList { + l := make([]FromList, len(d)) + inf := math.Inf(1) + for i, di := range d { + li := NewFromList(len(d)) + p := li.Paths + for j, dij := range di { + if i == j || dij == inf { + p[j] = PathEnd{From: -1} + } else { + p[j] = PathEnd{From: NI(i)} + } + } + l[i] = li + } + for k, dk := range d { + pk := l[k].Paths + for i, di := range d { + dik := di[k] + pi := l[i].Paths + for j := range d { + if d2 := dik + dk[j]; d2 < di[j] { + di[j] = d2 + pi[j] = pk[j] + } + } + } + } + for _, li := range l { + li.RecalcLeaves() + li.RecalcLen() + } + return l +} + +// AddEdge adds an edge to a subgraph. +// +// For argument e, e.N1 and e.N2 must be NIs in supergraph s.Super. As with +// AddNode, AddEdge panics if e.N1 and e.N2 are not valid node indexes of +// s.Super. +// +// Edge e must exist in s.Super. Further, the number of +// parallel edges in the subgraph cannot exceed the number of corresponding +// parallel edges in the supergraph. That is, each edge already added to the +// subgraph counts against the edges available in the supergraph. If a matching +// edge is not available, AddEdge returns an error. +// +// If a matching edge is available, subgraph nodes are added as needed, the +// subgraph edge is added, and the method returns nil. +func (s *UndirectedSubgraph) AddEdge(n1, n2 NI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(n1) < 0 || int(n1) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", n1, " not in supergraph")) + } + if int(n2) < 0 || int(n2) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", n2, " not in supergraph")) + } + // count existing matching edges in subgraph + n := 0 + a := s.Undirected.AdjacencyList + if b1, ok := s.SubNI[n1]; ok { + if b2, ok := s.SubNI[n2]; ok { + // both NIs already exist in subgraph, need to count edges + for _, t := range a[b1] { + if t == b2 { + n++ + } + } + if b1 != b2 { + // verify reciprocal arcs exist + r := 0 + for _, t := range a[b2] { + if t == b1 { + r++ + } + } + if r < n { + n = r + } + } + } + } + // verify matching edges are available in supergraph + m := 0 + for _, t := range (*s.Super).AdjacencyList[n1] { + if t == n2 { + if m == n { + goto r // arc match after all existing arcs matched + } + m++ + } + } + return errors.New("edge not available in supergraph") +r: + if n1 != n2 { + // verify reciprocal arcs + m = 0 + for _, t := range (*s.Super).AdjacencyList[n2] { + if t == n1 { + if m == n { + goto good + } + m++ + } + } + return errors.New("edge not available in supergraph") + } +good: + // matched enough edges. nodes can finally + // be added as needed and then the edge can be added. + b1 := s.AddNode(n1) + b2 := s.AddNode(n2) + s.Undirected.AddEdge(b1, b2) + return nil // success +} + +// AddEdge adds an edge to a subgraph. +// +// For argument e, e.N1 and e.N2 must be NIs in supergraph s.Super. As with +// AddNode, AddEdge panics if e.N1 and e.N2 are not valid node indexes of +// s.Super. +// +// Edge e must exist in s.Super with label l. Further, the number of +// parallel edges in the subgraph cannot exceed the number of corresponding +// parallel edges in the supergraph. That is, each edge already added to the +// subgraph counts against the edges available in the supergraph. If a matching +// edge is not available, AddEdge returns an error. +// +// If a matching edge is available, subgraph nodes are added as needed, the +// subgraph edge is added, and the method returns nil. +func (s *LabeledUndirectedSubgraph) AddEdge(e Edge, l LI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(e.N1) < 0 || int(e.N1) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", e.N1, " not in supergraph")) + } + if int(e.N2) < 0 || int(e.N2) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", e.N2, " not in supergraph")) + } + // count existing matching edges in subgraph + n := 0 + a := s.LabeledUndirected.LabeledAdjacencyList + if b1, ok := s.SubNI[e.N1]; ok { + if b2, ok := s.SubNI[e.N2]; ok { + // both NIs already exist in subgraph, need to count edges + h := Half{b2, l} + for _, t := range a[b1] { + if t == h { + n++ + } + } + if b1 != b2 { + // verify reciprocal arcs exist + r := 0 + h.To = b1 + for _, t := range a[b2] { + if t == h { + r++ + } + } + if r < n { + n = r + } + } + } + } + // verify matching edges are available in supergraph + m := 0 + h := Half{e.N2, l} + for _, t := range (*s.Super).LabeledAdjacencyList[e.N1] { + if t == h { + if m == n { + goto r // arc match after all existing arcs matched + } + m++ + } + } + return errors.New("edge not available in supergraph") +r: + if e.N1 != e.N2 { + // verify reciprocal arcs + m = 0 + h.To = e.N1 + for _, t := range (*s.Super).LabeledAdjacencyList[e.N2] { + if t == h { + if m == n { + goto good + } + m++ + } + } + return errors.New("edge not available in supergraph") + } +good: + // matched enough edges. nodes can finally + // be added as needed and then the edge can be added. + n1 := s.AddNode(e.N1) + n2 := s.AddNode(e.N2) + s.LabeledUndirected.AddEdge(Edge{n1, n2}, l) + return nil // success +} + +// utility function called from all of the InduceList methods. +func mapList(l []NI) (sub map[NI]NI, sup []NI) { + sub = map[NI]NI{} + // one pass to collect unique NIs + for _, p := range l { + sub[NI(p)] = -1 + } + if len(sub) == len(l) { // NIs in l are unique + sup = append([]NI{}, l...) // just copy them + for b, p := range l { + sub[p] = NI(b) // and fill in map + } + } else { // NIs in l not unique + sup = make([]NI, 0, len(sub)) + for _, p := range l { // preserve ordering of first occurrences in l + if sub[p] < 0 { + sub[p] = NI(len(sup)) + sup = append(sup, p) + } + } + } + return +} + +// utility function called from all of the InduceBits methods. +func mapBits(t bits.Bits) (sub map[NI]NI, sup []NI) { + sup = make([]NI, 0, t.OnesCount()) + sub = make(map[NI]NI, cap(sup)) + t.IterateOnes(func(n int) bool { + sub[NI(n)] = NI(len(sup)) + sup = append(sup, NI(n)) + return true + }) + return +} + +// OrderMap formats maps for testable examples. +// +// OrderMap provides simple, no-frills formatting of maps in sorted order, +// convenient in some cases for output of testable examples. +func OrderMap(m interface{}) string { + // in particular exclude slices, which template would happily accept but + // which would probably represent a coding mistake + if reflect.TypeOf(m).Kind() != reflect.Map { + panic("not a map") + } + t := template.Must(template.New("").Parse( + `map[{{range $k, $v := .}}{{$k}}:{{$v}} {{end}}]`)) + var b bytes.Buffer + if err := t.Execute(&b, m); err != nil { + panic(err) + } + return b.String() +} diff --git a/vendor/github.com/soniakeys/graph/hacking.adoc b/vendor/github.com/soniakeys/graph/hacking.adoc new file mode 100644 index 0000000..876d33f --- /dev/null +++ b/vendor/github.com/soniakeys/graph/hacking.adoc @@ -0,0 +1,135 @@ += Hacking + +== Get, install +Basic use of the package is just go get, or git clone; go install. There are +no dependencies outside the standard library. + +== Build +CI is currently on travis-ci.org. + +The build runs go vet with a few exceptions for things I'm not a big fan of. + +https://github.com/client9/misspell has been valuable. + +Also I wrote https://github.com/soniakeys/vetc to validate that each source +file has copyright/license statement. + +Then, it’s not in the ci script, but I wrote https://github.com/soniakeys/rcv +to put coverage stats in the readme. Maybe it could be commit hook or +something but for now I’ll try just running it manually now and then. + +Go fmt is not in the ci script, but I have at least one editor set up to run +it on save, so code should stay formatted pretty well. + +== Examples with random output +The math/rand generators with constant seeds used to give consistent numbers +across Go versions and so some examples relied on this. Sometime after Go 1.9 +though the numbers changed. The technique for now is to go ahead and write +those examples, get them working, then change the `// Output:` line to +`// Random output:`. This keeps them showing in go doc but keeps them from +being run by go test. This works for now. It might be revisited at some +point. + +== Plans +The primary to-do list is the issue tracker on Github. + +== Direction, focus, features +The project started with no real goal or purpose, just as a place for some code +that might be useful. Here are some elements that characterize the direction. + +* The focus has been on algorithms on adjacency lists. That is, adjacency list + is the fundamental representation for most implemented algorithms. There are + many other interesting representations, many reasons to use them, but + adjacency list is common in literature and practice. It has been useful to + focus on this data representation, at first anyway. + +* The focus has been on single threaded algorithms. Again, there is much new + and interesting work being done with concurrent, parallel, and distributed + graph algorithms, and Go might be an excellent language to implement some of + these algorithms. But as a preliminary step, more traditional + single-threaded algorithms are implemented. + +* The focus has been on static finite graphs. Again there is much interesting + work in online algorithms, dynamic graphs, and infinite graphs, but these + are not generally considered here. + +* Algorithms selected for implementation are generally ones commonly appearing + in beginning graph theory discussions and in general purpose graph libraries + in other programming languages. With these as drivers, there's a big risk + developing a library of curiosities and academic exercises rather than a + library of practical utility. But well, it's a start. The hope is that + there are some practical drivers behind graph theory and behind other graph + libraries. + +* There is active current research going on in graph algorithm development. + One goal for this library is to implement newer and faster algorithms. + In some cases where it seems not too much work, older/classic/traditional + algorithms may be implemented for comparison. These generally go in the + alt subdirectory. + +== General principles +* The API is rather low level. + +* Slices instead of maps. Maps are pretty efficient, and the property of + unique keys can be useful, But slices are still faster and more efficient, + and the unique key property is not always needed or wanted. The Adjacency + list implementation of this library is all done in slices. Slices are used + in algorithms where possible, in preference to maps. Maps are still used in + some cases where uniqueness is needed. + +* Interfaces not generally used. Algorithms are implemented directly on + concrete data types and not on interfaces describing the capabilities of + the data types. The abstraction of interfaces is a nice match to graph + theory and the convenience of running graph algorithms on any type that + implements an interface is appealing, but the costs seem too high to me. + Slices are rich with capababilites that get hidden behind interfaces and + direct slice manipulation is always faster than going through interfaces. + An impedance for programs using the library is that they will generally + have to implement a mapping from slice indexes to their application data, + often including for example, some other form of node ID. This seems fair + to push this burden outside the graph library; the library cannot know + the needs of this mapping. + +* Bitsets are widely used, particularly to store one bit of information per + node of a graph. I used math/big at first but then moved to a dense bitset + of my own. Yes, I considered other third-party bitsets but had my own + feature set I wanted. A slice of bools is another alternative. Bools will + be faster in almost all cases but the bitset will use less memory. I'm + chosing size over speed for now. + +* Code generation is used to provide methods that work on both labeled and + unlabeled graphs. Code is written to labeled types, then transformations + generate the unlabled equivalents. + +* Methods are named for what they return rather than what they do, where + reasonable anyway. + +* Consistency in method signature and behavior across corresponding methods, + for example directed/undirected, labeled/unlabeled, again, as long as it's + reasonable. + +* Sometimes in tension with the consistency principle, methods are lazy about + datatypes of parameters and return values. Sometimes a vale might have + different reasonable representations, a set might be a bitset, map, slice + of bools, or slice of set members for example. Methods will take and return + whatever is convenient for them and not convert the form just for consistency + or to try to guess what a caller would prefer. + +* Methods return multiple results for whatever the algorithm produces that + might be of interest. Sometimes an algorithm will have a primary result but + then some secondary values that also might be of interest. If they are + already computed as a byproduct of the algorithm, or can be computed at + negligible cost, return them. + +* Sometimes in conflict with the multiple result principle, methods will not + speculatively compute secondary results if there is any significant cost + and if the secondary result can be just as easily computed later. + +== Code Maintenance +There are tons of cut and paste variants. There's the basic AdjacencyList, +then Directed and Undirected variants, then Labeled variants of each of those. +Code gen helps avoid some cut and paste but there's a bunch that doesn't +code gen very well and so is duplicated with cut and paste. In particular +the testable examples in the _test files don't cg well and so are pretty much +all duplicated by hand. If you change code, think about where there should +be variants and go look to see if the variants need similar changes. diff --git a/vendor/github.com/soniakeys/graph/mst.go b/vendor/github.com/soniakeys/graph/mst.go new file mode 100644 index 0000000..92a9175 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/mst.go @@ -0,0 +1,254 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "container/heap" + "sort" + + "github.com/soniakeys/bits" +) + +type dsElement struct { + from NI + rank int +} + +type disjointSet struct { + set []dsElement +} + +func newDisjointSet(n int) disjointSet { + set := make([]dsElement, n) + for i := range set { + set[i].from = -1 + } + return disjointSet{set} +} + +// return true if disjoint trees were combined. +// false if x and y were already in the same tree. +func (ds disjointSet) union(x, y NI) bool { + xr := ds.find(x) + yr := ds.find(y) + if xr == yr { + return false + } + switch xe, ye := &ds.set[xr], &ds.set[yr]; { + case xe.rank < ye.rank: + xe.from = yr + case xe.rank == ye.rank: + xe.rank++ + fallthrough + default: + ye.from = xr + } + return true +} + +func (ds disjointSet) find(n NI) NI { + // fast paths for n == root or from root. + // no updates need in these cases. + s := ds.set + fr := s[n].from + if fr < 0 { // n is root + return n + } + n, fr = fr, s[fr].from + if fr < 0 { // n is from root + return n + } + // otherwise updates needed. + // two iterative passes (rather than recursion or stack) + // pass 1: find root + r := fr + for { + f := s[r].from + if f < 0 { + break + } + r = f + } + // pass 2: update froms + for { + s[n].from = r + if fr == r { + return r + } + n = fr + fr = s[n].from + } +} + +// Kruskal implements Kruskal's algorithm for constructing a minimum spanning +// forest on an undirected graph. +// +// The forest is returned as an undirected graph. +// +// Also returned is a total distance for the returned forest. +// +// This method is a convenience wrapper for LabeledEdgeList.Kruskal. +// If you have no need for the input graph as a LabeledUndirected, it may be +// more efficient to construct a LabeledEdgeList directly. +func (g LabeledUndirected) Kruskal(w WeightFunc) (spanningForest LabeledUndirected, dist float64) { + return g.WeightedArcsAsEdges(w).Kruskal() +} + +// Kruskal implements Kruskal's algorithm for constructing a minimum spanning +// forest on an undirected graph. +// +// The algorithm allows parallel edges, thus it is acceptable to construct +// the receiver with LabeledUndirected.WeightedArcsAsEdges. It may be more +// efficient though, if you can construct the receiver WeightedEdgeList +// directly without parallel edges. +// +// The forest is returned as an undirected graph. +// +// Also returned is a total distance for the returned forest. +// +// The edge list of the receiver is sorted in place as a side effect of this +// method. See KruskalSorted for a version that relies on the edge list being +// already sorted. This method is a wrapper for KruskalSorted. If you can +// generate the input graph sorted as required for KruskalSorted, you can +// call that method directly and avoid the overhead of the sort. +func (l WeightedEdgeList) Kruskal() (g LabeledUndirected, dist float64) { + e := l.Edges + w := l.WeightFunc + sort.Slice(e, func(i, j int) bool { return w(e[i].LI) < w(e[j].LI) }) + return l.KruskalSorted() +} + +// KruskalSorted implements Kruskal's algorithm for constructing a minimum +// spanning tree on an undirected graph. +// +// When called, the edge list of the receiver must be already sorted by weight. +// See the Kruskal method for a version that accepts an unsorted edge list. +// As with Kruskal, parallel edges are allowed. +// +// The forest is returned as an undirected graph. +// +// Also returned is a total distance for the returned forest. +func (l WeightedEdgeList) KruskalSorted() (g LabeledUndirected, dist float64) { + ds := newDisjointSet(l.Order) + g.LabeledAdjacencyList = make(LabeledAdjacencyList, l.Order) + for _, e := range l.Edges { + if ds.union(e.N1, e.N2) { + g.AddEdge(Edge{e.N1, e.N2}, e.LI) + dist += l.WeightFunc(e.LI) + } + } + return +} + +// Prim implements the Jarník-Prim-Dijkstra algorithm for constructing +// a minimum spanning tree on an undirected graph. +// +// Prim computes a minimal spanning tree on the connected component containing +// the given start node. The tree is returned in FromList f. Argument f +// cannot be a nil pointer although it can point to a zero value FromList. +// +// If the passed FromList.Paths has the len of g though, it will be reused. +// In the case of a graph with multiple connected components, this allows a +// spanning forest to be accumulated by calling Prim successively on +// representative nodes of the components. In this case if leaves for +// individual trees are of interest, pass a non-nil zero-value for the argument +// componentLeaves and it will be populated with leaves for the single tree +// spanned by the call. +// +// If argument labels is non-nil, it must have the same length as g and will +// be populated with labels corresponding to the edges of the tree. +// +// Returned are the number of nodes spanned for the single tree (which will be +// the order of the connected component) and the total spanned distance for the +// single tree. +func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI, componentLeaves *bits.Bits) (numSpanned int, dist float64) { + al := g.LabeledAdjacencyList + if len(f.Paths) != len(al) { + *f = NewFromList(len(al)) + } + if f.Leaves.Num != len(al) { + f.Leaves = bits.New(len(al)) + } + b := make([]prNode, len(al)) // "best" + for n := range b { + b[n].nx = NI(n) + b[n].fx = -1 + } + rp := f.Paths + var frontier prHeap + rp[start] = PathEnd{From: -1, Len: 1} + numSpanned = 1 + fLeaves := &f.Leaves + fLeaves.SetBit(int(start), 1) + if componentLeaves != nil { + if componentLeaves.Num != len(al) { + *componentLeaves = bits.New(len(al)) + } + componentLeaves.SetBit(int(start), 1) + } + for a := start; ; { + for _, nb := range al[a] { + if rp[nb.To].Len > 0 { + continue // already in MST, no action + } + switch bp := &b[nb.To]; { + case bp.fx == -1: // new node for frontier + bp.from = fromHalf{From: a, Label: nb.Label} + bp.wt = w(nb.Label) + heap.Push(&frontier, bp) + case w(nb.Label) < bp.wt: // better arc + bp.from = fromHalf{From: a, Label: nb.Label} + bp.wt = w(nb.Label) + heap.Fix(&frontier, bp.fx) + } + } + if len(frontier) == 0 { + break // done + } + bp := heap.Pop(&frontier).(*prNode) + a = bp.nx + rp[a].Len = rp[bp.from.From].Len + 1 + rp[a].From = bp.from.From + if len(labels) != 0 { + labels[a] = bp.from.Label + } + dist += bp.wt + fLeaves.SetBit(int(bp.from.From), 0) + fLeaves.SetBit(int(a), 1) + if componentLeaves != nil { + componentLeaves.SetBit(int(bp.from.From), 0) + componentLeaves.SetBit(int(a), 1) + } + numSpanned++ + } + return +} + +type prNode struct { + nx NI + from fromHalf + wt float64 // p.Weight(from.Label) + fx int +} + +type prHeap []*prNode + +func (h prHeap) Len() int { return len(h) } +func (h prHeap) Less(i, j int) bool { return h[i].wt < h[j].wt } +func (h prHeap) Swap(i, j int) { + h[i], h[j] = h[j], h[i] + h[i].fx = i + h[j].fx = j +} +func (p *prHeap) Push(x interface{}) { + nd := x.(*prNode) + nd.fx = len(*p) + *p = append(*p, nd) +} +func (p *prHeap) Pop() interface{} { + r := *p + last := len(r) - 1 + *p = r[:last] + return r[last] +} diff --git a/vendor/github.com/soniakeys/graph/random.go b/vendor/github.com/soniakeys/graph/random.go new file mode 100644 index 0000000..e4bbe30 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/random.go @@ -0,0 +1,708 @@ +// Copyright 2016 Sonia Keys +// License MIT: https://opensource.org/licenses/MIT + +package graph + +import ( + "errors" + "math" + "math/rand" + + "github.com/soniakeys/bits" +) + +// ChungLu constructs a random simple undirected graph. +// +// The Chung Lu model is similar to a "configuration model" where each +// node has a specified degree. In the Chung Lu model the degree specified +// for each node is taken as an expected degree, not an exact degree. +// +// Argument w is "weight," the expected degree for each node. +// The values of w must be given in decreasing order. +// +// The constructed graph will have node 0 with expected degree w[0] and so on +// so degree will decrease with node number. To randomize degree across +// node numbers, consider using the Permute method with a rand.Perm. +// +// Also returned is the actual size m of constructed graph g. +// +// If Rand r is nil, the rand package default shared source is used. +func ChungLu(w []float64, rr *rand.Rand) (g Undirected, m int) { + // Ref: "Efficient Generation of Networks with Given Expected Degrees" + // Joel C. Miller and Aric Hagberg + // accessed at http://aric.hagberg.org/papers/miller-2011-efficient.pdf + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + a := make(AdjacencyList, len(w)) + S := 0. + for i := len(w) - 1; i >= 0; i-- { + S += w[i] + } + for u := 0; u < len(w)-1; u++ { + v := u + 1 + p := w[u] * w[v] / S + if p > 1 { + p = 1 + } + for v < len(w) && p > 0 { + if p != 1 { + v += int(math.Log(rf()) / math.Log(1-p)) + } + if v < len(w) { + q := w[u] * w[v] / S + if q > 1 { + q = 1 + } + if rf() < q/p { + a[u] = append(a[u], NI(v)) + a[v] = append(a[v], NI(u)) + m++ + } + p = q + v++ + } + } + } + return Undirected{a}, m +} + +// Euclidean generates a random simple graph on the Euclidean plane. +// +// Nodes are associated with coordinates uniformly distributed on a unit +// square. Arcs are added between random nodes with a bias toward connecting +// nearer nodes. +// +// Unfortunately the function has a few "knobs". +// The returned graph will have order nNodes and arc size nArcs. The affinity +// argument controls the bias toward connecting nearer nodes. The function +// selects random pairs of nodes as a candidate arc then rejects the candidate +// if the nodes fail an affinity test. Also parallel arcs are rejected. +// As more affine or denser graphs are requested, rejections increase, +// increasing run time. The patience argument controls the number of arc +// rejections allowed before the function gives up and returns an error. +// Note that higher affinity will require more patience and that some +// combinations of nNodes and nArcs cannot be achieved with any amount of +// patience given that the returned graph must be simple. +// +// If Rand r is nil, the rand package default shared source is used. +// +// Returned is a directed simple graph and associated positions indexed by +// node number. In the arc list for each node, to-nodes are in random +// order. +// +// See also LabeledEuclidean. +func Euclidean(nNodes, nArcs int, affinity float64, patience int, rr *rand.Rand) (g Directed, pos []struct{ X, Y float64 }, err error) { + a := make(AdjacencyList, nNodes) // graph + ri, rf, re := rand.Intn, rand.Float64, rand.ExpFloat64 + if rr != nil { + ri, rf, re = rr.Intn, rr.Float64, rr.ExpFloat64 + } + // generate random positions + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = rf() + pos[i].Y = rf() + } + // arcs + var tooFar, dup int +arc: + for i := 0; i < nArcs; { + if tooFar == nArcs*patience { + err = errors.New("affinity not found") + return + } + if dup == nArcs*patience { + err = errors.New("overcrowding") + return + } + n1 := NI(ri(nNodes)) + var n2 NI + for { + n2 = NI(ri(nNodes)) + if n2 != n1 { // no graph loops + break + } + } + c1 := &pos[n1] + c2 := &pos[n2] + dist := math.Hypot(c2.X-c1.X, c2.Y-c1.Y) + if dist*affinity > re() { // favor near nodes + tooFar++ + continue + } + for _, nb := range a[n1] { + if nb == n2 { // no parallel arcs + dup++ + continue arc + } + } + a[n1] = append(a[n1], n2) + i++ + } + g = Directed{a} + return +} + +// LabeledEuclidean generates a random simple graph on the Euclidean plane. +// +// Arc label values in the returned graph g are indexes into the return value +// wt. Wt is the Euclidean distance between the from and to nodes of the arc. +// +// Otherwise the function arguments and return values are the same as for +// function Euclidean. See Euclidean. +func LabeledEuclidean(nNodes, nArcs int, affinity float64, patience int, rr *rand.Rand) (g LabeledDirected, pos []struct{ X, Y float64 }, wt []float64, err error) { + a := make(LabeledAdjacencyList, nNodes) // graph + wt = make([]float64, nArcs) // arc weights + ri, rf, re := rand.Intn, rand.Float64, rand.ExpFloat64 + if rr != nil { + ri, rf, re = rr.Intn, rr.Float64, rr.ExpFloat64 + } + // generate random positions + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = rf() + pos[i].Y = rf() + } + // arcs + var tooFar, dup int +arc: + for i := 0; i < nArcs; { + if tooFar == nArcs*patience { + err = errors.New("affinity not found") + return + } + if dup == nArcs*patience { + err = errors.New("overcrowding") + return + } + n1 := NI(ri(nNodes)) + var n2 NI + for { + n2 = NI(ri(nNodes)) + if n2 != n1 { // no graph loops + break + } + } + c1 := &pos[n1] + c2 := &pos[n2] + dist := math.Hypot(c2.X-c1.X, c2.Y-c1.Y) + if dist*affinity > re() { // favor near nodes + tooFar++ + continue + } + for _, nb := range a[n1] { + if nb.To == n2 { // no parallel arcs + dup++ + continue arc + } + } + wt[i] = dist + a[n1] = append(a[n1], Half{n2, LI(i)}) + i++ + } + g = LabeledDirected{a} + return +} + +// Geometric generates a random geometric graph (RGG) on the Euclidean plane. +// +// An RGG is an undirected simple graph. Nodes are associated with coordinates +// uniformly distributed on a unit square. Edges are added between all nodes +// falling within a specified distance or radius of each other. +// +// The resulting number of edges is somewhat random but asymptotically +// approaches m = πr²n²/2. The method accumulates and returns the actual +// number of edges constructed. In the arc list for each node, to-nodes are +// ordered. Consider using ShuffleArcLists if random order is important. +// +// If Rand r is nil, the rand package default shared source is used. +// +// See also LabeledGeometric. +func Geometric(nNodes int, radius float64, rr *rand.Rand) (g Undirected, pos []struct{ X, Y float64 }, m int) { + // Expected degree is approximately nπr². + a := make(AdjacencyList, nNodes) + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = rf() + pos[i].Y = rf() + } + for u, up := range pos { + for v := u + 1; v < len(pos); v++ { + vp := pos[v] + dx := math.Abs(up.X - vp.X) + if dx >= radius { + continue + } + dy := math.Abs(up.Y - vp.Y) + if dy >= radius { + continue + } + if math.Hypot(dx, dy) < radius { + a[u] = append(a[u], NI(v)) + a[v] = append(a[v], NI(u)) + m++ + } + } + } + g = Undirected{a} + return +} + +// LabeledGeometric generates a random geometric graph (RGG) on the Euclidean +// plane. +// +// Edge label values in the returned graph g are indexes into the return value +// wt. Wt is the Euclidean distance between nodes of the edge. The graph +// size m is len(wt). +// +// See Geometric for additional description. +func LabeledGeometric(nNodes int, radius float64, rr *rand.Rand) (g LabeledUndirected, pos []struct{ X, Y float64 }, wt []float64) { + a := make(LabeledAdjacencyList, nNodes) + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + pos = make([]struct{ X, Y float64 }, nNodes) + for i := range pos { + pos[i].X = rf() + pos[i].Y = rf() + } + for u, up := range pos { + for v := u + 1; v < len(pos); v++ { + vp := pos[v] + if w := math.Hypot(up.X-vp.X, up.Y-vp.Y); w < radius { + a[u] = append(a[u], Half{NI(v), LI(len(wt))}) + a[v] = append(a[v], Half{NI(u), LI(len(wt))}) + wt = append(wt, w) + } + } + } + g = LabeledUndirected{a} + return +} + +// GnmUndirected constructs a random simple undirected graph. +// +// Construction is by the Erdős–Rényi model where the specified number of +// distinct edges is selected from all possible edges with equal probability. +// +// Argument n is number of nodes, m is number of edges and must be <= n(n-1)/2. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also Gnm3Undirected, a method producing a statistically equivalent +// result, but by an algorithm with somewhat different performance properties. +// Performance of the two methods is expected to be similar in most cases but +// it may be worth trying both with your data to see if one has a clear +// advantage. +func GnmUndirected(n, m int, rr *rand.Rand) Undirected { + // based on Alg. 2 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + re := n * (n - 1) / 2 + ml := m + if m*2 > re { + ml = re - m + } + e := map[int]struct{}{} + for len(e) < ml { + e[ri(re)] = struct{}{} + } + a := make(AdjacencyList, n) + if m*2 > re { + i := 0 + for v := 1; v < n; v++ { + for w := 0; w < v; w++ { + if _, ok := e[i]; !ok { + a[v] = append(a[v], NI(w)) + a[w] = append(a[w], NI(v)) + } + i++ + } + } + } else { + for i := range e { + v := 1 + int(math.Sqrt(.25+float64(2*i))-.5) + w := i - (v * (v - 1) / 2) + a[v] = append(a[v], NI(w)) + a[w] = append(a[w], NI(v)) + } + } + return Undirected{a} +} + +// GnmDirected constructs a random simple directed graph. +// +// Construction is by the Erdős–Rényi model where the specified number of +// distinct arcs is selected from all possible arcs with equal probability. +// +// Argument n is number of nodes, ma is number of arcs and must be <= n(n-1). +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also Gnm3Directed, a method producing a statistically equivalent +// result, but by +// an algorithm with somewhat different performance properties. Performance +// of the two methods is expected to be similar in most cases but it may be +// worth trying both with your data to see if one has a clear advantage. +func GnmDirected(n, ma int, rr *rand.Rand) Directed { + // based on Alg. 2 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + re := n * (n - 1) + ml := ma + if ma*2 > re { + ml = re - ma + } + e := map[int]struct{}{} + for len(e) < ml { + e[ri(re)] = struct{}{} + } + a := make(AdjacencyList, n) + if ma*2 > re { + i := 0 + for v := 0; v < n; v++ { + for w := 0; w < n; w++ { + if w == v { + continue + } + if _, ok := e[i]; !ok { + a[v] = append(a[v], NI(w)) + } + i++ + } + } + } else { + for i := range e { + v := i / (n - 1) + w := i % (n - 1) + if w >= v { + w++ + } + a[v] = append(a[v], NI(w)) + } + } + return Directed{a} +} + +// Gnm3Undirected constructs a random simple undirected graph. +// +// Construction is by the Erdős–Rényi model where the specified number of +// distinct edges is selected from all possible edges with equal probability. +// +// Argument n is number of nodes, m is number of edges and must be <= n(n-1)/2. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also GnmUndirected, a method producing a statistically equivalent +// result, but by an algorithm with somewhat different performance properties. +// Performance of the two methods is expected to be similar in most cases but +// it may be worth trying both with your data to see if one has a clear +// advantage. +func Gnm3Undirected(n, m int, rr *rand.Rand) Undirected { + // based on Alg. 3 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + // + // I like this algorithm for its elegance. Pitty it tends to run a + // a little slower than the retry algorithm of Gnm. + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + a := make(AdjacencyList, n) + re := n * (n - 1) / 2 + rm := map[int]int{} + for i := 0; i < m; i++ { + er := i + ri(re-i) + eNew := er + if rp, ok := rm[er]; ok { + eNew = rp + } + if rp, ok := rm[i]; !ok { + rm[er] = i + } else { + rm[er] = rp + } + v := 1 + int(math.Sqrt(.25+float64(2*eNew))-.5) + w := eNew - (v * (v - 1) / 2) + a[v] = append(a[v], NI(w)) + a[w] = append(a[w], NI(v)) + } + return Undirected{a} +} + +// Gnm3Directed constructs a random simple directed graph. +// +// Construction is by the Erdős–Rényi model where the specified number of +// distinct arcs is selected from all possible arcs with equal probability. +// +// Argument n is number of nodes, ma is number of arcs and must be <= n(n-1). +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also GnmDirected, a method producing a statistically equivalent result, +// but by an algorithm with somewhat different performance properties. +// Performance of the two methods is expected to be similar in most cases +// but it may be worth trying both with your data to see if one has a clear +// advantage. +func Gnm3Directed(n, ma int, rr *rand.Rand) Directed { + // based on Alg. 3 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + a := make(AdjacencyList, n) + re := n * (n - 1) + rm := map[int]int{} + for i := 0; i < ma; i++ { + er := i + ri(re-i) + eNew := er + if rp, ok := rm[er]; ok { + eNew = rp + } + if rp, ok := rm[i]; !ok { + rm[er] = i + } else { + rm[er] = rp + } + v := eNew / (n - 1) + w := eNew % (n - 1) + if w >= v { + w++ + } + a[v] = append(a[v], NI(w)) + } + return Directed{a} +} + +// GnpUndirected constructs a random simple undirected graph. +// +// Construction is by the Gilbert model, an Erdős–Rényi like model where +// distinct edges are independently selected from all possible edges with +// the specified probability. +// +// Argument n is number of nodes, p is probability for selecting an edge. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// Also returned is the actual size m of constructed graph g. +func GnpUndirected(n int, p float64, rr *rand.Rand) (g Undirected, m int) { + a := make(AdjacencyList, n) + if n < 2 { + return Undirected{a}, 0 + } + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + // based on Alg. 1 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + var v, w NI = 1, -1 +g: + for c := 1 / math.Log(1-p); ; { + w += 1 + NI(c*math.Log(1-rf())) + for { + if w < v { + a[v] = append(a[v], w) + a[w] = append(a[w], v) + m++ + continue g + } + w -= v + v++ + if v == NI(n) { + break g + } + } + } + return Undirected{a}, m +} + +// GnpDirected constructs a random simple directed graph. +// +// Construction is by the Gilbert model, an Erdős–Rényi like model where +// distinct arcs are independently selected from all possible arcs with +// the specified probability. +// +// Argument n is number of nodes, p is probability for selecting an arc. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// Also returned is the actual arc size m of constructed graph g. +func GnpDirected(n int, p float64, rr *rand.Rand) (g Directed, ma int) { + a := make(AdjacencyList, n) + if n < 2 { + return Directed{a}, 0 + } + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + // based on Alg. 1 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + var v, w NI = 0, -1 +g: + for c := 1 / math.Log(1-p); ; { + w += 1 + NI(c*math.Log(1-rf())) + for ; ; w -= NI(n) { + if w == v { + w++ + } + if w < NI(n) { + a[v] = append(a[v], w) + ma++ + continue g + } + v++ + if v == NI(n) { + break g + } + } + } + return Directed{a}, ma +} + +// KroneckerDirected generates a Kronecker-like random directed graph. +// +// The returned graph g is simple and has no isolated nodes but is not +// necessarily fully connected. The number of of nodes will be <= 2^scale, +// and will be near 2^scale for typical values of arcFactor, >= 2. +// ArcFactor * 2^scale arcs are generated, although loops and duplicate arcs +// are rejected. In the arc list for each node, to-nodes are in random +// order. +// +// If Rand r is nil, the rand package default shared source is used. +// +// Return value ma is the number of arcs retained in the result graph. +func KroneckerDirected(scale uint, arcFactor float64, rr *rand.Rand) (g Directed, ma int) { + a, m := kronecker(scale, arcFactor, true, rr) + return Directed{a}, m +} + +// KroneckerUndirected generates a Kronecker-like random undirected graph. +// +// The returned graph g is simple and has no isolated nodes but is not +// necessarily fully connected. The number of of nodes will be <= 2^scale, +// and will be near 2^scale for typical values of edgeFactor, >= 2. +// EdgeFactor * 2^scale edges are generated, although loops and duplicate edges +// are rejected. In the arc list for each node, to-nodes are in random +// order. +// +// If Rand r is nil, the rand package default shared source is used. +// +// Return value m is the true number of edges--not arcs--retained in the result +// graph. +func KroneckerUndirected(scale uint, edgeFactor float64, rr *rand.Rand) (g Undirected, m int) { + al, s := kronecker(scale, edgeFactor, false, rr) + return Undirected{al}, s +} + +// Styled after the Graph500 example code. Not well tested currently. +// Graph500 example generates undirected only. No idea if the directed variant +// here is meaningful or not. +// +// note mma returns arc size ma for dir=true, but returns size m for dir=false +func kronecker(scale uint, edgeFactor float64, dir bool, rr *rand.Rand) (g AdjacencyList, mma int) { + rf, ri, rp := rand.Float64, rand.Intn, rand.Perm + if rr != nil { + rf, ri, rp = rr.Float64, rr.Intn, rr.Perm + } + N := 1 << scale // node extent + M := int(edgeFactor*float64(N) + .5) // number of arcs/edges to generate + a, b, c := 0.57, 0.19, 0.19 // initiator probabilities + ab := a + b + cNorm := c / (1 - ab) + aNorm := a / ab + ij := make([][2]NI, M) + bm := bits.New(N) + var nNodes int + for k := range ij { + var i, j int + for b := 1; b < N; b <<= 1 { + if rf() > ab { + i |= b + if rf() > cNorm { + j |= b + } + } else if rf() > aNorm { + j |= b + } + } + if bm.Bit(i) == 0 { + bm.SetBit(i, 1) + nNodes++ + } + if bm.Bit(j) == 0 { + bm.SetBit(j, 1) + nNodes++ + } + r := ri(k + 1) // shuffle edges as they are generated + ij[k] = ij[r] + ij[r] = [2]NI{NI(i), NI(j)} + } + p := rp(nNodes) // mapping to shuffle IDs of non-isolated nodes + px := 0 + rn := make([]NI, N) + for i := range rn { + if bm.Bit(i) == 1 { + rn[i] = NI(p[px]) // fill lookup table + px++ + } + } + g = make(AdjacencyList, nNodes) +ij: + for _, e := range ij { + if e[0] == e[1] { + continue // skip loops + } + ri, rj := rn[e[0]], rn[e[1]] + for _, nb := range g[ri] { + if nb == rj { + continue ij // skip parallel edges + } + } + g[ri] = append(g[ri], rj) + mma++ + if !dir { + g[rj] = append(g[rj], ri) + } + } + return +} diff --git a/vendor/github.com/soniakeys/graph/readme.adoc b/vendor/github.com/soniakeys/graph/readme.adoc new file mode 100644 index 0000000..df771a5 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/readme.adoc @@ -0,0 +1,50 @@ += Graph + +A graph library with goals of speed and simplicity, Graph implements +graph algorithms on graphs of zero-based integer node IDs. + +image:https://godoc.org/github.com/soniakeys/graph?status.svg[link=https://godoc.org/github.com/soniakeys/graph] +image:http://gowalker.org/api/v1/badge[link=https://gowalker.org/github.com/soniakeys/graph] +image:http://go-search.org/badge?id=github.com%2Fsoniakeys%2Fgraph[link=http://go-search.org/view?id=github.com%2Fsoniakeys%2Fgraph] +image:https://travis-ci.org/soniakeys/graph.svg?branch=master[link=https://travis-ci.org/soniakeys/graph] + +The library provides efficient graph representations and many methods on +graph types. It can be imported and used directly in many applications that +require or can benefit from graph algorithms. + +The library should also be considered as library of source code that can serve +as starting material for coding variant or more complex algorithms. + +== Ancillary material of interest + +The directory link:tutorials[tutorials] is a work in progress - there are only +a few tutorials there yet - but the concept is to provide some topical +walk-throughs to supplement godoc. The source-based godoc documentation +remains the primary documentation. + +The directory link:anecdote[anecdote] contains a stand-alone program that +performs single runs of a number of methods, collecting one-off or "anecdotal" +timings. It currently runs only a small fraction of the library methods but +may still be of interest for giving a general idea of how fast some methods +run. + +The directory link:bench[bench] is another work in progress. The concept is +to present some plots showing benchmark performance approaching some +theoretical asymptote. + +link:hacking.adoc[hacking.adoc] has some information about how the library is +developed, built, and tested. It might be of interest if for example you +plan to fork or contribute to the the repository. + +== Test coverage +1 Jul 2017 +.... +graph 93.7% +graph/alt 88.0% +graph/dot 77.7% +graph/treevis 79.4% +.... + +== License +All files in the repository are licensed with the MIT License, +https://opensource.org/licenses/MIT. diff --git a/vendor/github.com/soniakeys/graph/sssp.go b/vendor/github.com/soniakeys/graph/sssp.go new file mode 100644 index 0000000..88e9d51 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/sssp.go @@ -0,0 +1,761 @@ +// Copyright 2013 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "container/heap" + "fmt" + "math" + + "github.com/soniakeys/bits" +) + +// rNode holds data for a "reached" node +type rNode struct { + nx NI + state int8 // state constants defined below + f float64 // "g+h", path dist + heuristic estimate + fx int // heap.Fix index +} + +// for rNode.state +const ( + unreached = 0 + reached = 1 + open = 1 + closed = 2 +) + +type openHeap []*rNode + +// A Heuristic is defined on a specific end node. The function +// returns an estimate of the path distance from node argument +// "from" to the end node. Two subclasses of heuristics are "admissible" +// and "monotonic." +// +// Admissible means the value returned is guaranteed to be less than or +// equal to the actual shortest path distance from the node to end. +// +// An admissible estimate may further be monotonic. +// Monotonic means that for any neighboring nodes A and B with half arc aB +// leading from A to B, and for heuristic h defined on some end node, then +// h(A) <= aB.ArcWeight + h(B). +// +// See AStarA for additional notes on implementing heuristic functions for +// AStar search methods. +type Heuristic func(from NI) float64 + +// Admissible returns true if heuristic h is admissible on graph g relative to +// the given end node. +// +// If h is inadmissible, the string result describes a counter example. +func (h Heuristic) Admissible(g LabeledAdjacencyList, w WeightFunc, end NI) (bool, string) { + // invert graph + inv := make(LabeledAdjacencyList, len(g)) + for from, nbs := range g { + for _, nb := range nbs { + inv[nb.To] = append(inv[nb.To], + Half{To: NI(from), Label: nb.Label}) + } + } + // run dijkstra + // Dijkstra.AllPaths takes a start node but after inverting the graph + // argument end now represents the start node of the inverted graph. + f, _, dist, _ := inv.Dijkstra(end, -1, w) + // compare h to found shortest paths + for n := range inv { + if f.Paths[n].Len == 0 { + continue // no path, any heuristic estimate is fine. + } + if !(h(NI(n)) <= dist[n]) { + return false, fmt.Sprintf("h(%d) = %g, "+ + "required to be <= found shortest path (%g)", + n, h(NI(n)), dist[n]) + } + } + return true, "" +} + +// Monotonic returns true if heuristic h is monotonic on weighted graph g. +// +// If h is non-monotonic, the string result describes a counter example. +func (h Heuristic) Monotonic(g LabeledAdjacencyList, w WeightFunc) (bool, string) { + // precompute + hv := make([]float64, len(g)) + for n := range g { + hv[n] = h(NI(n)) + } + // iterate over all edges + for from, nbs := range g { + for _, nb := range nbs { + arcWeight := w(nb.Label) + if !(hv[from] <= arcWeight+hv[nb.To]) { + return false, fmt.Sprintf("h(%d) = %g, "+ + "required to be <= arc weight + h(%d) (= %g + %g = %g)", + from, hv[from], + nb.To, arcWeight, hv[nb.To], arcWeight+hv[nb.To]) + } + } + } + return true, "" +} + +// AStarA finds a path between two nodes. +// +// AStarA implements both algorithm A and algorithm A*. The difference in the +// two algorithms is strictly in the heuristic estimate returned by argument h. +// If h is an "admissible" heuristic estimate, then the algorithm is termed A*, +// otherwise it is algorithm A. +// +// Like Dijkstra's algorithm, AStarA with an admissible heuristic finds the +// shortest path between start and end. AStarA generally runs faster than +// Dijkstra though, by using the heuristic distance estimate. +// +// AStarA with an inadmissible heuristic becomes algorithm A. Algorithm A +// will find a path, but it is not guaranteed to be the shortest path. +// The heuristic still guides the search however, so a nearly admissible +// heuristic is likely to find a very good path, if not the best. Quality +// of the path returned degrades gracefully with the quality of the heuristic. +// +// The heuristic function h should ideally be fairly inexpensive. AStarA +// may call it more than once for the same node, especially as graph density +// increases. In some cases it may be worth the effort to memoize or +// precompute values. +// +// Argument g is the graph to be searched, with arc weights returned by w. +// As usual for AStar, arc weights must be non-negative. +// Graphs may be directed or undirected. +// +// If AStarA finds a path it returns a FromList encoding the path, the arc +// labels for path nodes, the total path distance, and ok = true. +// Otherwise it returns ok = false. +func (g LabeledAdjacencyList) AStarA(w WeightFunc, start, end NI, h Heuristic) (f FromList, labels []LI, dist float64, ok bool) { + // NOTE: AStarM is largely duplicate code. + + f = NewFromList(len(g)) + labels = make([]LI, len(g)) + d := make([]float64, len(g)) + r := make([]rNode, len(g)) + for i := range r { + r[i].nx = NI(i) + } + // start node is reached initially + cr := &r[start] + cr.state = reached + cr.f = h(start) // total path estimate is estimate from start + rp := f.Paths + rp[start] = PathEnd{Len: 1, From: -1} // path length at start is 1 node + // oh is a heap of nodes "open" for exploration. nodes go on the heap + // when they get an initial or new "g" path distance, and therefore a + // new "f" which serves as priority for exploration. + oh := openHeap{cr} + for len(oh) > 0 { + bestPath := heap.Pop(&oh).(*rNode) + bestNode := bestPath.nx + if bestNode == end { + return f, labels, d[end], true + } + bp := &rp[bestNode] + nextLen := bp.Len + 1 + for _, nb := range g[bestNode] { + alt := &r[nb.To] + ap := &rp[alt.nx] + // "g" path distance from start + g := d[bestNode] + w(nb.Label) + if alt.state == reached { + if g > d[nb.To] { + // candidate path to nb is longer than some alternate path + continue + } + if g == d[nb.To] && nextLen >= ap.Len { + // candidate path has identical length of some alternate + // path but it takes no fewer hops. + continue + } + // cool, we found a better way to get to this node. + // record new path data for this node and + // update alt with new data and make sure it's on the heap. + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + if alt.fx < 0 { + heap.Push(&oh, alt) + } else { + heap.Fix(&oh, alt.fx) + } + } else { + // bestNode being reached for the first time. + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + alt.state = reached + heap.Push(&oh, alt) // and it's now open for exploration + } + } + } + return // no path +} + +// AStarAPath finds a shortest path using the AStarA algorithm. +// +// This is a convenience method with a simpler result than the AStarA method. +// See documentation on the AStarA method. +// +// If a path is found, the non-nil node path is returned with the total path +// distance. Otherwise the returned path will be nil. +func (g LabeledAdjacencyList) AStarAPath(start, end NI, h Heuristic, w WeightFunc) (LabeledPath, float64) { + f, labels, d, _ := g.AStarA(w, start, end, h) + return f.PathToLabeled(end, labels, nil), d +} + +// AStarM is AStarA optimized for monotonic heuristic estimates. +// +// Note that this function requires a monotonic heuristic. Results will +// not be meaningful if argument h is non-monotonic. +// +// See AStarA for general usage. See Heuristic for notes on monotonicity. +func (g LabeledAdjacencyList) AStarM(w WeightFunc, start, end NI, h Heuristic) (f FromList, labels []LI, dist float64, ok bool) { + // NOTE: AStarM is largely code duplicated from AStarA. + // Differences are noted in comments in this method. + + f = NewFromList(len(g)) + labels = make([]LI, len(g)) + d := make([]float64, len(g)) + r := make([]rNode, len(g)) + for i := range r { + r[i].nx = NI(i) + } + cr := &r[start] + + // difference from AStarA: + // instead of a bit to mark a reached node, there are two states, + // open and closed. open marks nodes "open" for exploration. + // nodes are marked open as they are reached, then marked + // closed as they are found to be on the best path. + cr.state = open + + cr.f = h(start) + rp := f.Paths + rp[start] = PathEnd{Len: 1, From: -1} + oh := openHeap{cr} + for len(oh) > 0 { + bestPath := heap.Pop(&oh).(*rNode) + bestNode := bestPath.nx + if bestNode == end { + return f, labels, d[end], true + } + + // difference from AStarA: + // move nodes to closed list as they are found to be best so far. + bestPath.state = closed + + bp := &rp[bestNode] + nextLen := bp.Len + 1 + for _, nb := range g[bestNode] { + alt := &r[nb.To] + + // difference from AStarA: + // Monotonicity means that f cannot be improved. + if alt.state == closed { + continue + } + + ap := &rp[alt.nx] + g := d[bestNode] + w(nb.Label) + + // difference from AStarA: + // test for open state, not just reached + if alt.state == open { + + if g > d[nb.To] { + continue + } + if g == d[nb.To] && nextLen >= ap.Len { + continue + } + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + + // difference from AStarA: + // we know alt was on the heap because we found it marked open + heap.Fix(&oh, alt.fx) + } else { + *ap = PathEnd{From: bestNode, Len: nextLen} + labels[nb.To] = nb.Label + d[nb.To] = g + alt.f = g + h(nb.To) + + // difference from AStarA: + // nodes are opened when first reached + alt.state = open + heap.Push(&oh, alt) + } + } + } + return +} + +// AStarMPath finds a shortest path using the AStarM algorithm. +// +// This is a convenience method with a simpler result than the AStarM method. +// See documentation on the AStarM and AStarA methods. +// +// If a path is found, the non-nil node path is returned with the total path +// distance. Otherwise the returned path will be nil. +func (g LabeledAdjacencyList) AStarMPath(start, end NI, h Heuristic, w WeightFunc) (LabeledPath, float64) { + f, labels, d, _ := g.AStarM(w, start, end, h) + return f.PathToLabeled(end, labels, nil), d +} + +// implement container/heap +func (h openHeap) Len() int { return len(h) } +func (h openHeap) Less(i, j int) bool { return h[i].f < h[j].f } +func (h openHeap) Swap(i, j int) { + h[i], h[j] = h[j], h[i] + h[i].fx = i + h[j].fx = j +} +func (p *openHeap) Push(x interface{}) { + h := *p + fx := len(h) + h = append(h, x.(*rNode)) + h[fx].fx = fx + *p = h +} + +func (p *openHeap) Pop() interface{} { + h := *p + last := len(h) - 1 + *p = h[:last] + h[last].fx = -1 + return h[last] +} + +// BellmanFord finds shortest paths from a start node in a weighted directed +// graph using the Bellman-Ford-Moore algorithm. +// +// WeightFunc w must translate arc labels to arc weights. +// Negative arc weights are allowed but not negative cycles. +// Loops and parallel arcs are allowed. +// +// If the algorithm completes without encountering a negative cycle the method +// returns shortest paths encoded in a FromList, labels and path distances +// indexed by node, and return value end = -1. +// +// If it encounters a negative cycle reachable from start it returns end >= 0. +// In this case the cycle can be obtained by calling f.BellmanFordCycle(end). +// +// Negative cycles are only detected when reachable from start. A negative +// cycle not reachable from start will not prevent the algorithm from finding +// shortest paths from start. +// +// See also NegativeCycle to find a cycle anywhere in the graph, see +// NegativeCycles for enumerating all negative cycles, and see +// HasNegativeCycle for lighter-weight negative cycle detection, +func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, labels []LI, dist []float64, end NI) { + a := g.LabeledAdjacencyList + f = NewFromList(len(a)) + labels = make([]LI, len(a)) + dist = make([]float64, len(a)) + inf := math.Inf(1) + for i := range dist { + dist[i] = inf + } + rp := f.Paths + rp[start] = PathEnd{Len: 1, From: -1} + dist[start] = 0 + for _ = range a[1:] { + imp := false + for from, nbs := range a { + fp := &rp[from] + d1 := dist[from] + for _, nb := range nbs { + d2 := d1 + w(nb.Label) + to := &rp[nb.To] + // TODO improve to break ties + if fp.Len > 0 && d2 < dist[nb.To] { + *to = PathEnd{From: NI(from), Len: fp.Len + 1} + labels[nb.To] = nb.Label + dist[nb.To] = d2 + imp = true + } + } + } + if !imp { + break + } + } + for from, nbs := range a { + d1 := dist[from] + for _, nb := range nbs { + if d1+w(nb.Label) < dist[nb.To] { + // return nb as end of a path with negative cycle at root + return f, labels, dist, NI(from) + } + } + } + return f, labels, dist, -1 +} + +// BellmanFordCycle decodes a negative cycle detected by BellmanFord. +// +// Receiver f and argument end must be results returned from BellmanFord. +func (f FromList) BellmanFordCycle(end NI) (c []NI) { + p := f.Paths + b := bits.New(len(p)) + for b.Bit(int(end)) == 0 { + b.SetBit(int(end), 1) + end = p[end].From + } + for b.Bit(int(end)) == 1 { + c = append(c, end) + b.SetBit(int(end), 0) + end = p[end].From + } + for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 { + c[i], c[j] = c[j], c[i] + } + return +} + +// HasNegativeCycle returns true if the graph contains any negative cycle. +// +// HasNegativeCycle uses a Bellman-Ford-like algorithm, but finds negative +// cycles anywhere in the graph. Also path information is not computed, +// reducing memory use somewhat compared to BellmanFord. +// +// See also NegativeCycle to obtain the cycle, see NegativeCycles for +// enumerating all negative cycles, and see BellmanFord for single source +// shortest path searches with negative cycle detection. +func (g LabeledDirected) HasNegativeCycle(w WeightFunc) bool { + a := g.LabeledAdjacencyList + dist := make([]float64, len(a)) + for _ = range a[1:] { + imp := false + for from, nbs := range a { + d1 := dist[from] + for _, nb := range nbs { + d2 := d1 + w(nb.Label) + if d2 < dist[nb.To] { + dist[nb.To] = d2 + imp = true + } + } + } + if !imp { + break + } + } + for from, nbs := range a { + d1 := dist[from] + for _, nb := range nbs { + if d1+w(nb.Label) < dist[nb.To] { + return true // negative cycle + } + } + } + return false +} + +// NegativeCycle finds a negative cycle if one exists. +// +// NegativeCycle uses a Bellman-Ford-like algorithm, but finds negative +// cycles anywhere in the graph. If a negative cycle exists, one will be +// returned. The result is nil if no negative cycle exists. +// +// See also NegativeCycles for enumerating all negative cycles, see +// HasNegativeCycle for lighter-weight cycle detection, and see +// BellmanFord for single source shortest paths, also with negative cycle +// detection. +func (g LabeledDirected) NegativeCycle(w WeightFunc) (c []Half) { + a := g.LabeledAdjacencyList + f := NewFromList(len(a)) + p := f.Paths + for n := range p { + p[n] = PathEnd{From: -1, Len: 1} + } + labels := make([]LI, len(a)) + dist := make([]float64, len(a)) + for _ = range a { + imp := false + for from, nbs := range a { + fp := &p[from] + d1 := dist[from] + for _, nb := range nbs { + d2 := d1 + w(nb.Label) + to := &p[nb.To] + if fp.Len > 0 && d2 < dist[nb.To] { + *to = PathEnd{From: NI(from), Len: fp.Len + 1} + labels[nb.To] = nb.Label + dist[nb.To] = d2 + imp = true + } + } + } + if !imp { + return nil + } + } + vis := bits.New(len(a)) +a: + for n := range a { + end := n + b := bits.New(len(a)) + for b.Bit(end) == 0 { + if vis.Bit(end) == 1 { + continue a + } + vis.SetBit(end, 1) + b.SetBit(end, 1) + end = int(p[end].From) + if end < 0 { + continue a + } + } + for b.Bit(end) == 1 { + c = append(c, Half{NI(end), labels[end]}) + b.SetBit(end, 0) + end = int(p[end].From) + } + for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 { + c[i], c[j] = c[j], c[i] + } + return c + } + return nil // no negative cycle +} + +// DAGMinDistPath finds a single shortest path. +// +// Shortest means minimum sum of arc weights. +// +// Returned is the path and distance as returned by FromList.PathTo. +// +// This is a convenience method. See DAGOptimalPaths for more options. +func (g LabeledDirected) DAGMinDistPath(start, end NI, w WeightFunc) (LabeledPath, float64, error) { + return g.dagPath(start, end, w, false) +} + +// DAGMaxDistPath finds a single longest path. +// +// Longest means maximum sum of arc weights. +// +// Returned is the path and distance as returned by FromList.PathTo. +// +// This is a convenience method. See DAGOptimalPaths for more options. +func (g LabeledDirected) DAGMaxDistPath(start, end NI, w WeightFunc) (LabeledPath, float64, error) { + return g.dagPath(start, end, w, true) +} + +func (g LabeledDirected) dagPath(start, end NI, w WeightFunc, longest bool) (LabeledPath, float64, error) { + o, _ := g.Topological() + if o == nil { + return LabeledPath{}, 0, fmt.Errorf("not a DAG") + } + f, labels, dist, _ := g.DAGOptimalPaths(start, end, o, w, longest) + if f.Paths[end].Len == 0 { + return LabeledPath{}, 0, fmt.Errorf("no path from %d to %d", start, end) + } + return f.PathToLabeled(end, labels, nil), dist[end], nil +} + +// DAGOptimalPaths finds either longest or shortest distance paths in a +// directed acyclic graph. +// +// Path distance is the sum of arc weights on the path. +// Negative arc weights are allowed. +// Where multiple paths exist with the same distance, the path length +// (number of nodes) is used as a tie breaker. +// +// Receiver g must be a directed acyclic graph. Argument o must be either nil +// or a topological ordering of g. If nil, a topologcal ordering is +// computed internally. If longest is true, an optimal path is a longest +// distance path. Otherwise it is a shortest distance path. +// +// Argument start is the start node for paths, end is the end node. If end +// is a valid node number, the method returns as soon as the optimal path +// to end is found. If end is -1, all optimal paths from start are found. +// +// Paths and path distances are encoded in the returned FromList, labels, +// and dist slices. The number of nodes reached is returned as nReached. +func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightFunc, longest bool) (f FromList, labels []LI, dist []float64, nReached int) { + a := g.LabeledAdjacencyList + f = NewFromList(len(a)) + f.Leaves = bits.New(len(a)) + labels = make([]LI, len(a)) + dist = make([]float64, len(a)) + if ordering == nil { + ordering, _ = g.Topological() + } + // search ordering for start + o := 0 + for ordering[o] != start { + o++ + } + var fBetter func(cand, ext float64) bool + var iBetter func(cand, ext int) bool + if longest { + fBetter = func(cand, ext float64) bool { return cand > ext } + iBetter = func(cand, ext int) bool { return cand > ext } + } else { + fBetter = func(cand, ext float64) bool { return cand < ext } + iBetter = func(cand, ext int) bool { return cand < ext } + } + p := f.Paths + p[start] = PathEnd{From: -1, Len: 1} + f.MaxLen = 1 + leaves := &f.Leaves + leaves.SetBit(int(start), 1) + nReached = 1 + for n := start; n != end; n = ordering[o] { + if p[n].Len > 0 && len(a[n]) > 0 { + nDist := dist[n] + candLen := p[n].Len + 1 // len for any candidate arc followed from n + for _, to := range a[n] { + leaves.SetBit(int(to.To), 1) + candDist := nDist + w(to.Label) + switch { + case p[to.To].Len == 0: // first path to node to.To + nReached++ + case fBetter(candDist, dist[to.To]): // better distance + case candDist == dist[to.To] && iBetter(candLen, p[to.To].Len): // same distance but better path length + default: + continue + } + dist[to.To] = candDist + p[to.To] = PathEnd{From: n, Len: candLen} + labels[to.To] = to.Label + if candLen > f.MaxLen { + f.MaxLen = candLen + } + } + leaves.SetBit(int(n), 0) + } + o++ + if o == len(ordering) { + break + } + } + return +} + +// Dijkstra finds shortest paths by Dijkstra's algorithm. +// +// Shortest means shortest distance where distance is the +// sum of arc weights. Where multiple paths exist with the same distance, +// a path with the minimum number of nodes is returned. +// +// As usual for Dijkstra's algorithm, arc weights must be non-negative. +// Graphs may be directed or undirected. Loops and parallel arcs are +// allowed. +// +// Paths and path distances are encoded in the returned FromList and dist +// slice. Returned labels are the labels of arcs followed to each node. +// The number of nodes reached is returned as nReached. +func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, labels []LI, dist []float64, nReached int) { + r := make([]tentResult, len(g)) + for i := range r { + r[i].nx = NI(i) + } + f = NewFromList(len(g)) + labels = make([]LI, len(g)) + dist = make([]float64, len(g)) + current := start + rp := f.Paths + rp[current] = PathEnd{Len: 1, From: -1} // path length at start is 1 node + cr := &r[current] + cr.dist = 0 // distance at start is 0. + cr.done = true // mark start done. it skips the heap. + nDone := 1 // accumulated for a return value + var t tent + for current != end { + nextLen := rp[current].Len + 1 + for _, nb := range g[current] { + // d.arcVis++ + hr := &r[nb.To] + if hr.done { + continue // skip nodes already done + } + dist := cr.dist + w(nb.Label) + vl := rp[nb.To].Len + visited := vl > 0 + if visited { + if dist > hr.dist { + continue // distance is worse + } + // tie breaker is a nice touch and doesn't seem to + // impact performance much. + if dist == hr.dist && nextLen >= vl { + continue // distance same, but number of nodes is no better + } + } + // the path through current to this node is shortest so far. + // record new path data for this node and update tentative set. + hr.dist = dist + rp[nb.To].Len = nextLen + rp[nb.To].From = current + labels[nb.To] = nb.Label + if visited { + heap.Fix(&t, hr.fx) + } else { + heap.Push(&t, hr) + } + } + //d.ndVis++ + if len(t) == 0 { + // no more reachable nodes. AllPaths normal return + return f, labels, dist, nDone + } + // new current is node with smallest tentative distance + cr = heap.Pop(&t).(*tentResult) + cr.done = true + nDone++ + current = cr.nx + dist[current] = cr.dist // store final distance + } + // normal return for single shortest path search + return f, labels, dist, -1 +} + +// DijkstraPath finds a single shortest path. +// +// Returned is the path as returned by FromList.LabeledPathTo and the total +// path distance. +func (g LabeledAdjacencyList) DijkstraPath(start, end NI, w WeightFunc) (LabeledPath, float64) { + f, labels, dist, _ := g.Dijkstra(start, end, w) + return f.PathToLabeled(end, labels, nil), dist[end] +} + +// tent implements container/heap +func (t tent) Len() int { return len(t) } +func (t tent) Less(i, j int) bool { return t[i].dist < t[j].dist } +func (t tent) Swap(i, j int) { + t[i], t[j] = t[j], t[i] + t[i].fx = i + t[j].fx = j +} +func (s *tent) Push(x interface{}) { + nd := x.(*tentResult) + nd.fx = len(*s) + *s = append(*s, nd) +} +func (s *tent) Pop() interface{} { + t := *s + last := len(t) - 1 + *s = t[:last] + return t[last] +} + +type tentResult struct { + dist float64 // tentative distance, sum of arc weights + nx NI // slice index, "node id" + fx int // heap.Fix index + done bool +} + +type tent []*tentResult diff --git a/vendor/github.com/soniakeys/graph/undir.go b/vendor/github.com/soniakeys/graph/undir.go new file mode 100644 index 0000000..21ef7b5 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/undir.go @@ -0,0 +1,817 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +// undir.go has methods specific to undirected graphs, Undirected and +// LabeledUndirected. + +import ( + "fmt" + + "github.com/soniakeys/bits" +) + +// AddEdge adds an edge to a graph. +// +// It can be useful for constructing undirected graphs. +// +// When n1 and n2 are distinct, it adds the arc n1->n2 and the reciprocal +// n2->n1. When n1 and n2 are the same, it adds a single arc loop. +// +// The pointer receiver allows the method to expand the graph as needed +// to include the values n1 and n2. If n1 or n2 happen to be greater than +// len(*p) the method does not panic, but simply expands the graph. +// +// If you know or can compute the final graph order however, consider +// preallocating to avoid any overhead of expanding the graph. +// See second example, "More". +func (p *Undirected) AddEdge(n1, n2 NI) { + // Similar code in LabeledAdjacencyList.AddEdge. + + // determine max of the two end points + max := n1 + if n2 > max { + max = n2 + } + // expand graph if needed, to include both + g := p.AdjacencyList + if int(max) >= len(g) { + p.AdjacencyList = make(AdjacencyList, max+1) + copy(p.AdjacencyList, g) + g = p.AdjacencyList + } + // create one half-arc, + g[n1] = append(g[n1], n2) + // and except for loops, create the reciprocal + if n1 != n2 { + g[n2] = append(g[n2], n1) + } +} + +// RemoveEdge removes a single edge between nodes n1 and n2. +// +// It removes reciprocal arcs in the case of distinct n1 and n2 or removes +// a single arc loop in the case of n1 == n2. +// +// Returns true if the specified edge is found and successfully removed, +// false if the edge does not exist. +func (g Undirected) RemoveEdge(n1, n2 NI) (ok bool) { + ok, x1, x2 := g.HasEdge(n1, n2) + if !ok { + return + } + a := g.AdjacencyList + to := a[n1] + last := len(to) - 1 + to[x1] = to[last] + a[n1] = to[:last] + if n1 == n2 { + return + } + to = a[n2] + last = len(to) - 1 + to[x2] = to[last] + a[n2] = to[:last] + return +} + +// ArcDensity returns density for a simple directed graph. +// +// Parameter n is order, or number of nodes of a simple directed graph. +// Parameter a is the arc size, or number of directed arcs. +// +// Returned density is the fraction `a` over the total possible number of arcs +// or a / (n * (n-1)). +// +// See also Density for density of a simple undirected graph. +// +// See also the corresponding methods AdjacencyList.ArcDensity and +// LabeledAdjacencyList.ArcDensity. +func ArcDensity(n, a int) float64 { + return float64(a) / (float64(n) * float64(n-1)) +} + +// Density returns density for a simple undirected graph. +// +// Parameter n is order, or number of nodes of a simple undirected graph. +// Parameter m is the size, or number of undirected edges. +// +// Returned density is the fraction m over the total possible number of edges +// or m / ((n * (n-1))/2). +// +// See also ArcDensity for simple directed graphs. +// +// See also the corresponding methods AdjacencyList.Density and +// LabeledAdjacencyList.Density. +func Density(n, m int) float64 { + return float64(m) * 2 / (float64(n) * float64(n-1)) +} + +// An EdgeVisitor is an argument to some traversal methods. +// +// Traversal methods call the visitor function for each edge visited. +// Argument e is the edge being visited. +type EdgeVisitor func(e Edge) + +// Edges iterates over the edges of an undirected graph. +// +// Edge visitor v is called for each edge of the graph. That is, it is called +// once for each reciprocal arc pair and once for each loop. +// +// See also LabeledUndirected.Edges for a labeled version. +// See also Undirected.SimpleEdges for a version that emits only the simple +// subgraph. +func (g Undirected) Edges(v EdgeVisitor) { + a := g.AdjacencyList + unpaired := make(AdjacencyList, len(a)) + for fr, to := range a { + arc: // for each arc in a + for _, to := range to { + if to == NI(fr) { + v(Edge{NI(fr), to}) // output loop + continue + } + // search unpaired arcs + ut := unpaired[to] + for i, u := range ut { + if u == NI(fr) { // found reciprocal + v(Edge{u, to}) // output edge + last := len(ut) - 1 + ut[i] = ut[last] + unpaired[to] = ut[:last] + continue arc + } + } + // reciprocal not found + unpaired[fr] = append(unpaired[fr], to) + } + } + // undefined behavior is that unpaired arcs are silently ignored. +} + +// FromList builds a forest with a tree spanning each connected component. +// +// For each component a root is chosen and spanning is done with the method +// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with +// all spanned trees, a list of roots chosen, and a bool indicating if the +// receiver graph g was found to be a simple graph connected as a forest. +// Any cycles, loops, or parallel edges in any component will cause +// simpleForest to be false, but FromList f will still be populated with +// a valid and complete spanning forest. +func (g Undirected) FromList() (f FromList, roots []NI, simpleForest bool) { + p := make([]PathEnd, g.Order()) + for i := range p { + p[i].From = -1 + } + f.Paths = p + simpleForest = true + ts := 0 + for n := range g.AdjacencyList { + if p[n].From >= 0 { + continue + } + roots = append(roots, NI(n)) + ns, st := g.SpanTree(NI(n), &f) + if !st { + simpleForest = false + } + ts += ns + if ts == len(p) { + break + } + } + return +} + +// HasEdge returns true if g has any edge between nodes n1 and n2. +// +// Also returned are indexes x1 and x2 such that g[n1][x1] == n2 +// and g[n2][x2] == n1. If no edge between n1 and n2 is present HasArc +// returns `has` == false. +// +// See also HasArc. If you are interested only in the boolean result and +// g is a well formed (passes IsUndirected) then HasArc is an adequate test. +func (g Undirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) { + if has, x1 = g.HasArc(n1, n2); !has { + return has, x1, x1 + } + has, x2 = g.HasArc(n2, n1) + return +} + +// SimpleEdges iterates over the edges of the simple subgraph of an undirected +// graph. +// +// Edge visitor v is called for each pair of distinct nodes that is connected +// with an edge. That is, loops are ignored and parallel edges are reduced to +// a single edge. +// +// See also Undirected.Edges for a version that emits all edges. +func (g Undirected) SimpleEdges(v EdgeVisitor) { + for fr, to := range g.AdjacencyList { + e := bits.New(len(g.AdjacencyList)) + for _, to := range to { + if to > NI(fr) && e.Bit(int(to)) == 0 { + e.SetBit(int(to), 1) + v(Edge{NI(fr), to}) + } + } + } + // undefined behavior is that unpaired arcs may or may not be emitted. +} + +// SpanTree builds a tree spanning a connected component. +// +// The component is spanned by breadth-first search from the given root. +// The resulting spanning tree in stored a FromList. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of the returned FromList is populated +// with both From and Len values. The MaxLen member will be updated but +// not Leaves. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// in the component, and a bool indicating if the component was found to be a +// simply connected unrooted tree in the receiver graph g. Any cycles, loops, +// or parallel edges in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid and complete spanning tree. +func (g Undirected) SpanTree(root NI, f *FromList) (nSpanned int, simpleTree bool) { + a := g.AdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simpleTree = true + p[root] = PathEnd{From: -1, Len: 1} + type arc struct { + from NI + half NI + } + var next []arc + frontier := []arc{{-1, root}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.half].Len + 1 + for _, to := range a[fa.half] { + if to == fa.from { + continue + } + if p[to].Len > 0 { + simpleTree = false + continue + } + p[to] = PathEnd{From: fa.half, Len: l} + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.half, to}) + } + } + frontier, next = next, frontier[:0] + } + return +} + +// TarjanBiconnectedComponents decomposes a graph into maximal biconnected +// components, components for which if any node were removed the component +// would remain connected. +// +// The receiver g must be a simple graph. The method calls the emit argument +// for each component identified, as long as emit returns true. If emit +// returns false, TarjanBiconnectedComponents returns immediately. +// +// See also the eqivalent labeled TarjanBiconnectedComponents. +func (g Undirected) TarjanBiconnectedComponents(emit func([]Edge) bool) { + // Implemented closely to pseudocode in "Depth-first search and linear + // graph algorithms", Robert Tarjan, SIAM J. Comput. Vol. 1, No. 2, + // June 1972. + // + // Note Tarjan's "adjacency structure" is graph.AdjacencyList, + // His "adjacency list" is an element of a graph.AdjacencyList, also + // termed a "to-list", "neighbor list", or "child list." + a := g.AdjacencyList + number := make([]int, len(a)) + lowpt := make([]int, len(a)) + var stack []Edge + var i int + var biconnect func(NI, NI) bool + biconnect = func(v, u NI) bool { + i++ + number[v] = i + lowpt[v] = i + for _, w := range a[v] { + if number[w] == 0 { + stack = append(stack, Edge{v, w}) + if !biconnect(w, v) { + return false + } + if lowpt[w] < lowpt[v] { + lowpt[v] = lowpt[w] + } + if lowpt[w] >= number[v] { + var bcc []Edge + top := len(stack) - 1 + for number[stack[top].N1] >= number[w] { + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + } + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + if !emit(bcc) { + return false + } + } + } else if number[w] < number[v] && w != u { + stack = append(stack, Edge{v, w}) + if number[w] < lowpt[v] { + lowpt[v] = number[w] + } + } + } + return true + } + for w := range a { + if number[w] == 0 && !biconnect(NI(w), -1) { + return + } + } +} + +func (g Undirected) BlockCut(block func([]Edge) bool, cut func(NI) bool, isolated func(NI) bool) { + a := g.AdjacencyList + number := make([]int, len(a)) + lowpt := make([]int, len(a)) + var stack []Edge + var i, rc int + var biconnect func(NI, NI) bool + biconnect = func(v, u NI) bool { + i++ + number[v] = i + lowpt[v] = i + for _, w := range a[v] { + if number[w] == 0 { + if u < 0 { + rc++ + } + stack = append(stack, Edge{v, w}) + if !biconnect(w, v) { + return false + } + if lowpt[w] < lowpt[v] { + lowpt[v] = lowpt[w] + } + if lowpt[w] >= number[v] { + if u >= 0 && !cut(v) { + return false + } + var bcc []Edge + top := len(stack) - 1 + for number[stack[top].N1] >= number[w] { + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + } + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + if !block(bcc) { + return false + } + } + } else if number[w] < number[v] && w != u { + stack = append(stack, Edge{v, w}) + if number[w] < lowpt[v] { + lowpt[v] = number[w] + } + } + } + if u < 0 && rc > 1 { + return cut(v) + } + return true + } + for w := range a { + if number[w] > 0 { + continue + } + if len(a[w]) == 0 { + if !isolated(NI(w)) { + return + } + continue + } + rc = 0 + if !biconnect(NI(w), -1) { + return + } + } +} + +// AddEdge adds an edge to a labeled graph. +// +// It can be useful for constructing undirected graphs. +// +// When n1 and n2 are distinct, it adds the arc n1->n2 and the reciprocal +// n2->n1. When n1 and n2 are the same, it adds a single arc loop. +// +// If the edge already exists in *p, a parallel edge is added. +// +// The pointer receiver allows the method to expand the graph as needed +// to include the values n1 and n2. If n1 or n2 happen to be greater than +// len(*p) the method does not panic, but simply expands the graph. +func (p *LabeledUndirected) AddEdge(e Edge, l LI) { + // Similar code in AdjacencyList.AddEdge. + + // determine max of the two end points + max := e.N1 + if e.N2 > max { + max = e.N2 + } + // expand graph if needed, to include both + g := p.LabeledAdjacencyList + if max >= NI(len(g)) { + p.LabeledAdjacencyList = make(LabeledAdjacencyList, max+1) + copy(p.LabeledAdjacencyList, g) + g = p.LabeledAdjacencyList + } + // create one half-arc, + g[e.N1] = append(g[e.N1], Half{To: e.N2, Label: l}) + // and except for loops, create the reciprocal + if e.N1 != e.N2 { + g[e.N2] = append(g[e.N2], Half{To: e.N1, Label: l}) + } +} + +// A LabeledEdgeVisitor is an argument to some traversal methods. +// +// Traversal methods call the visitor function for each edge visited. +// Argument e is the edge being visited. +type LabeledEdgeVisitor func(e LabeledEdge) + +// Edges iterates over the edges of a labeled undirected graph. +// +// Edge visitor v is called for each edge of the graph. That is, it is called +// once for each reciprocal arc pair and once for each loop. +// +// See also Undirected.Edges for an unlabeled version. +// See also the more simplistic LabeledAdjacencyList.ArcsAsEdges. +func (g LabeledUndirected) Edges(v LabeledEdgeVisitor) { + // similar code in LabeledAdjacencyList.InUndirected + a := g.LabeledAdjacencyList + unpaired := make(LabeledAdjacencyList, len(a)) + for fr, to := range a { + arc: // for each arc in a + for _, to := range to { + if to.To == NI(fr) { + v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output loop + continue + } + // search unpaired arcs + ut := unpaired[to.To] + for i, u := range ut { + if u.To == NI(fr) && u.Label == to.Label { // found reciprocal + v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output edge + last := len(ut) - 1 + ut[i] = ut[last] + unpaired[to.To] = ut[:last] + continue arc + } + } + // reciprocal not found + unpaired[fr] = append(unpaired[fr], to) + } + } +} + +// FromList builds a forest with a tree spanning each connected component in g. +// +// A root is chosen and spanning is done with the LabeledUndirected.SpanTree +// method, and so is breadth-first. Returned is a FromList with all spanned +// trees, labels corresponding to arcs in f, +// a list of roots chosen, and a bool indicating if the receiver graph g was +// found to be a simple graph connected as a forest. Any cycles, loops, or +// parallel edges in any component will cause simpleForest to be false, but +// FromList f will still be populated with a valid and complete spanning forest. + +// FromList builds a forest with a tree spanning each connected component. +// +// For each component a root is chosen and spanning is done with the method +// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with +// all spanned trees, labels corresponding to arcs in f, a list of roots +// chosen, and a bool indicating if the receiver graph g was found to be a +// simple graph connected as a forest. Any cycles, loops, or parallel edges +// in any component will cause simpleForest to be false, but FromList f will +// still be populated with a valid and complete spanning forest. +func (g LabeledUndirected) FromList() (f FromList, labels []LI, roots []NI, simpleForest bool) { + p := make([]PathEnd, g.Order()) + for i := range p { + p[i].From = -1 + } + f.Paths = p + labels = make([]LI, len(p)) + simpleForest = true + ts := 0 + for n := range g.LabeledAdjacencyList { + if p[n].From >= 0 { + continue + } + roots = append(roots, NI(n)) + ns, st := g.SpanTree(NI(n), &f, labels) + if !st { + simpleForest = false + } + ts += ns + if ts == len(p) { + break + } + } + return +} + +// SpanTree builds a tree spanning a connected component. +// +// The component is spanned by breadth-first search from the given root. +// The resulting spanning tree in stored a FromList, and arc labels optionally +// stored in a slice. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of returned FromList f is populated +// populated with both From and Len values. The MaxLen member will be +// updated but not Leaves. +// +// The labels slice will be populated only if it is same length as g. +// Nil can be passed for example if labels are not needed. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// in the component, and a bool indicating if the component was found to be a +// simply connected unrooted tree in the receiver graph g. Any cycles, loops, +// or parallel edges in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid and complete spanning tree. +func (g LabeledUndirected) SpanTree(root NI, f *FromList, labels []LI) (nSpanned int, simple bool) { + a := g.LabeledAdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simple = true + p[root].Len = 1 + type arc struct { + from NI + half Half + } + var next []arc + frontier := []arc{{-1, Half{root, -1}}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.half.To].Len + 1 + for _, to := range a[fa.half.To] { + if to.To == fa.from && to.Label == fa.half.Label { + continue + } + if p[to.To].Len > 0 { + simple = false + continue + } + p[to.To] = PathEnd{From: fa.half.To, Len: l} + if len(labels) == len(p) { + labels[to.To] = to.Label + } + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.half.To, to}) + } + } + frontier, next = next, frontier[:0] + } + return +} + +// HasEdge returns true if g has any edge between nodes n1 and n2. +// +// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l} +// and g[n2][x2] == {n1, l} for some label l. If no edge between n1 and n2 +// exists, HasArc returns `has` == false. +// +// See also HasArc. If you are only interested in the boolean result then +// HasArc is an adequate test. +func (g LabeledUndirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) { + if has, x1 = g.HasArc(n1, n2); !has { + return has, x1, x1 + } + has, x2 = g.HasArcLabel(n2, n1, g.LabeledAdjacencyList[n1][x1].Label) + return +} + +// HasEdgeLabel returns true if g has any edge between nodes n1 and n2 with +// label l. +// +// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l} +// and g[n2][x2] == Half{n1, l}. If no edge between n1 and n2 with label l +// is present HasArc returns `has` == false. +func (g LabeledUndirected) HasEdgeLabel(n1, n2 NI, l LI) (has bool, x1, x2 int) { + if has, x1 = g.HasArcLabel(n1, n2, l); !has { + return has, x1, x1 + } + has, x2 = g.HasArcLabel(n2, n1, l) + return +} + +// RemoveEdge removes a single edge between nodes n1 and n2. +// +// It removes reciprocal arcs in the case of distinct n1 and n2 or removes +// a single arc loop in the case of n1 == n2. +// +// If the specified edge is found and successfully removed, RemoveEdge returns +// true and the label of the edge removed. If no edge exists between n1 and n2, +// RemoveEdge returns false, 0. +func (g LabeledUndirected) RemoveEdge(n1, n2 NI) (ok bool, label LI) { + ok, x1, x2 := g.HasEdge(n1, n2) + if !ok { + return + } + a := g.LabeledAdjacencyList + to := a[n1] + label = to[x1].Label // return value + last := len(to) - 1 + to[x1] = to[last] + a[n1] = to[:last] + if n1 == n2 { + return + } + to = a[n2] + last = len(to) - 1 + to[x2] = to[last] + a[n2] = to[:last] + return +} + +// RemoveEdgeLabel removes a single edge between nodes n1 and n2 with label l. +// +// It removes reciprocal arcs in the case of distinct n1 and n2 or removes +// a single arc loop in the case of n1 == n2. +// +// Returns true if the specified edge is found and successfully removed, +// false if the edge does not exist. +func (g LabeledUndirected) RemoveEdgeLabel(n1, n2 NI, l LI) (ok bool) { + ok, x1, x2 := g.HasEdgeLabel(n1, n2, l) + if !ok { + return + } + a := g.LabeledAdjacencyList + to := a[n1] + last := len(to) - 1 + to[x1] = to[last] + a[n1] = to[:last] + if n1 == n2 { + return + } + to = a[n2] + last = len(to) - 1 + to[x2] = to[last] + a[n2] = to[:last] + return +} + +// TarjanBiconnectedComponents decomposes a graph into maximal biconnected +// components, components for which if any node were removed the component +// would remain connected. +// +// The receiver g must be a simple graph. The method calls the emit argument +// for each component identified, as long as emit returns true. If emit +// returns false, TarjanBiconnectedComponents returns immediately. +// +// See also the eqivalent unlabeled TarjanBiconnectedComponents. +func (g LabeledUndirected) TarjanBiconnectedComponents(emit func([]LabeledEdge) bool) { + // Code nearly identical to unlabled version. + number := make([]int, g.Order()) + lowpt := make([]int, g.Order()) + var stack []LabeledEdge + var i int + var biconnect func(NI, NI) bool + biconnect = func(v, u NI) bool { + i++ + number[v] = i + lowpt[v] = i + for _, w := range g.LabeledAdjacencyList[v] { + if number[w.To] == 0 { + stack = append(stack, LabeledEdge{Edge{v, w.To}, w.Label}) + if !biconnect(w.To, v) { + return false + } + if lowpt[w.To] < lowpt[v] { + lowpt[v] = lowpt[w.To] + } + if lowpt[w.To] >= number[v] { + var bcc []LabeledEdge + top := len(stack) - 1 + for number[stack[top].N1] >= number[w.To] { + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + } + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + if !emit(bcc) { + return false + } + } + } else if number[w.To] < number[v] && w.To != u { + stack = append(stack, LabeledEdge{Edge{v, w.To}, w.Label}) + if number[w.To] < lowpt[v] { + lowpt[v] = number[w.To] + } + } + } + return true + } + for w := range g.LabeledAdjacencyList { + if number[w] == 0 && !biconnect(NI(w), -1) { + return + } + } +} + +func (e *eulerian) pushUndir() error { + for u := e.top(); ; { + e.uv.SetBit(int(u), 0) + arcs := e.g[u] + if len(arcs) == 0 { + return nil + } + w := arcs[0] + e.s++ + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + // difference from directed counterpart in dir.go: + // as long as it's not a loop, consume reciprocal arc as well + if w != u { + a2 := e.g[w] + for x, rx := range a2 { + if rx == u { // here it is + last := len(a2) - 1 + a2[x] = a2[last] // someone else gets the seat + e.g[w] = a2[:last] // and it's gone. + goto l + } + } + return fmt.Errorf("graph not undirected. %d -> %d reciprocal not found", u, w) + } + l: + u = w + } +} + +func (e *labEulerian) pushUndir() error { + for u := e.top(); ; { + e.uv.SetBit(int(u.To), 0) + arcs := e.g[u.To] + if len(arcs) == 0 { + return nil + } + w := arcs[0] + e.s++ + e.p[e.s] = w + e.g[u.To] = arcs[1:] // consume arc + // difference from directed counterpart in dir.go: + // as long as it's not a loop, consume reciprocal arc as well + if w.To != u.To { + a2 := e.g[w.To] + for x, rx := range a2 { + if rx.To == u.To && rx.Label == w.Label { // here it is + last := len(a2) - 1 + a2[x] = a2[last] // someone else can have the seat + e.g[w.To] = a2[:last] // and it's gone. + goto l + } + } + return fmt.Errorf("graph not undirected. %d -> %v reciprocal not found", u.To, w) + } + l: + u = w + } +} diff --git a/vendor/github.com/soniakeys/graph/undir_RO.go b/vendor/github.com/soniakeys/graph/undir_RO.go new file mode 100644 index 0000000..7707daf --- /dev/null +++ b/vendor/github.com/soniakeys/graph/undir_RO.go @@ -0,0 +1,1138 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + +// undir_RO.go is code generated from undir_cg.go by directives in graph.go. +// Editing undir_cg.go is okay. It is the code generation source. +// DO NOT EDIT undir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. +//------------------- + +// Bipartite constructs an object indexing the bipartite structure of a graph. +// +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. +// +// If the graph is bipartite, the method constructs and returns a new +// Bipartite object as b and returns ok = true. +// +// If the component is not bipartite, a representative odd cycle as oc and +// returns ok = false. +// +// In the case of a graph with mulitiple connected components, this method +// provides no control over the color orientation by component. See +// Undirected.BipartiteComponent if this control is needed. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Bipartite() (b *Bipartite, oc []NI, ok bool) { + c1 := bits.New(g.Order()) + c2 := bits.New(g.Order()) + r, _, _ := g.ConnectedComponentReps() + // accumulate n2 number of zero bits in c2 as number of one bits in n1 + var n, n2 int + for _, r := range r { + ok, n, _, oc = g.BipartiteComponent(r, c1, c2) + if !ok { + return + } + n2 += n + } + return &Bipartite{g, c2, n2}, nil, true +} + +// BipartiteComponent analyzes the bipartite structure of a connected component +// of an undirected graph. +// +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. +// +// Argument n can be any representative node of the component to be analyzed. +// Arguments c1 and c2 must be separate bits.Bits objects constructed to be +// of length of the number of nodes of g. These bitmaps are used in the +// component traversal and the bits of the component must be zero when the +// method is called. +// +// If the component is bipartite, BipartiteComponent populates bitmaps +// c1 and c2 with the two-coloring of the component, always assigning the set +// with representative node n to bitmap c1. It returns b = true, +// and also returns the number of bits set in c1 and c2 as n1 and n2 +// respectively. +// +// If the component is not bipartite, BipartiteComponent returns b = false +// and a representative odd cycle as oc. +// +// See also method Bipartite. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) BipartiteComponent(n NI, c1, c2 bits.Bits) (b bool, n1, n2 int, oc []NI) { + a := g.AdjacencyList + b = true + var open bool + var df func(n NI, c1, c2 *bits.Bits, n1, n2 *int) + df = func(n NI, c1, c2 *bits.Bits, n1, n2 *int) { + c1.SetBit(int(n), 1) + *n1++ + for _, nb := range a[n] { + if c1.Bit(int(nb)) == 1 { + b = false + oc = []NI{nb, n} + open = true + return + } + if c2.Bit(int(nb)) == 1 { + continue + } + df(nb, c2, c1, n2, n1) + if b { + continue + } + switch { + case !open: + case n == oc[0]: + open = false + default: + oc = append(oc, n) + } + return + } + } + df(n, &c1, &c2, &n1, &n2) + if b { + return b, n1, n2, nil + } + return b, 0, 0, oc +} + +// BronKerbosch1 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch1 algorithm of WP; that is, +// the original algorithm without improvements. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also more sophisticated variants BronKerbosch2 and BronKerbosch3. +func (g Undirected) BronKerbosch1(emit func(bits.Bits) bool) { + a := g.AdjacencyList + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { + switch { + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pf := func(n int) bool { + r2.Set(R) + r2.SetBit(n, 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) + } + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) + } + } + if !f(r2, p2, x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !P.IterateOnes(pf) { + return false + } + case X.AllZeros(): + return emit(R) + } + return true + } + var R, P, X bits.Bits + R = bits.New(len(a)) + P = bits.New(len(a)) + X = bits.New(len(a)) + P.SetAll() + f(R, P, X) +} + +// BKPivotMaxDegree is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to pick the node from P or X with the maximum degree +// (number of edges) in g. Note this is a shortcut from evaluating degrees +// in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) BKPivotMaxDegree(P, X bits.Bits) (p NI) { + // choose pivot u as highest degree node from P or X + a := g.AdjacencyList + maxDeg := -1 + P.IterateOnes(func(n int) bool { // scan P + if d := len(a[n]); d > maxDeg { + p = NI(n) + maxDeg = d + } + return true + }) + X.IterateOnes(func(n int) bool { // scan X + if d := len(a[n]); d > maxDeg { + p = NI(n) + maxDeg = d + } + return true + }) + return +} + +// BKPivotMinP is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to simply pick the first node in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) BKPivotMinP(P, X bits.Bits) NI { + return NI(P.OneFrom(0)) +} + +// BronKerbosch2 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch2 algorithm of WP; that is, +// the original algorithm plus pivoting. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variant BronKerbosch1 and more sophisticated variant +// BronKerbosch3. +func (g Undirected) BronKerbosch2(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { + a := g.AdjacencyList + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { + switch { + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) + // compute P \ N(u). next 5 lines are only difference from BK1 + pnu.Set(P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(int(to), 0) + } + // remaining code like BK1 + pf := func(n int) bool { + r2.Set(R) + r2.SetBit(n, 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) + } + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) + } + } + if !f(r2, p2, x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.IterateOnes(pf) { + return false + } + case X.AllZeros(): + return emit(R) + } + return true + } + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() + f(R, P, X) +} + +// BronKerbosch3 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch3 algorithm of WP; that is, +// the original algorithm with pivoting and degeneracy ordering. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variants BronKerbosch1 and BronKerbosch2. +func (g Undirected) BronKerbosch3(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { + a := g.AdjacencyList + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { + switch { + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) + // compute P \ N(u). next lines are only difference from BK1 + pnu.Set(P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(int(to), 0) + } + // remaining code like BK2 + pf := func(n int) bool { + r2.Set(R) + r2.SetBit(n, 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) + } + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) + } + } + if !f(r2, p2, x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.IterateOnes(pf) { + return false + } + case X.AllZeros(): + return emit(R) + } + return true + } + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() + // code above same as BK2 + // code below new to BK3 + ord, _ := g.DegeneracyOrdering() + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + for _, n := range ord { + R.SetBit(int(n), 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) + } + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) + } + } + if !f(R, p2, x2) { + return + } + R.SetBit(int(n), 0) + P.SetBit(int(n), 0) + X.SetBit(int(n), 1) + } +} + +// ConnectedComponentBits returns a function that iterates over connected +// components of g, returning a member bitmap for each. +// +// Each call of the returned function returns the order, arc size, +// and bits of a connected component. The underlying bits allocation is +// the same for each call and is overwritten on subsequent calls. Use or +// save the bits before calling the function again. The function returns +// zeros after returning all connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentInts, ConnectedComponentReps, and +// ConnectedComponentReps. +func (g Undirected) ConnectedComponentBits() func() (order, arcSize int, bits bits.Bits) { + a := g.AdjacencyList + vg := bits.New(len(a)) // nodes visited in graph + vc := bits.New(len(a)) // nodes visited in current component + var order, arcSize int + var df func(NI) + df = func(n NI) { + vg.SetBit(int(n), 1) + vc.SetBit(int(n), 1) + order++ + arcSize += len(a[n]) + for _, nb := range a[n] { + if vg.Bit(int(nb)) == 0 { + df(nb) + } + } + return + } + var n int + return func() (o, ma int, b bits.Bits) { + for ; n < len(a); n++ { + if vg.Bit(n) == 0 { + vc.ClearAll() + order, arcSize = 0, 0 + df(NI(n)) + return order, arcSize, vc + } + } + return // return zeros signalling no more components + } +} + +// ConnectedComponenInts returns a list of component numbers (ints) for each +// node of graph g. +// +// The method assigns numbers to components 1-based, 1 through the number of +// components. Return value ci contains the component number for each node. +// Return value nc is the number of components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits, ConnectedComponentLists, and +// ConnectedComponentReps. +func (g Undirected) ConnectedComponentInts() (ci []int, nc int) { + a := g.AdjacencyList + ci = make([]int, len(a)) + var df func(NI) + df = func(nd NI) { + ci[nd] = nc + for _, to := range a[nd] { + if ci[to] == 0 { + df(to) + } + } + return + } + for nd := range a { + if ci[nd] == 0 { + nc++ + df(NI(nd)) + } + } + return +} + +// ConnectedComponentLists returns a function that iterates over connected +// components of g, returning the member list of each. +// +// Each call of the returned function returns a node list of a connected +// component and the arc size of the component. The returned function returns +// nil, 0 after returning all connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits, ConnectedComponentInts, and +// ConnectedComponentReps. +func (g Undirected) ConnectedComponentLists() func() (nodes []NI, arcSize int) { + a := g.AdjacencyList + vg := bits.New(len(a)) // nodes visited in graph + var l []NI // accumulated node list of current component + var ma int // accumulated arc size of current component + var df func(NI) + df = func(n NI) { + vg.SetBit(int(n), 1) + l = append(l, n) + ma += len(a[n]) + for _, nb := range a[n] { + if vg.Bit(int(nb)) == 0 { + df(nb) + } + } + return + } + var n int + return func() ([]NI, int) { + for ; n < len(a); n++ { + if vg.Bit(n) == 0 { + l, ma = nil, 0 + df(NI(n)) + return l, ma + } + } + return nil, 0 + } +} + +// ConnectedComponentReps returns a representative node from each connected +// component of g. +// +// Returned is a slice with a single representative node from each connected +// component and also parallel slices with the orders and arc sizes +// in the corresponding components. +// +// This is fairly minimal information describing connected components. +// From a representative node, other nodes in the component can be reached +// by depth first traversal for example. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits and ConnectedComponentLists which can +// collect component members in a single traversal, and IsConnected which +// is an even simpler boolean test. +func (g Undirected) ConnectedComponentReps() (reps []NI, orders, arcSizes []int) { + a := g.AdjacencyList + c := bits.New(len(a)) + var o, ma int + var df func(NI) + df = func(n NI) { + c.SetBit(int(n), 1) + o++ + ma += len(a[n]) + for _, nb := range a[n] { + if c.Bit(int(nb)) == 0 { + df(nb) + } + } + return + } + for n := range a { + if c.Bit(n) == 0 { + o, ma = 0, 0 + df(NI(n)) + reps = append(reps, NI(n)) + orders = append(orders, o) + arcSizes = append(arcSizes, ma) + } + } + return +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Copy() (c Undirected, ma int) { + l, s := g.AdjacencyList.Copy() + return Undirected{l}, s +} + +// Degeneracy is a measure of dense subgraphs within a graph. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// See also method DegeneracyOrdering which returns a degeneracy node +// ordering and k-core breaks. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Degeneracy() (k int) { + a := g.AdjacencyList + // WP algorithm, attributed to Matula and Beck. + L := bits.New(len(a)) + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for range a { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + L.SetBit(int(v), 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(int(nb)) == 1 { + continue + } + dn := d[nb] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb) + } + } + return +} + +// DegeneracyOrdering computes degeneracy node ordering and k-core breaks. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// In return value ordering, nodes are ordered by their "coreness" as +// defined at https://en.wikipedia.org/wiki/Degeneracy_(graph_theory)#k-Cores. +// +// Return value kbreaks indexes ordering by coreness number. len(kbreaks) +// will be one more than the graph degeneracy as returned by the Degeneracy +// method. If degeneracy is d, d = len(kbreaks) - 1, kbreaks[d] is the last +// value in kbreaks and ordering[:kbreaks[d]] contains nodes of the d-cores +// of the graph. kbreaks[0] is always the number of nodes in g as all nodes +// are in in a 0-core. +// +// Note that definitions of "k-core" differ on whether a k-core must be a +// single connected component. This method does not resolve individual +// connected components. +// +// See also method Degeneracy which returns just the degeneracy number. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) DegeneracyOrdering() (ordering []NI, kbreaks []int) { + a := g.AdjacencyList + // WP algorithm + k := 0 + ordering = make([]NI, len(a)) + kbreaks = []int{len(a)} + L := bits.New(len(a)) + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for ox := len(a) - 1; ox >= 0; ox-- { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + for len(kbreaks) <= i { + kbreaks = append(kbreaks, ox+1) + } + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + ordering[ox] = v + L.SetBit(int(v), 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(int(nb)) == 1 { + continue + } + dn := d[nb] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb) + } + } + //for i, j := 0, k; i < j; i, j = i+1, j-1 { + // kbreaks[i], kbreaks[j] = kbreaks[j], kbreaks[i] + //} + return +} + +// Degree for undirected graphs, returns the degree of a node. +// +// The degree of a node in an undirected graph is the number of incident +// edges, where loops count twice. +// +// If g is known to be loop-free, the result is simply equivalent to len(g[n]). +// See handshaking lemma example at AdjacencyList.ArcSize. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Degree(n NI) int { + to := g.AdjacencyList[n] + d := len(to) // just "out" degree, + for _, to := range to { + if to == n { + d++ // except loops count twice + } + } + return d +} + +// DegreeCentralization returns the degree centralization metric of a graph. +// +// Degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple graphs of three or +// more nodes. As a special case, 0 is returned for graphs of two or fewer +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) DegreeCentralization() float64 { + a := g.AdjacencyList + if len(a) <= 2 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + return float64(len(a)*max-sum) / float64((len(a)-1)*(len(a)-2)) +} + +// Density returns density for a simple graph. +// +// See also Density function. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Density() float64 { + return Density(g.Order(), g.Size()) +} + +// Eulerian scans an undirected graph to determine if it is Eulerian. +// +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. +// +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the two end nodes of the path, and nil. +// +// Otherwise it returns an error. +// +// See also method EulerianStart, which short-circuits as soon as it finds +// a node that must be a start or end node of an Eulerian path. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Eulerian() (end1, end2 NI, err error) { + end1 = -1 + end2 = -1 + for n := range g.AdjacencyList { + switch { + case g.Degree(NI(n))%2 == 0: + case end1 < 0: + end1 = NI(n) + case end2 < 0: + end2 = NI(n) + default: + err = errors.New("non-Eulerian") + return + } + } + return +} + +// EulerianCycle finds an Eulerian cycle in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianCycle() ([]NI, error) { + c, _ := g.Copy() + return c.EulerianCycleD(c.Size()) +} + +// EulerianCycleD finds an Eulerian cycle in an undirected multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Parameter m must be the size of the undirected graph -- the +// number of edges. Use Undirected.Size if the size is unknown. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianCycleD(m int) ([]NI, error) { + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, m) + e.p[0] = 0 + for e.s >= 0 { + v := e.top() + if err := e.pushUndir(); err != nil { + return nil, err + } + if e.top() != v { + return nil, errors.New("not Eulerian") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianPath() ([]NI, error) { + c, _ := g.Copy() + start := c.EulerianStart() + if start < 0 { + start = 0 + } + return c.EulerianPathD(c.Size(), start) +} + +// EulerianPathD finds an Eulerian path in a undirected multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument m must be the correct size, or number of edges in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianPathD(m int, start NI) ([]NI, error) { + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, m) + e.p[0] = start + // unlike EulerianCycle, the first path doesn't have to be a cycle. + if err := e.pushUndir(); err != nil { + return nil, err + } + e.keep() + for e.s >= 0 { + start = e.top() + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top() != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A graph representing an Eulerian path can have two nodes with odd degree. +// If it does, these must be the end nodes of the path. EulerianEnd scans +// for a node with an odd degree, returning immediately with the first one +// it finds. +// +// If the scan completes without finding a node with odd degree the method +// returns -1. +// +// See also method Eulerian, which completely validates a graph as representing +// an Eulerian path. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianStart() NI { + for n := range g.AdjacencyList { + if g.Degree(NI(n))%2 != 0 { + return NI(n) + } + } + return -1 +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *UndirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.Undirected.AdjacencyList + b = NI(len(a)) + s.Undirected.AdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Undirected) InduceList(l []NI) *UndirectedSubgraph { + sub, sup := mapList(l) + return &UndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Undirected: Undirected{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Undirected) InduceBits(t bits.Bits) *UndirectedSubgraph { + sub, sup := mapBits(t) + return &UndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Undirected: Undirected{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + +// IsConnected tests if an undirected graph is a single connected component. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps for a method returning more information. +func (g Undirected) IsConnected() bool { + a := g.AdjacencyList + if len(a) == 0 { + return true + } + b := bits.New(len(a)) + var df func(NI) + df = func(n NI) { + b.SetBit(int(n), 1) + for _, to := range a[n] { + if b.Bit(int(to)) == 0 { + df(to) + } + } + } + df(0) + return b.AllOnes() +} + +// IsTree identifies trees in undirected graphs. +// +// Return value isTree is true if the connected component reachable from root +// is a tree. Further, return value allTree is true if the entire graph g is +// connected. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) IsTree(root NI) (isTree, allTree bool) { + a := g.AdjacencyList + v := bits.New(len(a)) + v.SetAll() + var df func(NI, NI) bool + df = func(fr, n NI) bool { + if v.Bit(int(n)) == 0 { + return false + } + v.SetBit(int(n), 0) + for _, to := range a[n] { + if to != fr && !df(n, to) { + return false + } + } + return true + } + v.SetBit(int(root), 0) + for _, to := range a[root] { + if !df(root, to) { + return false, false + } + } + return true, v.AllZeros() +} + +// Size returns the number of edges in g. +// +// See also ArcSize and AnyLoop. +func (g Undirected) Size() int { + m2 := 0 + for fr, to := range g.AdjacencyList { + m2 += len(to) + for _, to := range to { + if to == NI(fr) { + m2++ + } + } + } + return m2 / 2 +} + +// Density returns edge density of a bipartite graph. +// +// Edge density is number of edges over maximum possible number of edges. +// Maximum possible number of edges in a bipartite graph is number of +// nodes of one color times number of nodes of the other color. +func (g Bipartite) Density() float64 { + a := g.Undirected.AdjacencyList + s := 0 + g.Color.IterateOnes(func(n int) bool { + s += len(a[n]) + return true + }) + return float64(s) / float64(g.N0*(len(a)-g.N0)) +} + +// PermuteBiadjacency permutes a bipartite graph in place so that a prefix +// of the adjacency list encodes a biadjacency matrix. +// +// The permutation applied is returned. This would be helpful in referencing +// any externally stored node information. +// +// The biadjacency matrix is encoded as the prefix AdjacencyList[:g.N0]. +// Note though that this slice does not represent a valid complete +// AdjacencyList. BoundsOk would return false, for example. +// +// In adjacency list terms, the result of the permutation is that nodes of +// the prefix only have arcs to the suffix and nodes of the suffix only have +// arcs to the prefix. +func (g Bipartite) PermuteBiadjacency() []int { + p := make([]int, g.Order()) + i := 0 + g.Color.IterateZeros(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Color.IterateOnes(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Permute(p) + g.Color.ClearAll() + for i := g.N0; i < g.Order(); i++ { + g.Color.SetBit(i, 1) + } + return p +} diff --git a/vendor/github.com/soniakeys/graph/undir_cg.go b/vendor/github.com/soniakeys/graph/undir_cg.go new file mode 100644 index 0000000..ed93224 --- /dev/null +++ b/vendor/github.com/soniakeys/graph/undir_cg.go @@ -0,0 +1,1138 @@ +// Copyright 2014 Sonia Keys +// License MIT: http://opensource.org/licenses/MIT + +package graph + +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + +// undir_RO.go is code generated from undir_cg.go by directives in graph.go. +// Editing undir_cg.go is okay. It is the code generation source. +// DO NOT EDIT undir_RO.go. +// The RO means read only and it is upper case RO to slow you down a bit +// in case you start to edit the file. +//------------------- + +// Bipartite constructs an object indexing the bipartite structure of a graph. +// +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. +// +// If the graph is bipartite, the method constructs and returns a new +// Bipartite object as b and returns ok = true. +// +// If the component is not bipartite, a representative odd cycle as oc and +// returns ok = false. +// +// In the case of a graph with mulitiple connected components, this method +// provides no control over the color orientation by component. See +// Undirected.BipartiteComponent if this control is needed. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Bipartite() (b *LabeledBipartite, oc []NI, ok bool) { + c1 := bits.New(g.Order()) + c2 := bits.New(g.Order()) + r, _, _ := g.ConnectedComponentReps() + // accumulate n2 number of zero bits in c2 as number of one bits in n1 + var n, n2 int + for _, r := range r { + ok, n, _, oc = g.BipartiteComponent(r, c1, c2) + if !ok { + return + } + n2 += n + } + return &LabeledBipartite{g, c2, n2}, nil, true +} + +// BipartiteComponent analyzes the bipartite structure of a connected component +// of an undirected graph. +// +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. +// +// Argument n can be any representative node of the component to be analyzed. +// Arguments c1 and c2 must be separate bits.Bits objects constructed to be +// of length of the number of nodes of g. These bitmaps are used in the +// component traversal and the bits of the component must be zero when the +// method is called. +// +// If the component is bipartite, BipartiteComponent populates bitmaps +// c1 and c2 with the two-coloring of the component, always assigning the set +// with representative node n to bitmap c1. It returns b = true, +// and also returns the number of bits set in c1 and c2 as n1 and n2 +// respectively. +// +// If the component is not bipartite, BipartiteComponent returns b = false +// and a representative odd cycle as oc. +// +// See also method Bipartite. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) BipartiteComponent(n NI, c1, c2 bits.Bits) (b bool, n1, n2 int, oc []NI) { + a := g.LabeledAdjacencyList + b = true + var open bool + var df func(n NI, c1, c2 *bits.Bits, n1, n2 *int) + df = func(n NI, c1, c2 *bits.Bits, n1, n2 *int) { + c1.SetBit(int(n), 1) + *n1++ + for _, nb := range a[n] { + if c1.Bit(int(nb.To)) == 1 { + b = false + oc = []NI{nb.To, n} + open = true + return + } + if c2.Bit(int(nb.To)) == 1 { + continue + } + df(nb.To, c2, c1, n2, n1) + if b { + continue + } + switch { + case !open: + case n == oc[0]: + open = false + default: + oc = append(oc, n) + } + return + } + } + df(n, &c1, &c2, &n1, &n2) + if b { + return b, n1, n2, nil + } + return b, 0, 0, oc +} + +// BronKerbosch1 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch1 algorithm of WP; that is, +// the original algorithm without improvements. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also more sophisticated variants BronKerbosch2 and BronKerbosch3. +func (g LabeledUndirected) BronKerbosch1(emit func(bits.Bits) bool) { + a := g.LabeledAdjacencyList + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { + switch { + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pf := func(n int) bool { + r2.Set(R) + r2.SetBit(n, 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) + } + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) + } + } + if !f(r2, p2, x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !P.IterateOnes(pf) { + return false + } + case X.AllZeros(): + return emit(R) + } + return true + } + var R, P, X bits.Bits + R = bits.New(len(a)) + P = bits.New(len(a)) + X = bits.New(len(a)) + P.SetAll() + f(R, P, X) +} + +// BKPivotMaxDegree is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to pick the node from P or X with the maximum degree +// (number of edges) in g. Note this is a shortcut from evaluating degrees +// in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) BKPivotMaxDegree(P, X bits.Bits) (p NI) { + // choose pivot u as highest degree node from P or X + a := g.LabeledAdjacencyList + maxDeg := -1 + P.IterateOnes(func(n int) bool { // scan P + if d := len(a[n]); d > maxDeg { + p = NI(n) + maxDeg = d + } + return true + }) + X.IterateOnes(func(n int) bool { // scan X + if d := len(a[n]); d > maxDeg { + p = NI(n) + maxDeg = d + } + return true + }) + return +} + +// BKPivotMinP is a strategy for BronKerbosch methods. +// +// To use it, take the method value (see golang.org/ref/spec#Method_values) +// and pass it as the argument to BronKerbosch2 or 3. +// +// The strategy is to simply pick the first node in P. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) BKPivotMinP(P, X bits.Bits) NI { + return NI(P.OneFrom(0)) +} + +// BronKerbosch2 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch2 algorithm of WP; that is, +// the original algorithm plus pivoting. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variant BronKerbosch1 and more sophisticated variant +// BronKerbosch3. +func (g LabeledUndirected) BronKerbosch2(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { + a := g.LabeledAdjacencyList + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { + switch { + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) + // compute P \ N(u). next 5 lines are only difference from BK1 + pnu.Set(P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(int(to.To), 0) + } + // remaining code like BK1 + pf := func(n int) bool { + r2.Set(R) + r2.SetBit(n, 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) + } + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) + } + } + if !f(r2, p2, x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.IterateOnes(pf) { + return false + } + case X.AllZeros(): + return emit(R) + } + return true + } + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() + f(R, P, X) +} + +// BronKerbosch3 finds maximal cliques in an undirected graph. +// +// The graph must not contain parallel edges or loops. +// +// See https://en.wikipedia.org/wiki/Clique_(graph_theory) and +// https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm for background. +// +// This method implements the BronKerbosch3 algorithm of WP; that is, +// the original algorithm with pivoting and degeneracy ordering. +// +// The argument is a pivot function that must return a node of P or X. +// P is guaranteed to contain at least one node. X is not. +// For example see BKPivotMaxDegree. +// +// The method calls the emit argument for each maximal clique in g, as long +// as emit returns true. If emit returns false, BronKerbosch1 returns +// immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also simpler variants BronKerbosch1 and BronKerbosch2. +func (g LabeledUndirected) BronKerbosch3(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { + a := g.LabeledAdjacencyList + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { + switch { + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) + // compute P \ N(u). next lines are only difference from BK1 + pnu.Set(P) + for _, to := range a[pivot(P, X)] { + pnu.SetBit(int(to.To), 0) + } + // remaining code like BK2 + pf := func(n int) bool { + r2.Set(R) + r2.SetBit(n, 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) + } + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) + } + } + if !f(r2, p2, x2) { + return false + } + P.SetBit(n, 0) + X.SetBit(n, 1) + return true + } + if !pnu.IterateOnes(pf) { + return false + } + case X.AllZeros(): + return emit(R) + } + return true + } + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() + // code above same as BK2 + // code below new to BK3 + ord, _ := g.DegeneracyOrdering() + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + for _, n := range ord { + R.SetBit(int(n), 1) + p2.ClearAll() + x2.ClearAll() + for _, to := range a[n] { + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) + } + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) + } + } + if !f(R, p2, x2) { + return + } + R.SetBit(int(n), 0) + P.SetBit(int(n), 0) + X.SetBit(int(n), 1) + } +} + +// ConnectedComponentBits returns a function that iterates over connected +// components of g, returning a member bitmap for each. +// +// Each call of the returned function returns the order, arc size, +// and bits of a connected component. The underlying bits allocation is +// the same for each call and is overwritten on subsequent calls. Use or +// save the bits before calling the function again. The function returns +// zeros after returning all connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentInts, ConnectedComponentReps, and +// ConnectedComponentReps. +func (g LabeledUndirected) ConnectedComponentBits() func() (order, arcSize int, bits bits.Bits) { + a := g.LabeledAdjacencyList + vg := bits.New(len(a)) // nodes visited in graph + vc := bits.New(len(a)) // nodes visited in current component + var order, arcSize int + var df func(NI) + df = func(n NI) { + vg.SetBit(int(n), 1) + vc.SetBit(int(n), 1) + order++ + arcSize += len(a[n]) + for _, nb := range a[n] { + if vg.Bit(int(nb.To)) == 0 { + df(nb.To) + } + } + return + } + var n int + return func() (o, ma int, b bits.Bits) { + for ; n < len(a); n++ { + if vg.Bit(n) == 0 { + vc.ClearAll() + order, arcSize = 0, 0 + df(NI(n)) + return order, arcSize, vc + } + } + return // return zeros signalling no more components + } +} + +// ConnectedComponenInts returns a list of component numbers (ints) for each +// node of graph g. +// +// The method assigns numbers to components 1-based, 1 through the number of +// components. Return value ci contains the component number for each node. +// Return value nc is the number of components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits, ConnectedComponentLists, and +// ConnectedComponentReps. +func (g LabeledUndirected) ConnectedComponentInts() (ci []int, nc int) { + a := g.LabeledAdjacencyList + ci = make([]int, len(a)) + var df func(NI) + df = func(nd NI) { + ci[nd] = nc + for _, to := range a[nd] { + if ci[to.To] == 0 { + df(to.To) + } + } + return + } + for nd := range a { + if ci[nd] == 0 { + nc++ + df(NI(nd)) + } + } + return +} + +// ConnectedComponentLists returns a function that iterates over connected +// components of g, returning the member list of each. +// +// Each call of the returned function returns a node list of a connected +// component and the arc size of the component. The returned function returns +// nil, 0 after returning all connected components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits, ConnectedComponentInts, and +// ConnectedComponentReps. +func (g LabeledUndirected) ConnectedComponentLists() func() (nodes []NI, arcSize int) { + a := g.LabeledAdjacencyList + vg := bits.New(len(a)) // nodes visited in graph + var l []NI // accumulated node list of current component + var ma int // accumulated arc size of current component + var df func(NI) + df = func(n NI) { + vg.SetBit(int(n), 1) + l = append(l, n) + ma += len(a[n]) + for _, nb := range a[n] { + if vg.Bit(int(nb.To)) == 0 { + df(nb.To) + } + } + return + } + var n int + return func() ([]NI, int) { + for ; n < len(a); n++ { + if vg.Bit(n) == 0 { + l, ma = nil, 0 + df(NI(n)) + return l, ma + } + } + return nil, 0 + } +} + +// ConnectedComponentReps returns a representative node from each connected +// component of g. +// +// Returned is a slice with a single representative node from each connected +// component and also parallel slices with the orders and arc sizes +// in the corresponding components. +// +// This is fairly minimal information describing connected components. +// From a representative node, other nodes in the component can be reached +// by depth first traversal for example. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits and ConnectedComponentLists which can +// collect component members in a single traversal, and IsConnected which +// is an even simpler boolean test. +func (g LabeledUndirected) ConnectedComponentReps() (reps []NI, orders, arcSizes []int) { + a := g.LabeledAdjacencyList + c := bits.New(len(a)) + var o, ma int + var df func(NI) + df = func(n NI) { + c.SetBit(int(n), 1) + o++ + ma += len(a[n]) + for _, nb := range a[n] { + if c.Bit(int(nb.To)) == 0 { + df(nb.To) + } + } + return + } + for n := range a { + if c.Bit(n) == 0 { + o, ma = 0, 0 + df(NI(n)) + reps = append(reps, NI(n)) + orders = append(orders, o) + arcSizes = append(arcSizes, ma) + } + } + return +} + +// Copy makes a deep copy of g. +// Copy also computes the arc size ma, the number of arcs. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Copy() (c LabeledUndirected, ma int) { + l, s := g.LabeledAdjacencyList.Copy() + return LabeledUndirected{l}, s +} + +// Degeneracy is a measure of dense subgraphs within a graph. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// See also method DegeneracyOrdering which returns a degeneracy node +// ordering and k-core breaks. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Degeneracy() (k int) { + a := g.LabeledAdjacencyList + // WP algorithm, attributed to Matula and Beck. + L := bits.New(len(a)) + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for range a { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + L.SetBit(int(v), 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(int(nb.To)) == 1 { + continue + } + dn := d[nb.To] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb.To { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb.To] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb.To) + } + } + return +} + +// DegeneracyOrdering computes degeneracy node ordering and k-core breaks. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// In return value ordering, nodes are ordered by their "coreness" as +// defined at https://en.wikipedia.org/wiki/Degeneracy_(graph_theory)#k-Cores. +// +// Return value kbreaks indexes ordering by coreness number. len(kbreaks) +// will be one more than the graph degeneracy as returned by the Degeneracy +// method. If degeneracy is d, d = len(kbreaks) - 1, kbreaks[d] is the last +// value in kbreaks and ordering[:kbreaks[d]] contains nodes of the d-cores +// of the graph. kbreaks[0] is always the number of nodes in g as all nodes +// are in in a 0-core. +// +// Note that definitions of "k-core" differ on whether a k-core must be a +// single connected component. This method does not resolve individual +// connected components. +// +// See also method Degeneracy which returns just the degeneracy number. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) DegeneracyOrdering() (ordering []NI, kbreaks []int) { + a := g.LabeledAdjacencyList + // WP algorithm + k := 0 + ordering = make([]NI, len(a)) + kbreaks = []int{len(a)} + L := bits.New(len(a)) + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for ox := len(a) - 1; ox >= 0; ox-- { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + for len(kbreaks) <= i { + kbreaks = append(kbreaks, ox+1) + } + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + ordering[ox] = v + L.SetBit(int(v), 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(int(nb.To)) == 1 { + continue + } + dn := d[nb.To] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb.To { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb.To] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb.To) + } + } + //for i, j := 0, k; i < j; i, j = i+1, j-1 { + // kbreaks[i], kbreaks[j] = kbreaks[j], kbreaks[i] + //} + return +} + +// Degree for undirected graphs, returns the degree of a node. +// +// The degree of a node in an undirected graph is the number of incident +// edges, where loops count twice. +// +// If g is known to be loop-free, the result is simply equivalent to len(g[n]). +// See handshaking lemma example at AdjacencyList.ArcSize. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Degree(n NI) int { + to := g.LabeledAdjacencyList[n] + d := len(to) // just "out" degree, + for _, to := range to { + if to.To == n { + d++ // except loops count twice + } + } + return d +} + +// DegreeCentralization returns the degree centralization metric of a graph. +// +// Degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple graphs of three or +// more nodes. As a special case, 0 is returned for graphs of two or fewer +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) DegreeCentralization() float64 { + a := g.LabeledAdjacencyList + if len(a) <= 2 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + return float64(len(a)*max-sum) / float64((len(a)-1)*(len(a)-2)) +} + +// Density returns density for a simple graph. +// +// See also Density function. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Density() float64 { + return Density(g.Order(), g.Size()) +} + +// Eulerian scans an undirected graph to determine if it is Eulerian. +// +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. +// +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the two end nodes of the path, and nil. +// +// Otherwise it returns an error. +// +// See also method EulerianStart, which short-circuits as soon as it finds +// a node that must be a start or end node of an Eulerian path. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Eulerian() (end1, end2 NI, err error) { + end1 = -1 + end2 = -1 + for n := range g.LabeledAdjacencyList { + switch { + case g.Degree(NI(n))%2 == 0: + case end1 < 0: + end1 = NI(n) + case end2 < 0: + end2 = NI(n) + default: + err = errors.New("non-Eulerian") + return + } + } + return +} + +// EulerianCycle finds an Eulerian cycle in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianCycle() ([]Half, error) { + c, _ := g.Copy() + return c.EulerianCycleD(c.Size()) +} + +// EulerianCycleD finds an Eulerian cycle in an undirected multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Parameter m must be the size of the undirected graph -- the +// number of edges. Use Undirected.Size if the size is unknown. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianCycleD(m int) ([]Half, error) { + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, m) + e.p[0] = Half{0, -1} + for e.s >= 0 { + v := e.top() + if err := e.pushUndir(); err != nil { + return nil, err + } + if e.top().To != v.To { + return nil, errors.New("not Eulerian") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianPath() ([]Half, error) { + c, _ := g.Copy() + start := c.EulerianStart() + if start < 0 { + start = 0 + } + return c.EulerianPathD(c.Size(), start) +} + +// EulerianPathD finds an Eulerian path in a undirected multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument m must be the correct size, or number of edges in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianPathD(m int, start NI) ([]Half, error) { + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, m) + e.p[0] = Half{start, -1} + // unlike EulerianCycle, the first path doesn't have to be a cycle. + if err := e.pushUndir(); err != nil { + return nil, err + } + e.keep() + for e.s >= 0 { + start = e.top().To + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top().To != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A graph representing an Eulerian path can have two nodes with odd degree. +// If it does, these must be the end nodes of the path. EulerianEnd scans +// for a node with an odd degree, returning immediately with the first one +// it finds. +// +// If the scan completes without finding a node with odd degree the method +// returns -1. +// +// See also method Eulerian, which completely validates a graph as representing +// an Eulerian path. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianStart() NI { + for n := range g.LabeledAdjacencyList { + if g.Degree(NI(n))%2 != 0 { + return NI(n) + } + } + return -1 +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *LabeledUndirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.LabeledUndirected.LabeledAdjacencyList + b = NI(len(a)) + s.LabeledUndirected.LabeledAdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledUndirected) InduceList(l []NI) *LabeledUndirectedSubgraph { + sub, sup := mapList(l) + return &LabeledUndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledUndirected: LabeledUndirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledUndirected) InduceBits(t bits.Bits) *LabeledUndirectedSubgraph { + sub, sup := mapBits(t) + return &LabeledUndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledUndirected: LabeledUndirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + +// IsConnected tests if an undirected graph is a single connected component. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentReps for a method returning more information. +func (g LabeledUndirected) IsConnected() bool { + a := g.LabeledAdjacencyList + if len(a) == 0 { + return true + } + b := bits.New(len(a)) + var df func(NI) + df = func(n NI) { + b.SetBit(int(n), 1) + for _, to := range a[n] { + if b.Bit(int(to.To)) == 0 { + df(to.To) + } + } + } + df(0) + return b.AllOnes() +} + +// IsTree identifies trees in undirected graphs. +// +// Return value isTree is true if the connected component reachable from root +// is a tree. Further, return value allTree is true if the entire graph g is +// connected. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) IsTree(root NI) (isTree, allTree bool) { + a := g.LabeledAdjacencyList + v := bits.New(len(a)) + v.SetAll() + var df func(NI, NI) bool + df = func(fr, n NI) bool { + if v.Bit(int(n)) == 0 { + return false + } + v.SetBit(int(n), 0) + for _, to := range a[n] { + if to.To != fr && !df(n, to.To) { + return false + } + } + return true + } + v.SetBit(int(root), 0) + for _, to := range a[root] { + if !df(root, to.To) { + return false, false + } + } + return true, v.AllZeros() +} + +// Size returns the number of edges in g. +// +// See also ArcSize and AnyLoop. +func (g LabeledUndirected) Size() int { + m2 := 0 + for fr, to := range g.LabeledAdjacencyList { + m2 += len(to) + for _, to := range to { + if to.To == NI(fr) { + m2++ + } + } + } + return m2 / 2 +} + +// Density returns edge density of a bipartite graph. +// +// Edge density is number of edges over maximum possible number of edges. +// Maximum possible number of edges in a bipartite graph is number of +// nodes of one color times number of nodes of the other color. +func (g LabeledBipartite) Density() float64 { + a := g.LabeledUndirected.LabeledAdjacencyList + s := 0 + g.Color.IterateOnes(func(n int) bool { + s += len(a[n]) + return true + }) + return float64(s) / float64(g.N0*(len(a)-g.N0)) +} + +// PermuteBiadjacency permutes a bipartite graph in place so that a prefix +// of the adjacency list encodes a biadjacency matrix. +// +// The permutation applied is returned. This would be helpful in referencing +// any externally stored node information. +// +// The biadjacency matrix is encoded as the prefix AdjacencyList[:g.N0]. +// Note though that this slice does not represent a valid complete +// AdjacencyList. BoundsOk would return false, for example. +// +// In adjacency list terms, the result of the permutation is that nodes of +// the prefix only have arcs to the suffix and nodes of the suffix only have +// arcs to the prefix. +func (g LabeledBipartite) PermuteBiadjacency() []int { + p := make([]int, g.Order()) + i := 0 + g.Color.IterateZeros(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Color.IterateOnes(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Permute(p) + g.Color.ClearAll() + for i := g.N0; i < g.Order(); i++ { + g.Color.SetBit(i, 1) + } + return p +} diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go index bc3db73..260cfe5 100644 --- a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go @@ -350,8 +350,8 @@ func (db *hostKeyDB) check(address string, remote net.Addr, remoteKey ssh.Public return db.checkAddr(hostToCheck, remoteKey) } -// checkAddrs checks if we can find the given public key for any of -// the given addresses. If we only find an entry for the IP address, +// checkAddr checks if we can find the given public key for the +// given address. If we only find an entry for the IP address, // or only the hostname, then this still succeeds. func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { // TODO(hanwen): are these the right semantics? What if there diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go index 9a88759..9d666ff 100644 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -159,6 +159,10 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { return keyClearScreen, b[1:] case 23: // ^W return keyDeleteWord, b[1:] + case 14: // ^N + return keyDown, b[1:] + case 16: // ^P + return keyUp, b[1:] } } diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go index 553ead7..f6026b9 100644 --- a/vendor/golang.org/x/net/proxy/proxy.go +++ b/vendor/golang.org/x/net/proxy/proxy.go @@ -79,8 +79,13 @@ func FromURL(u *url.URL, forward Dialer) (Dialer, error) { } switch u.Scheme { - case "socks5": - return SOCKS5("tcp", u.Host, auth, forward) + case "socks5", "socks5h": + addr := u.Hostname() + port := u.Port() + if port == "" { + port = "1080" + } + return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward) } // If the scheme doesn't match any of the built-in schemes, see if it diff --git a/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s b/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s new file mode 100644 index 0000000..6f98ba5 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s @@ -0,0 +1,29 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !gccgo + +#include "textflag.h" + +// +// System call support for ARM64, NetBSD +// + +// Just jump to package syscall's implementation for all these functions. +// The runtime may know about them. + +TEXT ·Syscall(SB),NOSPLIT,$0-56 + B syscall·Syscall(SB) + +TEXT ·Syscall6(SB),NOSPLIT,$0-80 + B syscall·Syscall6(SB) + +TEXT ·Syscall9(SB),NOSPLIT,$0-104 + B syscall·Syscall9(SB) + +TEXT ·RawSyscall(SB),NOSPLIT,$0-56 + B syscall·RawSyscall(SB) + +TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 + B syscall·RawSyscall6(SB) diff --git a/vendor/golang.org/x/sys/unix/fcntl.go b/vendor/golang.org/x/sys/unix/fcntl.go index 9379ba9..39c03f1 100644 --- a/vendor/golang.org/x/sys/unix/fcntl.go +++ b/vendor/golang.org/x/sys/unix/fcntl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd linux netbsd openbsd +// +build dragonfly freebsd linux netbsd openbsd package unix diff --git a/vendor/golang.org/x/sys/unix/fcntl_darwin.go b/vendor/golang.org/x/sys/unix/fcntl_darwin.go new file mode 100644 index 0000000..5868a4a --- /dev/null +++ b/vendor/golang.org/x/sys/unix/fcntl_darwin.go @@ -0,0 +1,18 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unix + +import "unsafe" + +// FcntlInt performs a fcntl syscall on fd with the provided command and argument. +func FcntlInt(fd uintptr, cmd, arg int) (int, error) { + return fcntl(int(fd), cmd, arg) +} + +// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. +func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { + _, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(lk)))) + return err +} diff --git a/vendor/golang.org/x/sys/unix/mkall.sh b/vendor/golang.org/x/sys/unix/mkall.sh index b9804c0..d74115a 100644 --- a/vendor/golang.org/x/sys/unix/mkall.sh +++ b/vendor/golang.org/x/sys/unix/mkall.sh @@ -62,12 +62,12 @@ _* | *_ | _) ;; aix_ppc) mkerrors="$mkerrors -maix32" - mksyscall="./mksyscall_aix_ppc.pl -aix" + mksyscall="go run mksyscall_aix_ppc.go -aix" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; aix_ppc64) mkerrors="$mkerrors -maix64" - mksyscall="./mksyscall_aix_ppc64.pl -aix" + mksyscall="go run mksyscall_aix_ppc64.go -aix" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; darwin_386) @@ -99,31 +99,31 @@ darwin_arm64) dragonfly_amd64) mkerrors="$mkerrors -m64" mksyscall="go run mksyscall.go -dragonfly" - mksysnum="go run mksysnum.go 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; freebsd_386) mkerrors="$mkerrors -m32" mksyscall="go run mksyscall.go -l32" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; freebsd_amd64) mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; freebsd_arm) mkerrors="$mkerrors" mksyscall="go run mksyscall.go -l32 -arm" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" # Let the type of C char be signed for making the bare syscall # API consistent across platforms. mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" ;; freebsd_arm64) mkerrors="$mkerrors -m64" - mksysnum="go run mksysnum.go 'http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; netbsd_386) @@ -150,21 +150,21 @@ openbsd_386) mkerrors="$mkerrors -m32" mksyscall="go run mksyscall.go -l32 -openbsd" mksysctl="./mksysctl_openbsd.pl" - mksysnum="go run mksysnum.go 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_amd64) mkerrors="$mkerrors -m64" mksyscall="go run mksyscall.go -openbsd" mksysctl="./mksysctl_openbsd.pl" - mksysnum="go run mksysnum.go 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" mktypes="GOARCH=$GOARCH go tool cgo -godefs" ;; openbsd_arm) mkerrors="$mkerrors" mksyscall="go run mksyscall.go -l32 -openbsd -arm" mksysctl="./mksysctl_openbsd.pl" - mksysnum="go run mksysnum.go 'http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" + mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'" # Let the type of C char be signed for making the bare syscall # API consistent across platforms. mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char" diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index 178077f..2268e8b 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -179,8 +179,10 @@ struct ltchars { #include #include #include +#include #include #include +#include #include #include #include @@ -453,7 +455,7 @@ ccflags="$@" $2 !~ "MNT_BITS" && $2 ~ /^(MS|MNT|UMOUNT)_/ || $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || - $2 ~ /^(O|F|E?FD|NAME|S|PTRACE|PT)_/ || + $2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ || $2 ~ /^KEXEC_/ || $2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || @@ -474,12 +476,13 @@ ccflags="$@" $2 ~ /^CLONE_[A-Z_]+/ || $2 !~ /^(BPF_TIMEVAL)$/ && $2 ~ /^(BPF|DLT)_/ || - $2 ~ /^CLOCK_/ || + $2 ~ /^(CLOCK|TIMER)_/ || $2 ~ /^CAN_/ || $2 ~ /^CAP_/ || $2 ~ /^ALG_/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ || $2 ~ /^GRND_/ || + $2 ~ /^RND/ || $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || $2 ~ /^KEYCTL_/ || $2 ~ /^PERF_EVENT_IOC_/ || diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go new file mode 100644 index 0000000..f2c58fb --- /dev/null +++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go @@ -0,0 +1,404 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +/* +This program reads a file containing function prototypes +(like syscall_aix.go) and generates system call bodies. +The prototypes are marked by lines beginning with "//sys" +and read like func declarations if //sys is replaced by func, but: + * The parameter lists must give a name for each argument. + This includes return parameters. + * The parameter lists must give a type for each argument: + the (x, y, z int) shorthand is not allowed. + * If the return parameter is an error number, it must be named err. + * If go func name needs to be different than its libc name, + * or the function is not in libc, name could be specified + * at the end, after "=" sign, like + //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt +*/ +package main + +import ( + "bufio" + "flag" + "fmt" + "os" + "regexp" + "strings" +) + +var ( + b32 = flag.Bool("b32", false, "32bit big-endian") + l32 = flag.Bool("l32", false, "32bit little-endian") + aix = flag.Bool("aix", false, "aix") + tags = flag.String("tags", "", "build tags") +) + +// cmdLine returns this programs's commandline arguments +func cmdLine() string { + return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ") +} + +// buildTags returns build tags +func buildTags() string { + return *tags +} + +// Param is function parameter +type Param struct { + Name string + Type string +} + +// usage prints the program usage +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n") + os.Exit(1) +} + +// parseParamList parses parameter list and returns a slice of parameters +func parseParamList(list string) []string { + list = strings.TrimSpace(list) + if list == "" { + return []string{} + } + return regexp.MustCompile(`\s*,\s*`).Split(list, -1) +} + +// parseParam splits a parameter into name and type +func parseParam(p string) Param { + ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p) + if ps == nil { + fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p) + os.Exit(1) + } + return Param{ps[1], ps[2]} +} + +func main() { + flag.Usage = usage + flag.Parse() + if len(flag.Args()) <= 0 { + fmt.Fprintf(os.Stderr, "no files to parse provided\n") + usage() + } + + endianness := "" + if *b32 { + endianness = "big-endian" + } else if *l32 { + endianness = "little-endian" + } + + pack := "" + text := "" + cExtern := "/*\n#include \n#include \n" + for _, path := range flag.Args() { + file, err := os.Open(path) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + s := bufio.NewScanner(file) + for s.Scan() { + t := s.Text() + t = strings.TrimSpace(t) + t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `) + if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" { + pack = p[1] + } + nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t) + if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil { + continue + } + + // Line must be of the form + // func Open(path string, mode int, perm int) (fd int, err error) + // Split into name, in params, out params. + f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t) + if f == nil { + fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t) + os.Exit(1) + } + funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6] + + // Split argument lists on comma. + in := parseParamList(inps) + out := parseParamList(outps) + + inps = strings.Join(in, ", ") + outps = strings.Join(out, ", ") + + // Try in vain to keep people from editing this file. + // The theory is that they jump into the middle of the file + // without reading the header. + text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n" + + // Check if value return, err return available + errvar := "" + retvar := "" + rettype := "" + for _, param := range out { + p := parseParam(param) + if p.Type == "error" { + errvar = p.Name + } else { + retvar = p.Name + rettype = p.Type + } + } + + // System call name. + if sysname == "" { + sysname = funct + } + sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`) + sysname = strings.ToLower(sysname) // All libc functions are lowercase. + + cRettype := "" + if rettype == "unsafe.Pointer" { + cRettype = "uintptr_t" + } else if rettype == "uintptr" { + cRettype = "uintptr_t" + } else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil { + cRettype = "uintptr_t" + } else if rettype == "int" { + cRettype = "int" + } else if rettype == "int32" { + cRettype = "int" + } else if rettype == "int64" { + cRettype = "long long" + } else if rettype == "uint32" { + cRettype = "unsigned int" + } else if rettype == "uint64" { + cRettype = "unsigned long long" + } else { + cRettype = "int" + } + if sysname == "exit" { + cRettype = "void" + } + + // Change p.Types to c + var cIn []string + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "string" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t", "size_t") + } else if p.Type == "unsafe.Pointer" { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "uintptr" { + cIn = append(cIn, "uintptr_t") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + cIn = append(cIn, "uintptr_t") + } else if p.Type == "int" { + cIn = append(cIn, "int") + } else if p.Type == "int32" { + cIn = append(cIn, "int") + } else if p.Type == "int64" { + cIn = append(cIn, "long long") + } else if p.Type == "uint32" { + cIn = append(cIn, "unsigned int") + } else if p.Type == "uint64" { + cIn = append(cIn, "unsigned long long") + } else { + cIn = append(cIn, "int") + } + } + + if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" { + // Imports of system calls from libc + cExtern += fmt.Sprintf("%s %s", cRettype, sysname) + cIn := strings.Join(cIn, ", ") + cExtern += fmt.Sprintf("(%s);\n", cIn) + } + + // So file name. + if *aix { + if modname == "" { + modname = "libc.a/shr_64.o" + } else { + fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct) + os.Exit(1) + } + } + + strconvfunc := "C.CString" + + // Go function header. + if outps != "" { + outps = fmt.Sprintf(" (%s)", outps) + } + if text != "" { + text += "\n" + } + + text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps) + + // Prepare arguments to Syscall. + var args []string + n := 0 + argN := 0 + for _, param := range in { + p := parseParam(param) + if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil { + args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))") + } else if p.Type == "string" && errvar != "" { + text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if p.Type == "string" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n") + text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n)) + n++ + } else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil { + // Convert slice into pointer, length. + // Have to be careful not to take address of &a[0] if len == 0: + // pass nil in that case. + text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1]) + text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n)) + n++ + text += fmt.Sprintf("\tvar _p%d int\n", n) + text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name) + args = append(args, fmt.Sprintf("C.size_t(_p%d)", n)) + n++ + } else if p.Type == "int64" && endianness != "" { + if endianness == "big-endian" { + args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name)) + } + n++ + } else if p.Type == "bool" { + text += fmt.Sprintf("\tvar _p%d uint32\n", n) + text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n) + args = append(args, fmt.Sprintf("_p%d", n)) + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil { + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) + } else if p.Type == "unsafe.Pointer" { + args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name)) + } else if p.Type == "int" { + if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) { + args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name)) + } else if argN == 0 && funct == "fcntl" { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } + } else if p.Type == "int32" { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } else if p.Type == "int64" { + args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name)) + } else if p.Type == "uint32" { + args = append(args, fmt.Sprintf("C.uint(%s)", p.Name)) + } else if p.Type == "uint64" { + args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name)) + } else if p.Type == "uintptr" { + args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + args = append(args, fmt.Sprintf("C.int(%s)", p.Name)) + } + argN++ + } + + // Actual call. + arglist := strings.Join(args, ", ") + call := "" + if sysname == "exit" { + if errvar != "" { + call += "er :=" + } else { + call += "" + } + } else if errvar != "" { + call += "r0,er :=" + } else if retvar != "" { + call += "r0,_ :=" + } else { + call += "" + } + call += fmt.Sprintf("C.%s(%s)", sysname, arglist) + + // Assign return values. + body := "" + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + } else { + reg = "r0" + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + + // verify return + if sysname != "exit" && errvar != "" { + if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil { + body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } else { + body += "\tif (r0 ==-1 && er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } + } else if errvar != "" { + body += "\tif (er != nil) {\n" + body += fmt.Sprintf("\t\t%s = er\n", errvar) + body += "\t}\n" + } + + text += fmt.Sprintf("\t%s\n", call) + text += body + + text += "\treturn\n" + text += "}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text) +} + +const srcTemplate = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + + +%s +*/ +import "C" +import ( + "unsafe" +) + + +%s + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl deleted file mode 100644 index c44de8d..0000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl +++ /dev/null @@ -1,384 +0,0 @@ -#!/usr/bin/env perl -# Copyright 2018 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This program reads a file containing function prototypes -# (like syscall_aix.go) and generates system call bodies. -# The prototypes are marked by lines beginning with "//sys" -# and read like func declarations if //sys is replaced by func, but: -# * The parameter lists must give a name for each argument. -# This includes return parameters. -# * The parameter lists must give a type for each argument: -# the (x, y, z int) shorthand is not allowed. -# * If the return parameter is an error number, it must be named err. -# * If go func name needs to be different than its libc name, -# * or the function is not in libc, name could be specified -# * at the end, after "=" sign, like -# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt - -use strict; - -my $cmdline = "mksyscall_aix_ppc.pl " . join(' ', @ARGV); -my $errors = 0; -my $_32bit = ""; -my $tags = ""; # build tags -my $aix = 0; -my $solaris = 0; - -binmode STDOUT; - -if($ARGV[0] eq "-b32") { - $_32bit = "big-endian"; - shift; -} elsif($ARGV[0] eq "-l32") { - $_32bit = "little-endian"; - shift; -} -if($ARGV[0] eq "-aix") { - $aix = 1; - shift; -} -if($ARGV[0] eq "-tags") { - shift; - $tags = $ARGV[0]; - shift; -} - -if($ARGV[0] =~ /^-/) { - print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n"; - exit 1; -} - -sub parseparamlist($) { - my ($list) = @_; - $list =~ s/^\s*//; - $list =~ s/\s*$//; - if($list eq "") { - return (); - } - return split(/\s*,\s*/, $list); -} - -sub parseparam($) { - my ($p) = @_; - if($p !~ /^(\S*) (\S*)$/) { - print STDERR "$ARGV:$.: malformed parameter: $p\n"; - $errors = 1; - return ("xx", "int"); - } - return ($1, $2); -} - -my $package = ""; -my $text = ""; -my $c_extern = "/*\n#include \n#include \n"; -my @vars = (); -while(<>) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - $package = $1 if !$package && /^package (\S+)$/; - my $nonblock = /^\/\/sysnb /; - next if !/^\/\/sys / && !$nonblock; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, err error) - # Split into name, in params, out params. - if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - $in = join(', ', @in); - $out = join(', ', @out); - - # Try in vain to keep people from editing this file. - # The theory is that they jump into the middle of the file - # without reading the header. - $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - - # Check if value return, err return available - my $errvar = ""; - my $retvar = ""; - my $rettype = ""; - foreach my $p (@out) { - my ($name, $type) = parseparam($p); - if($type eq "error") { - $errvar = $name; - } else { - $retvar = $name; - $rettype = $type; - } - } - - # System call name. - #if($func ne "fcntl") { - - if($sysname eq "") { - $sysname = "$func"; - } - - $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; - $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. - - my $C_rettype = ""; - if($rettype eq "unsafe.Pointer") { - $C_rettype = "uintptr_t"; - } elsif($rettype eq "uintptr") { - $C_rettype = "uintptr_t"; - } elsif($rettype =~ /^_/) { - $C_rettype = "uintptr_t"; - } elsif($rettype eq "int") { - $C_rettype = "int"; - } elsif($rettype eq "int32") { - $C_rettype = "int"; - } elsif($rettype eq "int64") { - $C_rettype = "long long"; - } elsif($rettype eq "uint32") { - $C_rettype = "unsigned int"; - } elsif($rettype eq "uint64") { - $C_rettype = "unsigned long long"; - } else { - $C_rettype = "int"; - } - if($sysname eq "exit") { - $C_rettype = "void"; - } - - # Change types to c - my @c_in = (); - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @c_in, "uintptr_t"; - } elsif($type eq "string") { - push @c_in, "uintptr_t"; - } elsif($type =~ /^\[\](.*)/) { - push @c_in, "uintptr_t", "size_t"; - } elsif($type eq "unsafe.Pointer") { - push @c_in, "uintptr_t"; - } elsif($type eq "uintptr") { - push @c_in, "uintptr_t"; - } elsif($type =~ /^_/) { - push @c_in, "uintptr_t"; - } elsif($type eq "int") { - push @c_in, "int"; - } elsif($type eq "int32") { - push @c_in, "int"; - } elsif($type eq "int64") { - push @c_in, "long long"; - } elsif($type eq "uint32") { - push @c_in, "unsigned int"; - } elsif($type eq "uint64") { - push @c_in, "unsigned long long"; - } else { - push @c_in, "int"; - } - } - - if ($func ne "fcntl" && $func ne "FcntlInt" && $func ne "readlen" && $func ne "writelen") { - # Imports of system calls from libc - $c_extern .= "$C_rettype $sysname"; - my $c_in = join(', ', @c_in); - $c_extern .= "($c_in);\n"; - } - - # So file name. - if($aix) { - if($modname eq "") { - $modname = "libc.a/shr_64.o"; - } else { - print STDERR "$func: only syscall using libc are available\n"; - $errors = 1; - next; - } - } - - my $strconvfunc = "C.CString"; - my $strconvtype = "*byte"; - - # Go function header. - if($out ne "") { - $out = " ($out)"; - } - if($text ne "") { - $text .= "\n" - } - - $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ; - - # Prepare arguments to call. - my @args = (); - my $n = 0; - my $arg_n = 0; - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @args, "C.uintptr_t(uintptr(unsafe.Pointer($name)))"; - } elsif($type eq "string" && $errvar ne "") { - $text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n"; - push @args, "C.uintptr_t(_p$n)"; - $n++; - } elsif($type eq "string") { - print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; - $text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n"; - push @args, "C.uintptr_t(_p$n)"; - $n++; - } elsif($type =~ /^\[\](.*)/) { - # Convert slice into pointer, length. - # Have to be careful not to take address of &a[0] if len == 0: - # pass nil in that case. - $text .= "\tvar _p$n *$1\n"; - $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; - push @args, "C.uintptr_t(uintptr(unsafe.Pointer(_p$n)))"; - $n++; - $text .= "\tvar _p$n int\n"; - $text .= "\t_p$n = len($name)\n"; - push @args, "C.size_t(_p$n)"; - $n++; - } elsif($type eq "int64" && $_32bit ne "") { - if($_32bit eq "big-endian") { - push @args, "uintptr($name >> 32)", "uintptr($name)"; - } else { - push @args, "uintptr($name)", "uintptr($name >> 32)"; - } - $n++; - } elsif($type eq "bool") { - $text .= "\tvar _p$n uint32\n"; - $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; - push @args, "_p$n"; - $n++; - } elsif($type =~ /^_/) { - push @args, "C.uintptr_t(uintptr($name))"; - } elsif($type eq "unsafe.Pointer") { - push @args, "C.uintptr_t(uintptr($name))"; - } elsif($type eq "int") { - if (($arg_n == 2) && (($func eq "readlen") || ($func eq "writelen"))) { - push @args, "C.size_t($name)"; - } elsif ($arg_n == 0 && $func eq "fcntl") { - push @args, "C.uintptr_t($name)"; - } elsif (($arg_n == 2) && (($func eq "fcntl") || ($func eq "FcntlInt"))) { - push @args, "C.uintptr_t($name)"; - } else { - push @args, "C.int($name)"; - } - } elsif($type eq "int32") { - push @args, "C.int($name)"; - } elsif($type eq "int64") { - push @args, "C.longlong($name)"; - } elsif($type eq "uint32") { - push @args, "C.uint($name)"; - } elsif($type eq "uint64") { - push @args, "C.ulonglong($name)"; - } elsif($type eq "uintptr") { - push @args, "C.uintptr_t($name)"; - } else { - push @args, "C.int($name)"; - } - $arg_n++; - } - my $nargs = @args; - - - # Determine which form to use; pad args with zeros. - if ($nonblock) { - } - - my $args = join(', ', @args); - my $call = ""; - if ($sysname eq "exit") { - if ($errvar ne "") { - $call .= "er :="; - } else { - $call .= ""; - } - } elsif ($errvar ne "") { - $call .= "r0,er :="; - } elsif ($retvar ne "") { - $call .= "r0,_ :="; - } else { - $call .= "" - } - $call .= "C.$sysname($args)"; - - # Assign return values. - my $body = ""; - my $failexpr = ""; - - for(my $i=0; $i<@out; $i++) { - my $p = $out[$i]; - my ($name, $type) = parseparam($p); - my $reg = ""; - if($name eq "err") { - $reg = "e1"; - } else { - $reg = "r0"; - } - if($reg ne "e1" ) { - $body .= "\t$name = $type($reg)\n"; - } - } - - # verify return - if ($sysname ne "exit" && $errvar ne "") { - if ($C_rettype =~ /^uintptr/) { - $body .= "\tif \(uintptr\(r0\) ==\^uintptr\(0\) && er != nil\) {\n"; - $body .= "\t\t$errvar = er\n"; - $body .= "\t}\n"; - } else { - $body .= "\tif \(r0 ==-1 && er != nil\) {\n"; - $body .= "\t\t$errvar = er\n"; - $body .= "\t}\n"; - } - } elsif ($errvar ne "") { - $body .= "\tif \(er != nil\) {\n"; - $body .= "\t\t$errvar = er\n"; - $body .= "\t}\n"; - } - - $text .= "\t$call\n"; - $text .= $body; - - $text .= "\treturn\n"; - $text .= "}\n"; -} - -if($errors) { - exit 1; -} - -print < 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name) + argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n)) + argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n)) + n++ + } else if p.Type == "int64" && endianness != "" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n") + } else if p.Type == "bool" { + fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n") + } else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" { + argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else if p.Type == "int" { + if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) { + // These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock + argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + + } else { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } + } else if p.Type == "int32" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int32", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } else if p.Type == "int64" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s int64", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name)) + } else if p.Type == "uint32" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name)) + } else if p.Type == "uint64" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name)) + } else if p.Type == "uintptr" { + argscommon = append(argscommon, p.Name) + argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name)) + argsgc = append(argsgc, p.Name) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name)) + } else { + argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name)) + argscall = append(argscall, fmt.Sprintf("%s int", p.Name)) + argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name)) + argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name)) + } + argN++ + } + nargs := len(argsgc) + + // COMMON function generation + argscommonlist := strings.Join(argscommon, ", ") + callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist) + ret := []string{"_", "_"} + body := "" + doErrno := false + for i := 0; i < len(out); i++ { + p := parseParam(out[i]) + reg := "" + if p.Name == "err" { + reg = "e1" + ret[1] = reg + doErrno = true + } else { + reg = "r0" + ret[0] = reg + } + if p.Type == "bool" { + reg = fmt.Sprintf("%s != 0", reg) + } + if reg != "e1" { + body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg) + } + } + if ret[0] == "_" && ret[1] == "_" { + textcommon += fmt.Sprintf("\t%s\n", callcommon) + } else { + textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon) + } + textcommon += body + + if doErrno { + textcommon += "\tif e1 != 0 {\n" + textcommon += "\t\terr = errnoErr(e1)\n" + textcommon += "\t}\n" + } + textcommon += "\treturn\n" + textcommon += "}\n" + + if onlyCommon { + continue + } + + // CALL Prototype + callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", ")) + + // GC function generation + asm := "syscall6" + if nonblock != nil { + asm = "rawSyscall6" + } + + if len(argsgc) <= 6 { + for len(argsgc) < 6 { + argsgc = append(argsgc, "0") + } + } else { + fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct) + os.Exit(1) + } + argsgclist := strings.Join(argsgc, ", ") + callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist) + + textgc += callProto + textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc) + textgc += "\treturn\n}\n" + + // GCCGO function generation + argsgccgolist := strings.Join(argsgccgo, ", ") + callgccgo := fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist) + textgccgo += callProto + textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo) + textgccgo += "\te1 = syscall.GetErrno()\n" + textgccgo += "\treturn\n}\n" + } + if err := s.Err(); err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + file.Close() + } + imp := "" + if pack != "unix" { + imp = "import \"golang.org/x/sys/unix\"\n" + + } + + // Print zsyscall_aix_ppc64.go + err := ioutil.WriteFile("zsyscall_aix_ppc64.go", + []byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + // Print zsyscall_aix_ppc64_gc.go + vardecls := "\t" + strings.Join(vars, ",\n\t") + vardecls += " syscallFunc" + err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go", + []byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + // Print zsyscall_aix_ppc64_gccgo.go + err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go", + []byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)), + 0644) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } +} + +const srcTemplate1 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s + +package %s + +import ( + "unsafe" +) + + +%s + +%s +` +const srcTemplate2 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s +// +build !gccgo + +package %s + +import ( + "unsafe" +) +%s +%s +%s +type syscallFunc uintptr + +var ( +%s +) + +// Implemented in runtime/syscall_aix.go. +func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) +func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +%s +` +const srcTemplate3 = `// %s +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build %s +// +build gccgo + +package %s + +%s +*/ +import "C" +import ( + "syscall" +) + + +%s + +%s +` diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl deleted file mode 100644 index 53df26b..0000000 --- a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl +++ /dev/null @@ -1,579 +0,0 @@ -#!/usr/bin/env perl -# Copyright 2018 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# This program reads a file containing function prototypes -# (like syscall_aix.go) and generates system call bodies. -# The prototypes are marked by lines beginning with "//sys" -# and read like func declarations if //sys is replaced by func, but: -# * The parameter lists must give a name for each argument. -# This includes return parameters. -# * The parameter lists must give a type for each argument: -# the (x, y, z int) shorthand is not allowed. -# * If the return parameter is an error number, it must be named err. -# * If go func name needs to be different than its libc name, -# * or the function is not in libc, name could be specified -# * at the end, after "=" sign, like -# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt - -# This program will generate three files and handle both gc and gccgo implementation: -# - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation) -# - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6 -# - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type. - -# The generated code looks like this -# -# zsyscall_aix_ppc64.go -# func asyscall(...) (n int, err error) { -# // Pointer Creation -# r1, e1 := callasyscall(...) -# // Type Conversion -# // Error Handler -# return -# } -# -# zsyscall_aix_ppc64_gc.go -# //go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o" -# //go:linkname libc_asyscall libc_asyscall -# var asyscall syscallFunc -# -# func callasyscall(...) (r1 uintptr, e1 Errno) { -# r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... ) -# return -# } -# -# zsyscall_aix_ppc64_ggcgo.go -# /* -# int asyscall(...) -# -# */ -# import "C" -# -# func callasyscall(...) (r1 uintptr, e1 Errno) { -# r1 = uintptr(C.asyscall(...)) -# e1 = syscall.GetErrno() -# return -# } - - - -use strict; - -my $cmdline = "mksyscall_aix_ppc64.pl " . join(' ', @ARGV); -my $errors = 0; -my $_32bit = ""; -my $tags = ""; # build tags -my $aix = 0; -my $solaris = 0; - -binmode STDOUT; - -if($ARGV[0] eq "-b32") { - $_32bit = "big-endian"; - shift; -} elsif($ARGV[0] eq "-l32") { - $_32bit = "little-endian"; - shift; -} -if($ARGV[0] eq "-aix") { - $aix = 1; - shift; -} -if($ARGV[0] eq "-tags") { - shift; - $tags = $ARGV[0]; - shift; -} - -if($ARGV[0] =~ /^-/) { - print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n"; - exit 1; -} - -sub parseparamlist($) { - my ($list) = @_; - $list =~ s/^\s*//; - $list =~ s/\s*$//; - if($list eq "") { - return (); - } - return split(/\s*,\s*/, $list); -} - -sub parseparam($) { - my ($p) = @_; - if($p !~ /^(\S*) (\S*)$/) { - print STDERR "$ARGV:$.: malformed parameter: $p\n"; - $errors = 1; - return ("xx", "int"); - } - return ($1, $2); -} - -my $package = ""; -# GCCGO -my $textgccgo = ""; -my $c_extern = "/*\n#include \n"; -# GC -my $textgc = ""; -my $dynimports = ""; -my $linknames = ""; -my @vars = (); -# COMMUN -my $textcommon = ""; - -while(<>) { - chomp; - s/\s+/ /g; - s/^\s+//; - s/\s+$//; - $package = $1 if !$package && /^package (\S+)$/; - my $nonblock = /^\/\/sysnb /; - next if !/^\/\/sys / && !$nonblock; - - # Line must be of the form - # func Open(path string, mode int, perm int) (fd int, err error) - # Split into name, in params, out params. - if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) { - print STDERR "$ARGV:$.: malformed //sys declaration\n"; - $errors = 1; - next; - } - my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6); - - # Split argument lists on comma. - my @in = parseparamlist($in); - my @out = parseparamlist($out); - - $in = join(', ', @in); - $out = join(', ', @out); - - if($sysname eq "") { - $sysname = "$func"; - } - - my $onlyCommon = 0; - if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") { - # This function call another syscall which is already implemented. - # Therefore, the gc and gccgo part must not be generated. - $onlyCommon = 1 - } - - # Try in vain to keep people from editing this file. - # The theory is that they jump into the middle of the file - # without reading the header. - - $textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - if (!$onlyCommon) { - $textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - $textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"; - } - - - # Check if value return, err return available - my $errvar = ""; - my $retvar = ""; - my $rettype = ""; - foreach my $p (@out) { - my ($name, $type) = parseparam($p); - if($type eq "error") { - $errvar = $name; - } else { - $retvar = $name; - $rettype = $type; - } - } - - - $sysname =~ s/([a-z])([A-Z])/${1}_$2/g; - $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. - - # GCCGO Prototype return type - my $C_rettype = ""; - if($rettype eq "unsafe.Pointer") { - $C_rettype = "uintptr_t"; - } elsif($rettype eq "uintptr") { - $C_rettype = "uintptr_t"; - } elsif($rettype =~ /^_/) { - $C_rettype = "uintptr_t"; - } elsif($rettype eq "int") { - $C_rettype = "int"; - } elsif($rettype eq "int32") { - $C_rettype = "int"; - } elsif($rettype eq "int64") { - $C_rettype = "long long"; - } elsif($rettype eq "uint32") { - $C_rettype = "unsigned int"; - } elsif($rettype eq "uint64") { - $C_rettype = "unsigned long long"; - } else { - $C_rettype = "int"; - } - if($sysname eq "exit") { - $C_rettype = "void"; - } - - # GCCGO Prototype arguments type - my @c_in = (); - foreach my $i (0 .. $#in) { - my ($name, $type) = parseparam($in[$i]); - if($type =~ /^\*/) { - push @c_in, "uintptr_t"; - } elsif($type eq "string") { - push @c_in, "uintptr_t"; - } elsif($type =~ /^\[\](.*)/) { - push @c_in, "uintptr_t", "size_t"; - } elsif($type eq "unsafe.Pointer") { - push @c_in, "uintptr_t"; - } elsif($type eq "uintptr") { - push @c_in, "uintptr_t"; - } elsif($type =~ /^_/) { - push @c_in, "uintptr_t"; - } elsif($type eq "int") { - if (($i == 0 || $i == 2) && $func eq "fcntl"){ - # These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock - push @c_in, "uintptr_t"; - } else { - push @c_in, "int"; - } - } elsif($type eq "int32") { - push @c_in, "int"; - } elsif($type eq "int64") { - push @c_in, "long long"; - } elsif($type eq "uint32") { - push @c_in, "unsigned int"; - } elsif($type eq "uint64") { - push @c_in, "unsigned long long"; - } else { - push @c_in, "int"; - } - } - - if (!$onlyCommon){ - # GCCGO Prototype Generation - # Imports of system calls from libc - $c_extern .= "$C_rettype $sysname"; - my $c_in = join(', ', @c_in); - $c_extern .= "($c_in);\n"; - } - - # GC Library name - if($modname eq "") { - $modname = "libc.a/shr_64.o"; - } else { - print STDERR "$func: only syscall using libc are available\n"; - $errors = 1; - next; - } - my $sysvarname = "libc_${sysname}"; - - if (!$onlyCommon){ - # GC Runtime import of function to allow cross-platform builds. - $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n"; - # GC Link symbol to proc address variable. - $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n"; - # GC Library proc address variable. - push @vars, $sysvarname; - } - - my $strconvfunc ="BytePtrFromString"; - my $strconvtype = "*byte"; - - # Go function header. - if($out ne "") { - $out = " ($out)"; - } - if($textcommon ne "") { - $textcommon .= "\n" - } - - $textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ; - - # Prepare arguments to call. - my @argscommun = (); # Arguments in the commun part - my @argscall = (); # Arguments for call prototype - my @argsgc = (); # Arguments for gc call (with syscall6) - my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall) - my $n = 0; - my $arg_n = 0; - foreach my $p (@in) { - my ($name, $type) = parseparam($p); - if($type =~ /^\*/) { - push @argscommun, "uintptr(unsafe.Pointer($name))"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } elsif($type eq "string" && $errvar ne "") { - $textcommon .= "\tvar _p$n $strconvtype\n"; - $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; - $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - - push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; - push @argscall, "_p$n uintptr "; - push @argsgc, "_p$n"; - push @argsgccgo, "C.uintptr_t(_p$n)"; - $n++; - } elsif($type eq "string") { - print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n"; - $textcommon .= "\tvar _p$n $strconvtype\n"; - $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n"; - $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n"; - - push @argscommun, "uintptr(unsafe.Pointer(_p$n))"; - push @argscall, "_p$n uintptr"; - push @argsgc, "_p$n"; - push @argsgccgo, "C.uintptr_t(_p$n)"; - $n++; - } elsif($type =~ /^\[\](.*)/) { - # Convert slice into pointer, length. - # Have to be careful not to take address of &a[0] if len == 0: - # pass nil in that case. - $textcommon .= "\tvar _p$n *$1\n"; - $textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n"; - push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)"; - push @argscall, "_p$n uintptr", "_lenp$n int"; - push @argsgc, "_p$n", "uintptr(_lenp$n)"; - push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)"; - $n++; - } elsif($type eq "int64" && $_32bit ne "") { - print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n"; - # if($_32bit eq "big-endian") { - # push @args, "uintptr($name >> 32)", "uintptr($name)"; - # } else { - # push @args, "uintptr($name)", "uintptr($name >> 32)"; - # } - # $n++; - } elsif($type eq "bool") { - print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n"; - # $text .= "\tvar _p$n uint32\n"; - # $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n"; - # push @args, "_p$n"; - # $n++; - } elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") { - push @argscommun, "uintptr($name)"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } elsif($type eq "int") { - if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) { - # These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock - push @argscommun, "uintptr($name)"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } else { - push @argscommun, "$name"; - push @argscall, "$name int"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.int($name)"; - } - } elsif($type eq "int32") { - push @argscommun, "$name"; - push @argscall, "$name int32"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.int($name)"; - } elsif($type eq "int64") { - push @argscommun, "$name"; - push @argscall, "$name int64"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.longlong($name)"; - } elsif($type eq "uint32") { - push @argscommun, "$name"; - push @argscall, "$name uint32"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.uint($name)"; - } elsif($type eq "uint64") { - push @argscommun, "$name"; - push @argscall, "$name uint64"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.ulonglong($name)"; - } elsif($type eq "uintptr") { - push @argscommun, "$name"; - push @argscall, "$name uintptr"; - push @argsgc, "$name"; - push @argsgccgo, "C.uintptr_t($name)"; - } else { - push @argscommun, "int($name)"; - push @argscall, "$name int"; - push @argsgc, "uintptr($name)"; - push @argsgccgo, "C.int($name)"; - } - $arg_n++; - } - my $nargs = @argsgc; - - # COMMUN function generation - my $argscommun = join(', ', @argscommun); - my $callcommun = "call$sysname($argscommun)"; - my @ret = ("_", "_"); - my $body = ""; - my $do_errno = 0; - for(my $i=0; $i<@out; $i++) { - my $p = $out[$i]; - my ($name, $type) = parseparam($p); - my $reg = ""; - if($name eq "err") { - $reg = "e1"; - $ret[1] = $reg; - $do_errno = 1; - } else { - $reg = "r0"; - $ret[0] = $reg; - } - if($type eq "bool") { - $reg = "$reg != 0"; - } - if($reg ne "e1") { - $body .= "\t$name = $type($reg)\n"; - } - } - if ($ret[0] eq "_" && $ret[1] eq "_") { - $textcommon .= "\t$callcommun\n"; - } else { - $textcommon .= "\t$ret[0], $ret[1] := $callcommun\n"; - } - $textcommon .= $body; - - if ($do_errno) { - $textcommon .= "\tif e1 != 0 {\n"; - $textcommon .= "\t\terr = errnoErr(e1)\n"; - $textcommon .= "\t}\n"; - } - $textcommon .= "\treturn\n"; - $textcommon .= "}\n"; - - if ($onlyCommon){ - next - } - # CALL Prototype - my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall); - - # GC function generation - my $asm = "syscall6"; - if ($nonblock) { - $asm = "rawSyscall6"; - } - - if(@argsgc <= 6) { - while(@argsgc < 6) { - push @argsgc, "0"; - } - } else { - print STDERR "$ARGV:$.: too many arguments to system call\n"; - } - my $argsgc = join(', ', @argsgc); - my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)"; - - $textgc .= $callProto; - $textgc .= "\tr1, _, e1 = $callgc\n"; - $textgc .= "\treturn\n}\n"; - - # GCCGO function generation - my $argsgccgo = join(', ', @argsgccgo); - my $callgccgo = "C.$sysname($argsgccgo)"; - $textgccgo .= $callProto; - $textgccgo .= "\tr1 = uintptr($callgccgo)\n"; - $textgccgo .= "\te1 = syscall.GetErrno()\n"; - $textgccgo .= "\treturn\n}\n"; -} - -if($errors) { - exit 1; -} - -# Print zsyscall_aix_ppc64.go -open(my $fcommun, '>', 'zsyscall_aix_ppc64.go'); -my $tofcommun = <', 'zsyscall_aix_ppc64_gc.go'); -my $tofgc = <', 'zsyscall_aix_ppc64_gccgo.go'); -my $tofgccgo = < 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { + r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, nevent int, timeout *Timespec) (n int, err error) { + r0, _, e1 := Syscall6(SYS_KEVENT, uintptr(kq), uintptr(change), uintptr(nchange), uintptr(event), uintptr(nevent), uintptr(unsafe.Pointer(timeout))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimes(path string, timeval *[2]Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func futimes(fd int, timeval *[2]Timeval) (err error) { + _, _, e1 := Syscall(SYS_FUTIMES, uintptr(fd), uintptr(unsafe.Pointer(timeval)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fcntl(fd int, cmd int, arg int) (val int, err error) { + r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Madvise(b []byte, behav int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(behav)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mlockall(flags int) (err error) { + _, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mprotect(b []byte, prot int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Msync(b []byte, flags int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlock(b []byte) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Munlockall() (err error) { + _, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe() (fd1 int, fd2 int, err error) { + r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) + fd1 = int(r0) + fd2 = int(r1) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getdents(fd int, buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_GETDENTS, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ioctl(fd int, req uint, arg uintptr) (err error) { + _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Access(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_ACCESS, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Adjtime(delta *Timeval, olddelta *Timeval) (err error) { + _, _, e1 := Syscall(SYS_ADJTIME, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chflags(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHFLAGS, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chmod(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHMOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(fd int) (nfd int, err error) { + r0, _, e1 := Syscall(SYS_DUP, uintptr(fd), 0, 0) + nfd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup2(from int, to int) (err error) { + _, _, e1 := Syscall(SYS_DUP2, uintptr(from), uintptr(to), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Exit(code int) { + Syscall(SYS_EXIT, uintptr(code), 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrGetFd(fd int, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_GET_FD, uintptr(fd), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p0)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrSetFd(fd int, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_SET_FD, uintptr(fd), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p0)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrDeleteFd(fd int, attrnamespace int, attrname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attrname) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_EXTATTR_DELETE_FD, uintptr(fd), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p0))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrListFd(fd int, attrnamespace int, data uintptr, nbytes int) (ret int, err error) { + r0, _, e1 := Syscall6(SYS_EXTATTR_LIST_FD, uintptr(fd), uintptr(attrnamespace), uintptr(data), uintptr(nbytes), 0, 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrGetFile(file string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(file) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_GET_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrSetFile(file string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(file) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_SET_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrDeleteFile(file string, attrnamespace int, attrname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(file) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_EXTATTR_DELETE_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrListFile(file string, attrnamespace int, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(file) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_LIST_FILE, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(data), uintptr(nbytes), 0, 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrGetLink(link string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_GET_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrSetLink(link string, attrnamespace int, attrname string, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_SET_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1)), uintptr(data), uintptr(nbytes), 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrDeleteLink(link string, attrnamespace int, attrname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attrname) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_EXTATTR_DELETE_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ExtattrListLink(link string, attrnamespace int, data uintptr, nbytes int) (ret int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_EXTATTR_LIST_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(attrnamespace), uintptr(data), uintptr(nbytes), 0, 0) + ret = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fadvise(fd int, offset int64, length int64, advice int) (err error) { + _, _, e1 := Syscall6(SYS_POSIX_FADVISE, uintptr(fd), 0, uintptr(offset), 0, uintptr(length), uintptr(advice)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchdir(fd int) (err error) { + _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchflags(fd int, flags int) (err error) { + _, _, e1 := Syscall(SYS_FCHFLAGS, uintptr(fd), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmod(fd int, mode uint32) (err error) { + _, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + _, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Flock(fd int, how int) (err error) { + _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fpathconf(fd int, name int) (val int, err error) { + r0, _, e1 := Syscall(SYS_FPATHCONF, uintptr(fd), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, stat *Stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FSTATAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsync(fd int) (err error) { + _, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), 0, uintptr(length)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0) + egid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (uid int) { + r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgid(pid int) (pgid int, err error) { + r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0) + pgid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgrp() (pgrp int) { + r0, _, _ := RawSyscall(SYS_GETPGRP, 0, 0, 0) + pgrp = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpid() (pid int) { + r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getppid() (ppid int) { + r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0) + ppid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpriority(which int, who int) (prio int, err error) { + r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) + prio = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrlimit(which int, lim *Rlimit) (err error) { + _, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrusage(who int, rusage *Rusage) (err error) { + _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := RawSyscall(SYS_GETSID, uintptr(pid), 0, 0) + sid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gettimeofday(tv *Timeval) (err error) { + _, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Issetugid() (tainted bool) { + r0, _, _ := Syscall(SYS_ISSETUGID, 0, 0, 0) + tainted = bool(r0 != 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kill(pid int, signum syscall.Signal) (err error) { + _, _, e1 := Syscall(SYS_KILL, uintptr(pid), uintptr(signum), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kqueue() (fd int, err error) { + r0, _, e1 := Syscall(SYS_KQUEUE, 0, 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Link(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_LINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, backlog int) (err error) { + _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lstat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdir(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIR, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifo(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFO, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknod(path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKNOD, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Nanosleep(time *Timespec, leftover *Timespec) (err error) { + _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Open(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0) + fd = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pathconf(path string, name int) (val int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_PATHCONF, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0) + val = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), 0, uintptr(offset), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func read(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_READLINK, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rename(from string, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_RENAME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Revoke(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_REVOKE, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Rmdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_RMDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { + r0, _, e1 := Syscall6(SYS_LSEEK, uintptr(fd), 0, uintptr(offset), uintptr(whence), 0, 0) + newoffset = int64(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error) { + _, _, e1 := Syscall6(SYS_SELECT, uintptr(n), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setegid(egid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETEGID, uintptr(egid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETEUID, uintptr(euid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setgid(gid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETGID, uintptr(gid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpgid(pid int, pgid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setpriority(which int, who int, prio int) (err error) { + _, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setregid(rgid int, egid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setreuid(ruid int, euid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setrlimit(which int, lim *Rlimit) (err error) { + _, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(which), uintptr(unsafe.Pointer(lim)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setsid() (pid int, err error) { + r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0) + pid = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Settimeofday(tp *Timeval) (err error) { + _, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Setuid(uid int) (err error) { + _, _, e1 := RawSyscall(SYS_SETUID, uintptr(uid), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Stat(path string, stat *Stat_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlink(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINK, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Sync() (err error) { + _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Truncate(path string, length int64) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), 0, uintptr(length)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Umask(newmask int) (oldmask int) { + r0, _, _ := Syscall(SYS_UMASK, uintptr(newmask), 0, 0) + oldmask = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlink(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINK, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unmount(path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func write(fd int, p []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { + r0, _, e1 := Syscall9(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), 0, 0) + ret = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func munmap(addr uintptr, length uintptr) (err error) { + _, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func readlen(fd int, buf *byte, nbuf int) (n int, err error) { + r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func writelen(fd int, buf *byte, nbuf int) (n int, err error) { + r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go index ff3976e..464c9a9 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master +// go run mksysnum.go https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build amd64,dragonfly diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go index b1e81b7..55c3a32 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master +// go run mksysnum.go https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build 386,freebsd diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go index 73e277f..b39be6c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master +// go run mksysnum.go https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build amd64,freebsd diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go index e12b469..44ffd4c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master +// go run mksysnum.go https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build arm,freebsd diff --git a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go index 8c1e16c..9f21e95 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go @@ -1,4 +1,4 @@ -// mksysnum_freebsd.pl +// go run mksysnum.go https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build arm64,freebsd diff --git a/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go new file mode 100644 index 0000000..0291c09 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go @@ -0,0 +1,274 @@ +// go run mksysnum.go http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master +// Code generated by the command above; DO NOT EDIT. + +// +build arm64,netbsd + +package unix + +const ( + SYS_EXIT = 1 // { void|sys||exit(int rval); } + SYS_FORK = 2 // { int|sys||fork(void); } + SYS_READ = 3 // { ssize_t|sys||read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t|sys||write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int|sys||open(const char *path, int flags, ... mode_t mode); } + SYS_CLOSE = 6 // { int|sys||close(int fd); } + SYS_LINK = 9 // { int|sys||link(const char *path, const char *link); } + SYS_UNLINK = 10 // { int|sys||unlink(const char *path); } + SYS_CHDIR = 12 // { int|sys||chdir(const char *path); } + SYS_FCHDIR = 13 // { int|sys||fchdir(int fd); } + SYS_CHMOD = 15 // { int|sys||chmod(const char *path, mode_t mode); } + SYS_CHOWN = 16 // { int|sys||chown(const char *path, uid_t uid, gid_t gid); } + SYS_BREAK = 17 // { int|sys||obreak(char *nsize); } + SYS_GETPID = 20 // { pid_t|sys||getpid_with_ppid(void); } + SYS_UNMOUNT = 22 // { int|sys||unmount(const char *path, int flags); } + SYS_SETUID = 23 // { int|sys||setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t|sys||getuid_with_euid(void); } + SYS_GETEUID = 25 // { uid_t|sys||geteuid(void); } + SYS_PTRACE = 26 // { int|sys||ptrace(int req, pid_t pid, void *addr, int data); } + SYS_RECVMSG = 27 // { ssize_t|sys||recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { ssize_t|sys||sendmsg(int s, const struct msghdr *msg, int flags); } + SYS_RECVFROM = 29 // { ssize_t|sys||recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlenaddr); } + SYS_ACCEPT = 30 // { int|sys||accept(int s, struct sockaddr *name, socklen_t *anamelen); } + SYS_GETPEERNAME = 31 // { int|sys||getpeername(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_GETSOCKNAME = 32 // { int|sys||getsockname(int fdes, struct sockaddr *asa, socklen_t *alen); } + SYS_ACCESS = 33 // { int|sys||access(const char *path, int flags); } + SYS_CHFLAGS = 34 // { int|sys||chflags(const char *path, u_long flags); } + SYS_FCHFLAGS = 35 // { int|sys||fchflags(int fd, u_long flags); } + SYS_SYNC = 36 // { void|sys||sync(void); } + SYS_KILL = 37 // { int|sys||kill(pid_t pid, int signum); } + SYS_GETPPID = 39 // { pid_t|sys||getppid(void); } + SYS_DUP = 41 // { int|sys||dup(int fd); } + SYS_PIPE = 42 // { int|sys||pipe(void); } + SYS_GETEGID = 43 // { gid_t|sys||getegid(void); } + SYS_PROFIL = 44 // { int|sys||profil(char *samples, size_t size, u_long offset, u_int scale); } + SYS_KTRACE = 45 // { int|sys||ktrace(const char *fname, int ops, int facs, pid_t pid); } + SYS_GETGID = 47 // { gid_t|sys||getgid_with_egid(void); } + SYS___GETLOGIN = 49 // { int|sys||__getlogin(char *namebuf, size_t namelen); } + SYS___SETLOGIN = 50 // { int|sys||__setlogin(const char *namebuf); } + SYS_ACCT = 51 // { int|sys||acct(const char *path); } + SYS_IOCTL = 54 // { int|sys||ioctl(int fd, u_long com, ... void *data); } + SYS_REVOKE = 56 // { int|sys||revoke(const char *path); } + SYS_SYMLINK = 57 // { int|sys||symlink(const char *path, const char *link); } + SYS_READLINK = 58 // { ssize_t|sys||readlink(const char *path, char *buf, size_t count); } + SYS_EXECVE = 59 // { int|sys||execve(const char *path, char * const *argp, char * const *envp); } + SYS_UMASK = 60 // { mode_t|sys||umask(mode_t newmask); } + SYS_CHROOT = 61 // { int|sys||chroot(const char *path); } + SYS_VFORK = 66 // { int|sys||vfork(void); } + SYS_SBRK = 69 // { int|sys||sbrk(intptr_t incr); } + SYS_SSTK = 70 // { int|sys||sstk(int incr); } + SYS_VADVISE = 72 // { int|sys||ovadvise(int anom); } + SYS_MUNMAP = 73 // { int|sys||munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int|sys||mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int|sys||madvise(void *addr, size_t len, int behav); } + SYS_MINCORE = 78 // { int|sys||mincore(void *addr, size_t len, char *vec); } + SYS_GETGROUPS = 79 // { int|sys||getgroups(int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int|sys||setgroups(int gidsetsize, const gid_t *gidset); } + SYS_GETPGRP = 81 // { int|sys||getpgrp(void); } + SYS_SETPGID = 82 // { int|sys||setpgid(pid_t pid, pid_t pgid); } + SYS_DUP2 = 90 // { int|sys||dup2(int from, int to); } + SYS_FCNTL = 92 // { int|sys||fcntl(int fd, int cmd, ... void *arg); } + SYS_FSYNC = 95 // { int|sys||fsync(int fd); } + SYS_SETPRIORITY = 96 // { int|sys||setpriority(int which, id_t who, int prio); } + SYS_CONNECT = 98 // { int|sys||connect(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_GETPRIORITY = 100 // { int|sys||getpriority(int which, id_t who); } + SYS_BIND = 104 // { int|sys||bind(int s, const struct sockaddr *name, socklen_t namelen); } + SYS_SETSOCKOPT = 105 // { int|sys||setsockopt(int s, int level, int name, const void *val, socklen_t valsize); } + SYS_LISTEN = 106 // { int|sys||listen(int s, int backlog); } + SYS_GETSOCKOPT = 118 // { int|sys||getsockopt(int s, int level, int name, void *val, socklen_t *avalsize); } + SYS_READV = 120 // { ssize_t|sys||readv(int fd, const struct iovec *iovp, int iovcnt); } + SYS_WRITEV = 121 // { ssize_t|sys||writev(int fd, const struct iovec *iovp, int iovcnt); } + SYS_FCHOWN = 123 // { int|sys||fchown(int fd, uid_t uid, gid_t gid); } + SYS_FCHMOD = 124 // { int|sys||fchmod(int fd, mode_t mode); } + SYS_SETREUID = 126 // { int|sys||setreuid(uid_t ruid, uid_t euid); } + SYS_SETREGID = 127 // { int|sys||setregid(gid_t rgid, gid_t egid); } + SYS_RENAME = 128 // { int|sys||rename(const char *from, const char *to); } + SYS_FLOCK = 131 // { int|sys||flock(int fd, int how); } + SYS_MKFIFO = 132 // { int|sys||mkfifo(const char *path, mode_t mode); } + SYS_SENDTO = 133 // { ssize_t|sys||sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); } + SYS_SHUTDOWN = 134 // { int|sys||shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int|sys||socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int|sys||mkdir(const char *path, mode_t mode); } + SYS_RMDIR = 137 // { int|sys||rmdir(const char *path); } + SYS_SETSID = 147 // { int|sys||setsid(void); } + SYS_SYSARCH = 165 // { int|sys||sysarch(int op, void *parms); } + SYS_PREAD = 173 // { ssize_t|sys||pread(int fd, void *buf, size_t nbyte, int PAD, off_t offset); } + SYS_PWRITE = 174 // { ssize_t|sys||pwrite(int fd, const void *buf, size_t nbyte, int PAD, off_t offset); } + SYS_NTP_ADJTIME = 176 // { int|sys||ntp_adjtime(struct timex *tp); } + SYS_SETGID = 181 // { int|sys||setgid(gid_t gid); } + SYS_SETEGID = 182 // { int|sys||setegid(gid_t egid); } + SYS_SETEUID = 183 // { int|sys||seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { long|sys||pathconf(const char *path, int name); } + SYS_FPATHCONF = 192 // { long|sys||fpathconf(int fd, int name); } + SYS_GETRLIMIT = 194 // { int|sys||getrlimit(int which, struct rlimit *rlp); } + SYS_SETRLIMIT = 195 // { int|sys||setrlimit(int which, const struct rlimit *rlp); } + SYS_MMAP = 197 // { void *|sys||mmap(void *addr, size_t len, int prot, int flags, int fd, long PAD, off_t pos); } + SYS_LSEEK = 199 // { off_t|sys||lseek(int fd, int PAD, off_t offset, int whence); } + SYS_TRUNCATE = 200 // { int|sys||truncate(const char *path, int PAD, off_t length); } + SYS_FTRUNCATE = 201 // { int|sys||ftruncate(int fd, int PAD, off_t length); } + SYS___SYSCTL = 202 // { int|sys||__sysctl(const int *name, u_int namelen, void *old, size_t *oldlenp, const void *new, size_t newlen); } + SYS_MLOCK = 203 // { int|sys||mlock(const void *addr, size_t len); } + SYS_MUNLOCK = 204 // { int|sys||munlock(const void *addr, size_t len); } + SYS_UNDELETE = 205 // { int|sys||undelete(const char *path); } + SYS_GETPGID = 207 // { pid_t|sys||getpgid(pid_t pid); } + SYS_REBOOT = 208 // { int|sys||reboot(int opt, char *bootstr); } + SYS_POLL = 209 // { int|sys||poll(struct pollfd *fds, u_int nfds, int timeout); } + SYS_SEMGET = 221 // { int|sys||semget(key_t key, int nsems, int semflg); } + SYS_SEMOP = 222 // { int|sys||semop(int semid, struct sembuf *sops, size_t nsops); } + SYS_SEMCONFIG = 223 // { int|sys||semconfig(int flag); } + SYS_MSGGET = 225 // { int|sys||msgget(key_t key, int msgflg); } + SYS_MSGSND = 226 // { int|sys||msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); } + SYS_MSGRCV = 227 // { ssize_t|sys||msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); } + SYS_SHMAT = 228 // { void *|sys||shmat(int shmid, const void *shmaddr, int shmflg); } + SYS_SHMDT = 230 // { int|sys||shmdt(const void *shmaddr); } + SYS_SHMGET = 231 // { int|sys||shmget(key_t key, size_t size, int shmflg); } + SYS_TIMER_CREATE = 235 // { int|sys||timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid); } + SYS_TIMER_DELETE = 236 // { int|sys||timer_delete(timer_t timerid); } + SYS_TIMER_GETOVERRUN = 239 // { int|sys||timer_getoverrun(timer_t timerid); } + SYS_FDATASYNC = 241 // { int|sys||fdatasync(int fd); } + SYS_MLOCKALL = 242 // { int|sys||mlockall(int flags); } + SYS_MUNLOCKALL = 243 // { int|sys||munlockall(void); } + SYS_SIGQUEUEINFO = 245 // { int|sys||sigqueueinfo(pid_t pid, const siginfo_t *info); } + SYS_MODCTL = 246 // { int|sys||modctl(int cmd, void *arg); } + SYS___POSIX_RENAME = 270 // { int|sys||__posix_rename(const char *from, const char *to); } + SYS_SWAPCTL = 271 // { int|sys||swapctl(int cmd, void *arg, int misc); } + SYS_MINHERIT = 273 // { int|sys||minherit(void *addr, size_t len, int inherit); } + SYS_LCHMOD = 274 // { int|sys||lchmod(const char *path, mode_t mode); } + SYS_LCHOWN = 275 // { int|sys||lchown(const char *path, uid_t uid, gid_t gid); } + SYS_MSYNC = 277 // { int|sys|13|msync(void *addr, size_t len, int flags); } + SYS___POSIX_CHOWN = 283 // { int|sys||__posix_chown(const char *path, uid_t uid, gid_t gid); } + SYS___POSIX_FCHOWN = 284 // { int|sys||__posix_fchown(int fd, uid_t uid, gid_t gid); } + SYS___POSIX_LCHOWN = 285 // { int|sys||__posix_lchown(const char *path, uid_t uid, gid_t gid); } + SYS_GETSID = 286 // { pid_t|sys||getsid(pid_t pid); } + SYS___CLONE = 287 // { pid_t|sys||__clone(int flags, void *stack); } + SYS_FKTRACE = 288 // { int|sys||fktrace(int fd, int ops, int facs, pid_t pid); } + SYS_PREADV = 289 // { ssize_t|sys||preadv(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); } + SYS_PWRITEV = 290 // { ssize_t|sys||pwritev(int fd, const struct iovec *iovp, int iovcnt, int PAD, off_t offset); } + SYS___GETCWD = 296 // { int|sys||__getcwd(char *bufp, size_t length); } + SYS_FCHROOT = 297 // { int|sys||fchroot(int fd); } + SYS_LCHFLAGS = 304 // { int|sys||lchflags(const char *path, u_long flags); } + SYS_ISSETUGID = 305 // { int|sys||issetugid(void); } + SYS_UTRACE = 306 // { int|sys||utrace(const char *label, void *addr, size_t len); } + SYS_GETCONTEXT = 307 // { int|sys||getcontext(struct __ucontext *ucp); } + SYS_SETCONTEXT = 308 // { int|sys||setcontext(const struct __ucontext *ucp); } + SYS__LWP_CREATE = 309 // { int|sys||_lwp_create(const struct __ucontext *ucp, u_long flags, lwpid_t *new_lwp); } + SYS__LWP_EXIT = 310 // { int|sys||_lwp_exit(void); } + SYS__LWP_SELF = 311 // { lwpid_t|sys||_lwp_self(void); } + SYS__LWP_WAIT = 312 // { int|sys||_lwp_wait(lwpid_t wait_for, lwpid_t *departed); } + SYS__LWP_SUSPEND = 313 // { int|sys||_lwp_suspend(lwpid_t target); } + SYS__LWP_CONTINUE = 314 // { int|sys||_lwp_continue(lwpid_t target); } + SYS__LWP_WAKEUP = 315 // { int|sys||_lwp_wakeup(lwpid_t target); } + SYS__LWP_GETPRIVATE = 316 // { void *|sys||_lwp_getprivate(void); } + SYS__LWP_SETPRIVATE = 317 // { void|sys||_lwp_setprivate(void *ptr); } + SYS__LWP_KILL = 318 // { int|sys||_lwp_kill(lwpid_t target, int signo); } + SYS__LWP_DETACH = 319 // { int|sys||_lwp_detach(lwpid_t target); } + SYS__LWP_UNPARK = 321 // { int|sys||_lwp_unpark(lwpid_t target, const void *hint); } + SYS__LWP_UNPARK_ALL = 322 // { ssize_t|sys||_lwp_unpark_all(const lwpid_t *targets, size_t ntargets, const void *hint); } + SYS__LWP_SETNAME = 323 // { int|sys||_lwp_setname(lwpid_t target, const char *name); } + SYS__LWP_GETNAME = 324 // { int|sys||_lwp_getname(lwpid_t target, char *name, size_t len); } + SYS__LWP_CTL = 325 // { int|sys||_lwp_ctl(int features, struct lwpctl **address); } + SYS___SIGACTION_SIGTRAMP = 340 // { int|sys||__sigaction_sigtramp(int signum, const struct sigaction *nsa, struct sigaction *osa, const void *tramp, int vers); } + SYS_PMC_GET_INFO = 341 // { int|sys||pmc_get_info(int ctr, int op, void *args); } + SYS_PMC_CONTROL = 342 // { int|sys||pmc_control(int ctr, int op, void *args); } + SYS_RASCTL = 343 // { int|sys||rasctl(void *addr, size_t len, int op); } + SYS_KQUEUE = 344 // { int|sys||kqueue(void); } + SYS__SCHED_SETPARAM = 346 // { int|sys||_sched_setparam(pid_t pid, lwpid_t lid, int policy, const struct sched_param *params); } + SYS__SCHED_GETPARAM = 347 // { int|sys||_sched_getparam(pid_t pid, lwpid_t lid, int *policy, struct sched_param *params); } + SYS__SCHED_SETAFFINITY = 348 // { int|sys||_sched_setaffinity(pid_t pid, lwpid_t lid, size_t size, const cpuset_t *cpuset); } + SYS__SCHED_GETAFFINITY = 349 // { int|sys||_sched_getaffinity(pid_t pid, lwpid_t lid, size_t size, cpuset_t *cpuset); } + SYS_SCHED_YIELD = 350 // { int|sys||sched_yield(void); } + SYS_FSYNC_RANGE = 354 // { int|sys||fsync_range(int fd, int flags, off_t start, off_t length); } + SYS_UUIDGEN = 355 // { int|sys||uuidgen(struct uuid *store, int count); } + SYS_GETVFSSTAT = 356 // { int|sys||getvfsstat(struct statvfs *buf, size_t bufsize, int flags); } + SYS_STATVFS1 = 357 // { int|sys||statvfs1(const char *path, struct statvfs *buf, int flags); } + SYS_FSTATVFS1 = 358 // { int|sys||fstatvfs1(int fd, struct statvfs *buf, int flags); } + SYS_EXTATTRCTL = 360 // { int|sys||extattrctl(const char *path, int cmd, const char *filename, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_FILE = 361 // { int|sys||extattr_set_file(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); } + SYS_EXTATTR_GET_FILE = 362 // { ssize_t|sys||extattr_get_file(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_FILE = 363 // { int|sys||extattr_delete_file(const char *path, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_FD = 364 // { int|sys||extattr_set_fd(int fd, int attrnamespace, const char *attrname, const void *data, size_t nbytes); } + SYS_EXTATTR_GET_FD = 365 // { ssize_t|sys||extattr_get_fd(int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_FD = 366 // { int|sys||extattr_delete_fd(int fd, int attrnamespace, const char *attrname); } + SYS_EXTATTR_SET_LINK = 367 // { int|sys||extattr_set_link(const char *path, int attrnamespace, const char *attrname, const void *data, size_t nbytes); } + SYS_EXTATTR_GET_LINK = 368 // { ssize_t|sys||extattr_get_link(const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes); } + SYS_EXTATTR_DELETE_LINK = 369 // { int|sys||extattr_delete_link(const char *path, int attrnamespace, const char *attrname); } + SYS_EXTATTR_LIST_FD = 370 // { ssize_t|sys||extattr_list_fd(int fd, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_FILE = 371 // { ssize_t|sys||extattr_list_file(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_EXTATTR_LIST_LINK = 372 // { ssize_t|sys||extattr_list_link(const char *path, int attrnamespace, void *data, size_t nbytes); } + SYS_SETXATTR = 375 // { int|sys||setxattr(const char *path, const char *name, const void *value, size_t size, int flags); } + SYS_LSETXATTR = 376 // { int|sys||lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags); } + SYS_FSETXATTR = 377 // { int|sys||fsetxattr(int fd, const char *name, const void *value, size_t size, int flags); } + SYS_GETXATTR = 378 // { int|sys||getxattr(const char *path, const char *name, void *value, size_t size); } + SYS_LGETXATTR = 379 // { int|sys||lgetxattr(const char *path, const char *name, void *value, size_t size); } + SYS_FGETXATTR = 380 // { int|sys||fgetxattr(int fd, const char *name, void *value, size_t size); } + SYS_LISTXATTR = 381 // { int|sys||listxattr(const char *path, char *list, size_t size); } + SYS_LLISTXATTR = 382 // { int|sys||llistxattr(const char *path, char *list, size_t size); } + SYS_FLISTXATTR = 383 // { int|sys||flistxattr(int fd, char *list, size_t size); } + SYS_REMOVEXATTR = 384 // { int|sys||removexattr(const char *path, const char *name); } + SYS_LREMOVEXATTR = 385 // { int|sys||lremovexattr(const char *path, const char *name); } + SYS_FREMOVEXATTR = 386 // { int|sys||fremovexattr(int fd, const char *name); } + SYS_GETDENTS = 390 // { int|sys|30|getdents(int fd, char *buf, size_t count); } + SYS_SOCKET = 394 // { int|sys|30|socket(int domain, int type, int protocol); } + SYS_GETFH = 395 // { int|sys|30|getfh(const char *fname, void *fhp, size_t *fh_size); } + SYS_MOUNT = 410 // { int|sys|50|mount(const char *type, const char *path, int flags, void *data, size_t data_len); } + SYS_MREMAP = 411 // { void *|sys||mremap(void *old_address, size_t old_size, void *new_address, size_t new_size, int flags); } + SYS_PSET_CREATE = 412 // { int|sys||pset_create(psetid_t *psid); } + SYS_PSET_DESTROY = 413 // { int|sys||pset_destroy(psetid_t psid); } + SYS_PSET_ASSIGN = 414 // { int|sys||pset_assign(psetid_t psid, cpuid_t cpuid, psetid_t *opsid); } + SYS__PSET_BIND = 415 // { int|sys||_pset_bind(idtype_t idtype, id_t first_id, id_t second_id, psetid_t psid, psetid_t *opsid); } + SYS_POSIX_FADVISE = 416 // { int|sys|50|posix_fadvise(int fd, int PAD, off_t offset, off_t len, int advice); } + SYS_SELECT = 417 // { int|sys|50|select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_GETTIMEOFDAY = 418 // { int|sys|50|gettimeofday(struct timeval *tp, void *tzp); } + SYS_SETTIMEOFDAY = 419 // { int|sys|50|settimeofday(const struct timeval *tv, const void *tzp); } + SYS_UTIMES = 420 // { int|sys|50|utimes(const char *path, const struct timeval *tptr); } + SYS_ADJTIME = 421 // { int|sys|50|adjtime(const struct timeval *delta, struct timeval *olddelta); } + SYS_FUTIMES = 423 // { int|sys|50|futimes(int fd, const struct timeval *tptr); } + SYS_LUTIMES = 424 // { int|sys|50|lutimes(const char *path, const struct timeval *tptr); } + SYS_SETITIMER = 425 // { int|sys|50|setitimer(int which, const struct itimerval *itv, struct itimerval *oitv); } + SYS_GETITIMER = 426 // { int|sys|50|getitimer(int which, struct itimerval *itv); } + SYS_CLOCK_GETTIME = 427 // { int|sys|50|clock_gettime(clockid_t clock_id, struct timespec *tp); } + SYS_CLOCK_SETTIME = 428 // { int|sys|50|clock_settime(clockid_t clock_id, const struct timespec *tp); } + SYS_CLOCK_GETRES = 429 // { int|sys|50|clock_getres(clockid_t clock_id, struct timespec *tp); } + SYS_NANOSLEEP = 430 // { int|sys|50|nanosleep(const struct timespec *rqtp, struct timespec *rmtp); } + SYS___SIGTIMEDWAIT = 431 // { int|sys|50|__sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec *timeout); } + SYS__LWP_PARK = 434 // { int|sys|50|_lwp_park(const struct timespec *ts, lwpid_t unpark, const void *hint, const void *unparkhint); } + SYS_KEVENT = 435 // { int|sys|50|kevent(int fd, const struct kevent *changelist, size_t nchanges, struct kevent *eventlist, size_t nevents, const struct timespec *timeout); } + SYS_PSELECT = 436 // { int|sys|50|pselect(int nd, fd_set *in, fd_set *ou, fd_set *ex, const struct timespec *ts, const sigset_t *mask); } + SYS_POLLTS = 437 // { int|sys|50|pollts(struct pollfd *fds, u_int nfds, const struct timespec *ts, const sigset_t *mask); } + SYS_STAT = 439 // { int|sys|50|stat(const char *path, struct stat *ub); } + SYS_FSTAT = 440 // { int|sys|50|fstat(int fd, struct stat *sb); } + SYS_LSTAT = 441 // { int|sys|50|lstat(const char *path, struct stat *ub); } + SYS___SEMCTL = 442 // { int|sys|50|__semctl(int semid, int semnum, int cmd, ... union __semun *arg); } + SYS_SHMCTL = 443 // { int|sys|50|shmctl(int shmid, int cmd, struct shmid_ds *buf); } + SYS_MSGCTL = 444 // { int|sys|50|msgctl(int msqid, int cmd, struct msqid_ds *buf); } + SYS_GETRUSAGE = 445 // { int|sys|50|getrusage(int who, struct rusage *rusage); } + SYS_TIMER_SETTIME = 446 // { int|sys|50|timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); } + SYS_TIMER_GETTIME = 447 // { int|sys|50|timer_gettime(timer_t timerid, struct itimerspec *value); } + SYS_NTP_GETTIME = 448 // { int|sys|50|ntp_gettime(struct ntptimeval *ntvp); } + SYS_WAIT4 = 449 // { int|sys|50|wait4(pid_t pid, int *status, int options, struct rusage *rusage); } + SYS_MKNOD = 450 // { int|sys|50|mknod(const char *path, mode_t mode, dev_t dev); } + SYS_FHSTAT = 451 // { int|sys|50|fhstat(const void *fhp, size_t fh_size, struct stat *sb); } + SYS_PIPE2 = 453 // { int|sys||pipe2(int *fildes, int flags); } + SYS_DUP3 = 454 // { int|sys||dup3(int from, int to, int flags); } + SYS_KQUEUE1 = 455 // { int|sys||kqueue1(int flags); } + SYS_PACCEPT = 456 // { int|sys||paccept(int s, struct sockaddr *name, socklen_t *anamelen, const sigset_t *mask, int flags); } + SYS_LINKAT = 457 // { int|sys||linkat(int fd1, const char *name1, int fd2, const char *name2, int flags); } + SYS_RENAMEAT = 458 // { int|sys||renameat(int fromfd, const char *from, int tofd, const char *to); } + SYS_MKFIFOAT = 459 // { int|sys||mkfifoat(int fd, const char *path, mode_t mode); } + SYS_MKNODAT = 460 // { int|sys||mknodat(int fd, const char *path, mode_t mode, uint32_t dev); } + SYS_MKDIRAT = 461 // { int|sys||mkdirat(int fd, const char *path, mode_t mode); } + SYS_FACCESSAT = 462 // { int|sys||faccessat(int fd, const char *path, int amode, int flag); } + SYS_FCHMODAT = 463 // { int|sys||fchmodat(int fd, const char *path, mode_t mode, int flag); } + SYS_FCHOWNAT = 464 // { int|sys||fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag); } + SYS_FEXECVE = 465 // { int|sys||fexecve(int fd, char * const *argp, char * const *envp); } + SYS_FSTATAT = 466 // { int|sys||fstatat(int fd, const char *path, struct stat *buf, int flag); } + SYS_UTIMENSAT = 467 // { int|sys||utimensat(int fd, const char *path, const struct timespec *tptr, int flag); } + SYS_OPENAT = 468 // { int|sys||openat(int fd, const char *path, int oflags, ... mode_t mode); } + SYS_READLINKAT = 469 // { int|sys||readlinkat(int fd, const char *path, char *buf, size_t bufsize); } + SYS_SYMLINKAT = 470 // { int|sys||symlinkat(const char *path1, int fd, const char *path2); } + SYS_UNLINKAT = 471 // { int|sys||unlinkat(int fd, const char *path, int flag); } + SYS_FUTIMENS = 472 // { int|sys||futimens(int fd, const struct timespec *tptr); } + SYS___QUOTACTL = 473 // { int|sys||__quotactl(const char *path, struct quotactl_args *args); } + SYS_POSIX_SPAWN = 474 // { int|sys||posix_spawn(pid_t *pid, const char *path, const struct posix_spawn_file_actions *file_actions, const struct posix_spawnattr *attrp, char *const *argv, char *const *envp); } + SYS_RECVMMSG = 475 // { int|sys||recvmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout); } + SYS_SENDMMSG = 476 // { int|sys||sendmmsg(int s, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags); } +) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go index d5bf3c4..b0207d1 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master +// go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build 386,openbsd diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go index cbcfdfb..f0dec6f 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master +// go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build amd64,openbsd diff --git a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go index a84cead..33d1dc5 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go @@ -1,4 +1,4 @@ -// go run mksysnum.go http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master +// go run mksysnum.go https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master // Code generated by the command above; see README.md. DO NOT EDIT. // +build arm,openbsd diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index ebf10d4..aab0051 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -759,7 +759,25 @@ type Sigset_t struct { Val [32]uint32 } -const RNDGETENTCNT = 0x80045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1964,6 +1982,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1983,4 +2005,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 99a6900..f1bc69d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -772,7 +772,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x80045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1977,6 +1995,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1996,4 +2018,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 5ccc4b5..a716dcb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -748,7 +748,25 @@ type Sigset_t struct { Val [32]uint32 } -const RNDGETENTCNT = 0x80045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1955,6 +1973,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1974,4 +1996,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index be375d9..32af3d2 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -751,7 +751,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x80045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1956,6 +1974,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1975,4 +1997,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 195f7e1..73de572 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -753,7 +753,25 @@ type Sigset_t struct { Val [32]uint32 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1961,6 +1979,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1980,4 +2002,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 77acf56..03842b0 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -753,7 +753,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1958,6 +1976,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1977,4 +1999,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 2fb7498..33a28ec 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -753,7 +753,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1958,6 +1976,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1977,4 +1999,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 41cb148..7e07a31 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -753,7 +753,25 @@ type Sigset_t struct { Val [32]uint32 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1961,6 +1979,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1980,4 +2002,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 8e6b5fa..f2218cb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -761,7 +761,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1966,6 +1984,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1985,4 +2007,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 019d2d6..c16f849 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -761,7 +761,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1966,6 +1984,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1985,4 +2007,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index cf110ce..18d9a0e 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -212,7 +212,7 @@ type RawSockaddrInet6 struct { type RawSockaddrUnix struct { Family uint16 - Path [108]uint8 + Path [108]int8 } type RawSockaddrLinklayer struct { @@ -778,7 +778,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x80045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1983,6 +2001,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -2002,4 +2024,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index abdc086..47187b5 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -774,7 +774,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x80045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1980,6 +1998,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1999,4 +2021,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index b0c9798..859ef97 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -756,7 +756,25 @@ type Sigset_t struct { Val [16]uint64 } -const RNDGETENTCNT = 0x40045200 +type SignalfdSiginfo struct { + Signo uint32 + Errno int32 + Code int32 + Pid uint32 + Uid uint32 + Fd int32 + Tid uint32 + Band uint32 + Overrun uint32 + Trapno uint32 + Status int32 + Int int32 + Ptr uint64 + Utime uint64 + Stime uint64 + Addr uint64 + _ [48]uint8 +} const PERF_IOC_FLAG_GROUP = 0x1 @@ -1961,6 +1979,10 @@ const ( NCSI_CHANNEL_ATTR_VLAN_ID = 0xa ) +type ScmTimestamping struct { + Ts [3]Timespec +} + const ( SOF_TIMESTAMPING_TX_HARDWARE = 0x1 SOF_TIMESTAMPING_TX_SOFTWARE = 0x2 @@ -1980,4 +2002,18 @@ const ( SOF_TIMESTAMPING_LAST = 0x4000 SOF_TIMESTAMPING_MASK = 0x7fff + + SCM_TSTAMP_SND = 0x0 + SCM_TSTAMP_SCHED = 0x1 + SCM_TSTAMP_ACK = 0x2 ) + +type SockExtendedErr struct { + Errno uint32 + Origin uint8 + Type uint8 + Code uint8 + Pad uint8 + Info uint32 + Data uint32 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go new file mode 100644 index 0000000..43da2c4 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go @@ -0,0 +1,472 @@ +// cgo -godefs types_netbsd.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build arm64,netbsd + +package unix + +const ( + SizeofPtr = 0x8 + SizeofShort = 0x2 + SizeofInt = 0x4 + SizeofLong = 0x8 + SizeofLongLong = 0x8 +) + +type ( + _C_short int16 + _C_int int32 + _C_long int64 + _C_long_long int64 +) + +type Timespec struct { + Sec int64 + Nsec int64 +} + +type Timeval struct { + Sec int64 + Usec int32 + Pad_cgo_0 [4]byte +} + +type Rusage struct { + Utime Timeval + Stime Timeval + Maxrss int64 + Ixrss int64 + Idrss int64 + Isrss int64 + Minflt int64 + Majflt int64 + Nswap int64 + Inblock int64 + Oublock int64 + Msgsnd int64 + Msgrcv int64 + Nsignals int64 + Nvcsw int64 + Nivcsw int64 +} + +type Rlimit struct { + Cur uint64 + Max uint64 +} + +type _Gid_t uint32 + +type Stat_t struct { + Dev uint64 + Mode uint32 + Pad_cgo_0 [4]byte + Ino uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Pad_cgo_1 [4]byte + Rdev uint64 + Atimespec Timespec + Mtimespec Timespec + Ctimespec Timespec + Birthtimespec Timespec + Size int64 + Blocks int64 + Blksize uint32 + Flags uint32 + Gen uint32 + Spare [2]uint32 + Pad_cgo_2 [4]byte +} + +type Statfs_t [0]byte + +type Flock_t struct { + Start int64 + Len int64 + Pid int32 + Type int16 + Whence int16 +} + +type Dirent struct { + Fileno uint64 + Reclen uint16 + Namlen uint16 + Type uint8 + Name [512]int8 + Pad_cgo_0 [3]byte +} + +type Fsid struct { + X__fsid_val [2]int32 +} + +const ( + PathMax = 0x400 +) + +const ( + FADV_NORMAL = 0x0 + FADV_RANDOM = 0x1 + FADV_SEQUENTIAL = 0x2 + FADV_WILLNEED = 0x3 + FADV_DONTNEED = 0x4 + FADV_NOREUSE = 0x5 +) + +type RawSockaddrInet4 struct { + Len uint8 + Family uint8 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]int8 +} + +type RawSockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type RawSockaddrUnix struct { + Len uint8 + Family uint8 + Path [104]int8 +} + +type RawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [12]int8 +} + +type RawSockaddr struct { + Len uint8 + Family uint8 + Data [14]int8 +} + +type RawSockaddrAny struct { + Addr RawSockaddr + Pad [92]int8 +} + +type _Socklen uint32 + +type Linger struct { + Onoff int32 + Linger int32 +} + +type Iovec struct { + Base *byte + Len uint64 +} + +type IPMreq struct { + Multiaddr [4]byte /* in_addr */ + Interface [4]byte /* in_addr */ +} + +type IPv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type Msghdr struct { + Name *byte + Namelen uint32 + Pad_cgo_0 [4]byte + Iov *Iovec + Iovlen int32 + Pad_cgo_1 [4]byte + Control *byte + Controllen uint32 + Flags int32 +} + +type Cmsghdr struct { + Len uint32 + Level int32 + Type int32 +} + +type Inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type IPv6MTUInfo struct { + Addr RawSockaddrInet6 + Mtu uint32 +} + +type ICMPv6Filter struct { + Filt [8]uint32 +} + +const ( + SizeofSockaddrInet4 = 0x10 + SizeofSockaddrInet6 = 0x1c + SizeofSockaddrAny = 0x6c + SizeofSockaddrUnix = 0x6a + SizeofSockaddrDatalink = 0x14 + SizeofLinger = 0x8 + SizeofIPMreq = 0x8 + SizeofIPv6Mreq = 0x14 + SizeofMsghdr = 0x30 + SizeofCmsghdr = 0xc + SizeofInet6Pktinfo = 0x14 + SizeofIPv6MTUInfo = 0x20 + SizeofICMPv6Filter = 0x20 +) + +const ( + PTRACE_TRACEME = 0x0 + PTRACE_CONT = 0x7 + PTRACE_KILL = 0x8 +) + +type Kevent_t struct { + Ident uint64 + Filter uint32 + Flags uint32 + Fflags uint32 + Pad_cgo_0 [4]byte + Data int64 + Udata int64 +} + +type FdSet struct { + Bits [8]uint32 +} + +const ( + SizeofIfMsghdr = 0x98 + SizeofIfData = 0x88 + SizeofIfaMsghdr = 0x18 + SizeofIfAnnounceMsghdr = 0x18 + SizeofRtMsghdr = 0x78 + SizeofRtMetrics = 0x50 +) + +type IfMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + Pad_cgo_0 [2]byte + Data IfData +} + +type IfData struct { + Type uint8 + Addrlen uint8 + Hdrlen uint8 + Pad_cgo_0 [1]byte + Link_state int32 + Mtu uint64 + Metric uint64 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Noproto uint64 + Lastchange Timespec +} + +type IfaMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Metric int32 + Index uint16 + Pad_cgo_0 [6]byte +} + +type IfAnnounceMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Name [16]int8 + What uint16 +} + +type RtMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Pad_cgo_0 [2]byte + Flags int32 + Addrs int32 + Pid int32 + Seq int32 + Errno int32 + Use int32 + Inits int32 + Pad_cgo_1 [4]byte + Rmx RtMetrics +} + +type RtMetrics struct { + Locks uint64 + Mtu uint64 + Hopcount uint64 + Recvpipe uint64 + Sendpipe uint64 + Ssthresh uint64 + Rtt uint64 + Rttvar uint64 + Expire int64 + Pksent int64 +} + +type Mclpool [0]byte + +const ( + SizeofBpfVersion = 0x4 + SizeofBpfStat = 0x80 + SizeofBpfProgram = 0x10 + SizeofBpfInsn = 0x8 + SizeofBpfHdr = 0x20 +) + +type BpfVersion struct { + Major uint16 + Minor uint16 +} + +type BpfStat struct { + Recv uint64 + Drop uint64 + Capt uint64 + Padding [13]uint64 +} + +type BpfProgram struct { + Len uint32 + Pad_cgo_0 [4]byte + Insns *BpfInsn +} + +type BpfInsn struct { + Code uint16 + Jt uint8 + Jf uint8 + K uint32 +} + +type BpfHdr struct { + Tstamp BpfTimeval + Caplen uint32 + Datalen uint32 + Hdrlen uint16 + Pad_cgo_0 [6]byte +} + +type BpfTimeval struct { + Sec int64 + Usec int64 +} + +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]uint8 + Ispeed int32 + Ospeed int32 +} + +type Winsize struct { + Row uint16 + Col uint16 + Xpixel uint16 + Ypixel uint16 +} + +type Ptmget struct { + Cfd int32 + Sfd int32 + Cn [1024]byte + Sn [1024]byte +} + +const ( + AT_FDCWD = -0x64 + AT_SYMLINK_NOFOLLOW = 0x200 +) + +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLERR = 0x8 + POLLHUP = 0x10 + POLLIN = 0x1 + POLLNVAL = 0x20 + POLLOUT = 0x4 + POLLPRI = 0x2 + POLLRDBAND = 0x80 + POLLRDNORM = 0x40 + POLLWRBAND = 0x100 + POLLWRNORM = 0x4 +) + +type Sysctlnode struct { + Flags uint32 + Num int32 + Name [32]int8 + Ver uint32 + X__rsvd uint32 + Un [16]byte + X_sysctl_size [8]byte + X_sysctl_func [8]byte + X_sysctl_parent [8]byte + X_sysctl_desc [8]byte +} + +type Utsname struct { + Sysname [256]byte + Nodename [256]byte + Release [256]byte + Version [256]byte + Machine [256]byte +} + +const SizeofClockinfo = 0x14 + +type Clockinfo struct { + Hz int32 + Tick int32 + Tickadj int32 + Stathz int32 + Profhz int32 +} diff --git a/vendor/golang.org/x/text/unicode/norm/composition.go b/vendor/golang.org/x/text/unicode/norm/composition.go index bab4c5d..9f37ef0 100644 --- a/vendor/golang.org/x/text/unicode/norm/composition.go +++ b/vendor/golang.org/x/text/unicode/norm/composition.go @@ -407,7 +407,7 @@ func decomposeHangul(buf []byte, r rune) int { // decomposeHangul algorithmically decomposes a Hangul rune into // its Jamo components. -// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul. +// See https://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul. func (rb *reorderBuffer) decomposeHangul(r rune) { r -= hangulBase x := r % jamoTCount @@ -420,7 +420,7 @@ func (rb *reorderBuffer) decomposeHangul(r rune) { } // combineHangul algorithmically combines Jamo character components into Hangul. -// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul. +// See https://unicode.org/reports/tr15/#Hangul for details on combining Hangul. func (rb *reorderBuffer) combineHangul(s, i, k int) { b := rb.rune[:] bn := rb.nrune diff --git a/vendor/golang.org/x/text/unicode/norm/forminfo.go b/vendor/golang.org/x/text/unicode/norm/forminfo.go index e67e765..f7fbf86 100644 --- a/vendor/golang.org/x/text/unicode/norm/forminfo.go +++ b/vendor/golang.org/x/text/unicode/norm/forminfo.go @@ -4,6 +4,8 @@ package norm +import "encoding/binary" + // This file contains Form-specific logic and wrappers for data in tables.go. // Rune info is stored in a separate trie per composing form. A composing form @@ -178,6 +180,17 @@ func (p Properties) TrailCCC() uint8 { return ccc[p.tccc] } +func buildRecompMap() { + recompMap = make(map[uint32]rune, len(recompMapPacked)/8) + var buf [8]byte + for i := 0; i < len(recompMapPacked); i += 8 { + copy(buf[:], recompMapPacked[i:i+8]) + key := binary.BigEndian.Uint32(buf[:4]) + val := binary.BigEndian.Uint32(buf[4:]) + recompMap[key] = rune(val) + } +} + // Recomposition // We use 32-bit keys instead of 64-bit for the two codepoint keys. // This clips off the bits of three entries, but we know this will not @@ -188,6 +201,7 @@ func (p Properties) TrailCCC() uint8 { // combine returns the combined rune or 0 if it doesn't exist. func combine(a, b rune) rune { key := uint32(uint16(a))<<16 + uint32(uint16(b)) + recompMapOnce.Do(buildRecompMap) return recompMap[key] } diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go index 338c395..30a3aa9 100644 --- a/vendor/golang.org/x/text/unicode/norm/maketables.go +++ b/vendor/golang.org/x/text/unicode/norm/maketables.go @@ -12,6 +12,7 @@ package main import ( "bytes" + "encoding/binary" "flag" "fmt" "io" @@ -261,7 +262,7 @@ func compactCCC() { // CompositionExclusions.txt has form: // 0958 # ... -// See http://unicode.org/reports/tr44/ for full explanation +// See https://unicode.org/reports/tr44/ for full explanation func loadCompositionExclusions() { f := gen.OpenUCDFile("CompositionExclusions.txt") defer f.Close() @@ -735,6 +736,8 @@ func makeTables() { max = n } } + fmt.Fprintln(w, `import "sync"`) + fmt.Fprintln(w) fmt.Fprintln(w, "const (") fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.") @@ -782,16 +785,23 @@ func makeTables() { sz := nrentries * 8 size += sz fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz) - fmt.Fprintln(w, "var recompMap = map[uint32]rune{") + fmt.Fprintln(w, "var recompMap map[uint32]rune") + fmt.Fprintln(w, "var recompMapOnce sync.Once\n") + fmt.Fprintln(w, `const recompMapPacked = "" +`) + var buf [8]byte for i, c := range chars { f := c.forms[FCanonical] d := f.decomp if !f.isOneWay && len(d) > 0 { key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1])) - fmt.Fprintf(w, "0x%.8X: 0x%.4X,\n", key, i) + binary.BigEndian.PutUint32(buf[:4], key) + binary.BigEndian.PutUint32(buf[4:], uint32(i)) + fmt.Fprintf(w, "\t\t%q + // 0x%.8X: 0x%.8X\n", string(buf[:]), key, uint32(i)) } } - fmt.Fprintf(w, "}\n\n") + // hack so we don't have to special case the trailing plus sign + fmt.Fprintf(w, ` ""`) + fmt.Fprintln(w) } fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size) @@ -857,7 +867,7 @@ func verifyComputed() { // DerivedNormalizationProps.txt has form: // 00C0..00C5 ; NFD_QC; N # ... // 0374 ; NFD_QC; N # ... -// See http://unicode.org/reports/tr44/ for full explanation +// See https://unicode.org/reports/tr44/ for full explanation func testDerived() { f := gen.OpenUCDFile("DerivedNormalizationProps.txt") defer f.Close() diff --git a/vendor/golang.org/x/text/unicode/norm/normalize.go b/vendor/golang.org/x/text/unicode/norm/normalize.go index e28ac64..95efcf2 100644 --- a/vendor/golang.org/x/text/unicode/norm/normalize.go +++ b/vendor/golang.org/x/text/unicode/norm/normalize.go @@ -29,8 +29,8 @@ import ( // proceed independently on both sides: // f(x) == append(f(x[0:n]), f(x[n:])...) // -// References: http://unicode.org/reports/tr15/ and -// http://unicode.org/notes/tn5/. +// References: https://unicode.org/reports/tr15/ and +// https://unicode.org/notes/tn5/. type Form int const ( diff --git a/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go index 44dd397..c48a97b 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables10.0.0.go @@ -4,6 +4,8 @@ package norm +import "sync" + const ( // Version is the Unicode edition from which the tables are derived. Version = "10.0.0" @@ -6707,947 +6709,949 @@ var nfkcSparseValues = [869]valueRange{ } // recompMap: 7520 bytes (entries only) -var recompMap = map[uint32]rune{ - 0x00410300: 0x00C0, - 0x00410301: 0x00C1, - 0x00410302: 0x00C2, - 0x00410303: 0x00C3, - 0x00410308: 0x00C4, - 0x0041030A: 0x00C5, - 0x00430327: 0x00C7, - 0x00450300: 0x00C8, - 0x00450301: 0x00C9, - 0x00450302: 0x00CA, - 0x00450308: 0x00CB, - 0x00490300: 0x00CC, - 0x00490301: 0x00CD, - 0x00490302: 0x00CE, - 0x00490308: 0x00CF, - 0x004E0303: 0x00D1, - 0x004F0300: 0x00D2, - 0x004F0301: 0x00D3, - 0x004F0302: 0x00D4, - 0x004F0303: 0x00D5, - 0x004F0308: 0x00D6, - 0x00550300: 0x00D9, - 0x00550301: 0x00DA, - 0x00550302: 0x00DB, - 0x00550308: 0x00DC, - 0x00590301: 0x00DD, - 0x00610300: 0x00E0, - 0x00610301: 0x00E1, - 0x00610302: 0x00E2, - 0x00610303: 0x00E3, - 0x00610308: 0x00E4, - 0x0061030A: 0x00E5, - 0x00630327: 0x00E7, - 0x00650300: 0x00E8, - 0x00650301: 0x00E9, - 0x00650302: 0x00EA, - 0x00650308: 0x00EB, - 0x00690300: 0x00EC, - 0x00690301: 0x00ED, - 0x00690302: 0x00EE, - 0x00690308: 0x00EF, - 0x006E0303: 0x00F1, - 0x006F0300: 0x00F2, - 0x006F0301: 0x00F3, - 0x006F0302: 0x00F4, - 0x006F0303: 0x00F5, - 0x006F0308: 0x00F6, - 0x00750300: 0x00F9, - 0x00750301: 0x00FA, - 0x00750302: 0x00FB, - 0x00750308: 0x00FC, - 0x00790301: 0x00FD, - 0x00790308: 0x00FF, - 0x00410304: 0x0100, - 0x00610304: 0x0101, - 0x00410306: 0x0102, - 0x00610306: 0x0103, - 0x00410328: 0x0104, - 0x00610328: 0x0105, - 0x00430301: 0x0106, - 0x00630301: 0x0107, - 0x00430302: 0x0108, - 0x00630302: 0x0109, - 0x00430307: 0x010A, - 0x00630307: 0x010B, - 0x0043030C: 0x010C, - 0x0063030C: 0x010D, - 0x0044030C: 0x010E, - 0x0064030C: 0x010F, - 0x00450304: 0x0112, - 0x00650304: 0x0113, - 0x00450306: 0x0114, - 0x00650306: 0x0115, - 0x00450307: 0x0116, - 0x00650307: 0x0117, - 0x00450328: 0x0118, - 0x00650328: 0x0119, - 0x0045030C: 0x011A, - 0x0065030C: 0x011B, - 0x00470302: 0x011C, - 0x00670302: 0x011D, - 0x00470306: 0x011E, - 0x00670306: 0x011F, - 0x00470307: 0x0120, - 0x00670307: 0x0121, - 0x00470327: 0x0122, - 0x00670327: 0x0123, - 0x00480302: 0x0124, - 0x00680302: 0x0125, - 0x00490303: 0x0128, - 0x00690303: 0x0129, - 0x00490304: 0x012A, - 0x00690304: 0x012B, - 0x00490306: 0x012C, - 0x00690306: 0x012D, - 0x00490328: 0x012E, - 0x00690328: 0x012F, - 0x00490307: 0x0130, - 0x004A0302: 0x0134, - 0x006A0302: 0x0135, - 0x004B0327: 0x0136, - 0x006B0327: 0x0137, - 0x004C0301: 0x0139, - 0x006C0301: 0x013A, - 0x004C0327: 0x013B, - 0x006C0327: 0x013C, - 0x004C030C: 0x013D, - 0x006C030C: 0x013E, - 0x004E0301: 0x0143, - 0x006E0301: 0x0144, - 0x004E0327: 0x0145, - 0x006E0327: 0x0146, - 0x004E030C: 0x0147, - 0x006E030C: 0x0148, - 0x004F0304: 0x014C, - 0x006F0304: 0x014D, - 0x004F0306: 0x014E, - 0x006F0306: 0x014F, - 0x004F030B: 0x0150, - 0x006F030B: 0x0151, - 0x00520301: 0x0154, - 0x00720301: 0x0155, - 0x00520327: 0x0156, - 0x00720327: 0x0157, - 0x0052030C: 0x0158, - 0x0072030C: 0x0159, - 0x00530301: 0x015A, - 0x00730301: 0x015B, - 0x00530302: 0x015C, - 0x00730302: 0x015D, - 0x00530327: 0x015E, - 0x00730327: 0x015F, - 0x0053030C: 0x0160, - 0x0073030C: 0x0161, - 0x00540327: 0x0162, - 0x00740327: 0x0163, - 0x0054030C: 0x0164, - 0x0074030C: 0x0165, - 0x00550303: 0x0168, - 0x00750303: 0x0169, - 0x00550304: 0x016A, - 0x00750304: 0x016B, - 0x00550306: 0x016C, - 0x00750306: 0x016D, - 0x0055030A: 0x016E, - 0x0075030A: 0x016F, - 0x0055030B: 0x0170, - 0x0075030B: 0x0171, - 0x00550328: 0x0172, - 0x00750328: 0x0173, - 0x00570302: 0x0174, - 0x00770302: 0x0175, - 0x00590302: 0x0176, - 0x00790302: 0x0177, - 0x00590308: 0x0178, - 0x005A0301: 0x0179, - 0x007A0301: 0x017A, - 0x005A0307: 0x017B, - 0x007A0307: 0x017C, - 0x005A030C: 0x017D, - 0x007A030C: 0x017E, - 0x004F031B: 0x01A0, - 0x006F031B: 0x01A1, - 0x0055031B: 0x01AF, - 0x0075031B: 0x01B0, - 0x0041030C: 0x01CD, - 0x0061030C: 0x01CE, - 0x0049030C: 0x01CF, - 0x0069030C: 0x01D0, - 0x004F030C: 0x01D1, - 0x006F030C: 0x01D2, - 0x0055030C: 0x01D3, - 0x0075030C: 0x01D4, - 0x00DC0304: 0x01D5, - 0x00FC0304: 0x01D6, - 0x00DC0301: 0x01D7, - 0x00FC0301: 0x01D8, - 0x00DC030C: 0x01D9, - 0x00FC030C: 0x01DA, - 0x00DC0300: 0x01DB, - 0x00FC0300: 0x01DC, - 0x00C40304: 0x01DE, - 0x00E40304: 0x01DF, - 0x02260304: 0x01E0, - 0x02270304: 0x01E1, - 0x00C60304: 0x01E2, - 0x00E60304: 0x01E3, - 0x0047030C: 0x01E6, - 0x0067030C: 0x01E7, - 0x004B030C: 0x01E8, - 0x006B030C: 0x01E9, - 0x004F0328: 0x01EA, - 0x006F0328: 0x01EB, - 0x01EA0304: 0x01EC, - 0x01EB0304: 0x01ED, - 0x01B7030C: 0x01EE, - 0x0292030C: 0x01EF, - 0x006A030C: 0x01F0, - 0x00470301: 0x01F4, - 0x00670301: 0x01F5, - 0x004E0300: 0x01F8, - 0x006E0300: 0x01F9, - 0x00C50301: 0x01FA, - 0x00E50301: 0x01FB, - 0x00C60301: 0x01FC, - 0x00E60301: 0x01FD, - 0x00D80301: 0x01FE, - 0x00F80301: 0x01FF, - 0x0041030F: 0x0200, - 0x0061030F: 0x0201, - 0x00410311: 0x0202, - 0x00610311: 0x0203, - 0x0045030F: 0x0204, - 0x0065030F: 0x0205, - 0x00450311: 0x0206, - 0x00650311: 0x0207, - 0x0049030F: 0x0208, - 0x0069030F: 0x0209, - 0x00490311: 0x020A, - 0x00690311: 0x020B, - 0x004F030F: 0x020C, - 0x006F030F: 0x020D, - 0x004F0311: 0x020E, - 0x006F0311: 0x020F, - 0x0052030F: 0x0210, - 0x0072030F: 0x0211, - 0x00520311: 0x0212, - 0x00720311: 0x0213, - 0x0055030F: 0x0214, - 0x0075030F: 0x0215, - 0x00550311: 0x0216, - 0x00750311: 0x0217, - 0x00530326: 0x0218, - 0x00730326: 0x0219, - 0x00540326: 0x021A, - 0x00740326: 0x021B, - 0x0048030C: 0x021E, - 0x0068030C: 0x021F, - 0x00410307: 0x0226, - 0x00610307: 0x0227, - 0x00450327: 0x0228, - 0x00650327: 0x0229, - 0x00D60304: 0x022A, - 0x00F60304: 0x022B, - 0x00D50304: 0x022C, - 0x00F50304: 0x022D, - 0x004F0307: 0x022E, - 0x006F0307: 0x022F, - 0x022E0304: 0x0230, - 0x022F0304: 0x0231, - 0x00590304: 0x0232, - 0x00790304: 0x0233, - 0x00A80301: 0x0385, - 0x03910301: 0x0386, - 0x03950301: 0x0388, - 0x03970301: 0x0389, - 0x03990301: 0x038A, - 0x039F0301: 0x038C, - 0x03A50301: 0x038E, - 0x03A90301: 0x038F, - 0x03CA0301: 0x0390, - 0x03990308: 0x03AA, - 0x03A50308: 0x03AB, - 0x03B10301: 0x03AC, - 0x03B50301: 0x03AD, - 0x03B70301: 0x03AE, - 0x03B90301: 0x03AF, - 0x03CB0301: 0x03B0, - 0x03B90308: 0x03CA, - 0x03C50308: 0x03CB, - 0x03BF0301: 0x03CC, - 0x03C50301: 0x03CD, - 0x03C90301: 0x03CE, - 0x03D20301: 0x03D3, - 0x03D20308: 0x03D4, - 0x04150300: 0x0400, - 0x04150308: 0x0401, - 0x04130301: 0x0403, - 0x04060308: 0x0407, - 0x041A0301: 0x040C, - 0x04180300: 0x040D, - 0x04230306: 0x040E, - 0x04180306: 0x0419, - 0x04380306: 0x0439, - 0x04350300: 0x0450, - 0x04350308: 0x0451, - 0x04330301: 0x0453, - 0x04560308: 0x0457, - 0x043A0301: 0x045C, - 0x04380300: 0x045D, - 0x04430306: 0x045E, - 0x0474030F: 0x0476, - 0x0475030F: 0x0477, - 0x04160306: 0x04C1, - 0x04360306: 0x04C2, - 0x04100306: 0x04D0, - 0x04300306: 0x04D1, - 0x04100308: 0x04D2, - 0x04300308: 0x04D3, - 0x04150306: 0x04D6, - 0x04350306: 0x04D7, - 0x04D80308: 0x04DA, - 0x04D90308: 0x04DB, - 0x04160308: 0x04DC, - 0x04360308: 0x04DD, - 0x04170308: 0x04DE, - 0x04370308: 0x04DF, - 0x04180304: 0x04E2, - 0x04380304: 0x04E3, - 0x04180308: 0x04E4, - 0x04380308: 0x04E5, - 0x041E0308: 0x04E6, - 0x043E0308: 0x04E7, - 0x04E80308: 0x04EA, - 0x04E90308: 0x04EB, - 0x042D0308: 0x04EC, - 0x044D0308: 0x04ED, - 0x04230304: 0x04EE, - 0x04430304: 0x04EF, - 0x04230308: 0x04F0, - 0x04430308: 0x04F1, - 0x0423030B: 0x04F2, - 0x0443030B: 0x04F3, - 0x04270308: 0x04F4, - 0x04470308: 0x04F5, - 0x042B0308: 0x04F8, - 0x044B0308: 0x04F9, - 0x06270653: 0x0622, - 0x06270654: 0x0623, - 0x06480654: 0x0624, - 0x06270655: 0x0625, - 0x064A0654: 0x0626, - 0x06D50654: 0x06C0, - 0x06C10654: 0x06C2, - 0x06D20654: 0x06D3, - 0x0928093C: 0x0929, - 0x0930093C: 0x0931, - 0x0933093C: 0x0934, - 0x09C709BE: 0x09CB, - 0x09C709D7: 0x09CC, - 0x0B470B56: 0x0B48, - 0x0B470B3E: 0x0B4B, - 0x0B470B57: 0x0B4C, - 0x0B920BD7: 0x0B94, - 0x0BC60BBE: 0x0BCA, - 0x0BC70BBE: 0x0BCB, - 0x0BC60BD7: 0x0BCC, - 0x0C460C56: 0x0C48, - 0x0CBF0CD5: 0x0CC0, - 0x0CC60CD5: 0x0CC7, - 0x0CC60CD6: 0x0CC8, - 0x0CC60CC2: 0x0CCA, - 0x0CCA0CD5: 0x0CCB, - 0x0D460D3E: 0x0D4A, - 0x0D470D3E: 0x0D4B, - 0x0D460D57: 0x0D4C, - 0x0DD90DCA: 0x0DDA, - 0x0DD90DCF: 0x0DDC, - 0x0DDC0DCA: 0x0DDD, - 0x0DD90DDF: 0x0DDE, - 0x1025102E: 0x1026, - 0x1B051B35: 0x1B06, - 0x1B071B35: 0x1B08, - 0x1B091B35: 0x1B0A, - 0x1B0B1B35: 0x1B0C, - 0x1B0D1B35: 0x1B0E, - 0x1B111B35: 0x1B12, - 0x1B3A1B35: 0x1B3B, - 0x1B3C1B35: 0x1B3D, - 0x1B3E1B35: 0x1B40, - 0x1B3F1B35: 0x1B41, - 0x1B421B35: 0x1B43, - 0x00410325: 0x1E00, - 0x00610325: 0x1E01, - 0x00420307: 0x1E02, - 0x00620307: 0x1E03, - 0x00420323: 0x1E04, - 0x00620323: 0x1E05, - 0x00420331: 0x1E06, - 0x00620331: 0x1E07, - 0x00C70301: 0x1E08, - 0x00E70301: 0x1E09, - 0x00440307: 0x1E0A, - 0x00640307: 0x1E0B, - 0x00440323: 0x1E0C, - 0x00640323: 0x1E0D, - 0x00440331: 0x1E0E, - 0x00640331: 0x1E0F, - 0x00440327: 0x1E10, - 0x00640327: 0x1E11, - 0x0044032D: 0x1E12, - 0x0064032D: 0x1E13, - 0x01120300: 0x1E14, - 0x01130300: 0x1E15, - 0x01120301: 0x1E16, - 0x01130301: 0x1E17, - 0x0045032D: 0x1E18, - 0x0065032D: 0x1E19, - 0x00450330: 0x1E1A, - 0x00650330: 0x1E1B, - 0x02280306: 0x1E1C, - 0x02290306: 0x1E1D, - 0x00460307: 0x1E1E, - 0x00660307: 0x1E1F, - 0x00470304: 0x1E20, - 0x00670304: 0x1E21, - 0x00480307: 0x1E22, - 0x00680307: 0x1E23, - 0x00480323: 0x1E24, - 0x00680323: 0x1E25, - 0x00480308: 0x1E26, - 0x00680308: 0x1E27, - 0x00480327: 0x1E28, - 0x00680327: 0x1E29, - 0x0048032E: 0x1E2A, - 0x0068032E: 0x1E2B, - 0x00490330: 0x1E2C, - 0x00690330: 0x1E2D, - 0x00CF0301: 0x1E2E, - 0x00EF0301: 0x1E2F, - 0x004B0301: 0x1E30, - 0x006B0301: 0x1E31, - 0x004B0323: 0x1E32, - 0x006B0323: 0x1E33, - 0x004B0331: 0x1E34, - 0x006B0331: 0x1E35, - 0x004C0323: 0x1E36, - 0x006C0323: 0x1E37, - 0x1E360304: 0x1E38, - 0x1E370304: 0x1E39, - 0x004C0331: 0x1E3A, - 0x006C0331: 0x1E3B, - 0x004C032D: 0x1E3C, - 0x006C032D: 0x1E3D, - 0x004D0301: 0x1E3E, - 0x006D0301: 0x1E3F, - 0x004D0307: 0x1E40, - 0x006D0307: 0x1E41, - 0x004D0323: 0x1E42, - 0x006D0323: 0x1E43, - 0x004E0307: 0x1E44, - 0x006E0307: 0x1E45, - 0x004E0323: 0x1E46, - 0x006E0323: 0x1E47, - 0x004E0331: 0x1E48, - 0x006E0331: 0x1E49, - 0x004E032D: 0x1E4A, - 0x006E032D: 0x1E4B, - 0x00D50301: 0x1E4C, - 0x00F50301: 0x1E4D, - 0x00D50308: 0x1E4E, - 0x00F50308: 0x1E4F, - 0x014C0300: 0x1E50, - 0x014D0300: 0x1E51, - 0x014C0301: 0x1E52, - 0x014D0301: 0x1E53, - 0x00500301: 0x1E54, - 0x00700301: 0x1E55, - 0x00500307: 0x1E56, - 0x00700307: 0x1E57, - 0x00520307: 0x1E58, - 0x00720307: 0x1E59, - 0x00520323: 0x1E5A, - 0x00720323: 0x1E5B, - 0x1E5A0304: 0x1E5C, - 0x1E5B0304: 0x1E5D, - 0x00520331: 0x1E5E, - 0x00720331: 0x1E5F, - 0x00530307: 0x1E60, - 0x00730307: 0x1E61, - 0x00530323: 0x1E62, - 0x00730323: 0x1E63, - 0x015A0307: 0x1E64, - 0x015B0307: 0x1E65, - 0x01600307: 0x1E66, - 0x01610307: 0x1E67, - 0x1E620307: 0x1E68, - 0x1E630307: 0x1E69, - 0x00540307: 0x1E6A, - 0x00740307: 0x1E6B, - 0x00540323: 0x1E6C, - 0x00740323: 0x1E6D, - 0x00540331: 0x1E6E, - 0x00740331: 0x1E6F, - 0x0054032D: 0x1E70, - 0x0074032D: 0x1E71, - 0x00550324: 0x1E72, - 0x00750324: 0x1E73, - 0x00550330: 0x1E74, - 0x00750330: 0x1E75, - 0x0055032D: 0x1E76, - 0x0075032D: 0x1E77, - 0x01680301: 0x1E78, - 0x01690301: 0x1E79, - 0x016A0308: 0x1E7A, - 0x016B0308: 0x1E7B, - 0x00560303: 0x1E7C, - 0x00760303: 0x1E7D, - 0x00560323: 0x1E7E, - 0x00760323: 0x1E7F, - 0x00570300: 0x1E80, - 0x00770300: 0x1E81, - 0x00570301: 0x1E82, - 0x00770301: 0x1E83, - 0x00570308: 0x1E84, - 0x00770308: 0x1E85, - 0x00570307: 0x1E86, - 0x00770307: 0x1E87, - 0x00570323: 0x1E88, - 0x00770323: 0x1E89, - 0x00580307: 0x1E8A, - 0x00780307: 0x1E8B, - 0x00580308: 0x1E8C, - 0x00780308: 0x1E8D, - 0x00590307: 0x1E8E, - 0x00790307: 0x1E8F, - 0x005A0302: 0x1E90, - 0x007A0302: 0x1E91, - 0x005A0323: 0x1E92, - 0x007A0323: 0x1E93, - 0x005A0331: 0x1E94, - 0x007A0331: 0x1E95, - 0x00680331: 0x1E96, - 0x00740308: 0x1E97, - 0x0077030A: 0x1E98, - 0x0079030A: 0x1E99, - 0x017F0307: 0x1E9B, - 0x00410323: 0x1EA0, - 0x00610323: 0x1EA1, - 0x00410309: 0x1EA2, - 0x00610309: 0x1EA3, - 0x00C20301: 0x1EA4, - 0x00E20301: 0x1EA5, - 0x00C20300: 0x1EA6, - 0x00E20300: 0x1EA7, - 0x00C20309: 0x1EA8, - 0x00E20309: 0x1EA9, - 0x00C20303: 0x1EAA, - 0x00E20303: 0x1EAB, - 0x1EA00302: 0x1EAC, - 0x1EA10302: 0x1EAD, - 0x01020301: 0x1EAE, - 0x01030301: 0x1EAF, - 0x01020300: 0x1EB0, - 0x01030300: 0x1EB1, - 0x01020309: 0x1EB2, - 0x01030309: 0x1EB3, - 0x01020303: 0x1EB4, - 0x01030303: 0x1EB5, - 0x1EA00306: 0x1EB6, - 0x1EA10306: 0x1EB7, - 0x00450323: 0x1EB8, - 0x00650323: 0x1EB9, - 0x00450309: 0x1EBA, - 0x00650309: 0x1EBB, - 0x00450303: 0x1EBC, - 0x00650303: 0x1EBD, - 0x00CA0301: 0x1EBE, - 0x00EA0301: 0x1EBF, - 0x00CA0300: 0x1EC0, - 0x00EA0300: 0x1EC1, - 0x00CA0309: 0x1EC2, - 0x00EA0309: 0x1EC3, - 0x00CA0303: 0x1EC4, - 0x00EA0303: 0x1EC5, - 0x1EB80302: 0x1EC6, - 0x1EB90302: 0x1EC7, - 0x00490309: 0x1EC8, - 0x00690309: 0x1EC9, - 0x00490323: 0x1ECA, - 0x00690323: 0x1ECB, - 0x004F0323: 0x1ECC, - 0x006F0323: 0x1ECD, - 0x004F0309: 0x1ECE, - 0x006F0309: 0x1ECF, - 0x00D40301: 0x1ED0, - 0x00F40301: 0x1ED1, - 0x00D40300: 0x1ED2, - 0x00F40300: 0x1ED3, - 0x00D40309: 0x1ED4, - 0x00F40309: 0x1ED5, - 0x00D40303: 0x1ED6, - 0x00F40303: 0x1ED7, - 0x1ECC0302: 0x1ED8, - 0x1ECD0302: 0x1ED9, - 0x01A00301: 0x1EDA, - 0x01A10301: 0x1EDB, - 0x01A00300: 0x1EDC, - 0x01A10300: 0x1EDD, - 0x01A00309: 0x1EDE, - 0x01A10309: 0x1EDF, - 0x01A00303: 0x1EE0, - 0x01A10303: 0x1EE1, - 0x01A00323: 0x1EE2, - 0x01A10323: 0x1EE3, - 0x00550323: 0x1EE4, - 0x00750323: 0x1EE5, - 0x00550309: 0x1EE6, - 0x00750309: 0x1EE7, - 0x01AF0301: 0x1EE8, - 0x01B00301: 0x1EE9, - 0x01AF0300: 0x1EEA, - 0x01B00300: 0x1EEB, - 0x01AF0309: 0x1EEC, - 0x01B00309: 0x1EED, - 0x01AF0303: 0x1EEE, - 0x01B00303: 0x1EEF, - 0x01AF0323: 0x1EF0, - 0x01B00323: 0x1EF1, - 0x00590300: 0x1EF2, - 0x00790300: 0x1EF3, - 0x00590323: 0x1EF4, - 0x00790323: 0x1EF5, - 0x00590309: 0x1EF6, - 0x00790309: 0x1EF7, - 0x00590303: 0x1EF8, - 0x00790303: 0x1EF9, - 0x03B10313: 0x1F00, - 0x03B10314: 0x1F01, - 0x1F000300: 0x1F02, - 0x1F010300: 0x1F03, - 0x1F000301: 0x1F04, - 0x1F010301: 0x1F05, - 0x1F000342: 0x1F06, - 0x1F010342: 0x1F07, - 0x03910313: 0x1F08, - 0x03910314: 0x1F09, - 0x1F080300: 0x1F0A, - 0x1F090300: 0x1F0B, - 0x1F080301: 0x1F0C, - 0x1F090301: 0x1F0D, - 0x1F080342: 0x1F0E, - 0x1F090342: 0x1F0F, - 0x03B50313: 0x1F10, - 0x03B50314: 0x1F11, - 0x1F100300: 0x1F12, - 0x1F110300: 0x1F13, - 0x1F100301: 0x1F14, - 0x1F110301: 0x1F15, - 0x03950313: 0x1F18, - 0x03950314: 0x1F19, - 0x1F180300: 0x1F1A, - 0x1F190300: 0x1F1B, - 0x1F180301: 0x1F1C, - 0x1F190301: 0x1F1D, - 0x03B70313: 0x1F20, - 0x03B70314: 0x1F21, - 0x1F200300: 0x1F22, - 0x1F210300: 0x1F23, - 0x1F200301: 0x1F24, - 0x1F210301: 0x1F25, - 0x1F200342: 0x1F26, - 0x1F210342: 0x1F27, - 0x03970313: 0x1F28, - 0x03970314: 0x1F29, - 0x1F280300: 0x1F2A, - 0x1F290300: 0x1F2B, - 0x1F280301: 0x1F2C, - 0x1F290301: 0x1F2D, - 0x1F280342: 0x1F2E, - 0x1F290342: 0x1F2F, - 0x03B90313: 0x1F30, - 0x03B90314: 0x1F31, - 0x1F300300: 0x1F32, - 0x1F310300: 0x1F33, - 0x1F300301: 0x1F34, - 0x1F310301: 0x1F35, - 0x1F300342: 0x1F36, - 0x1F310342: 0x1F37, - 0x03990313: 0x1F38, - 0x03990314: 0x1F39, - 0x1F380300: 0x1F3A, - 0x1F390300: 0x1F3B, - 0x1F380301: 0x1F3C, - 0x1F390301: 0x1F3D, - 0x1F380342: 0x1F3E, - 0x1F390342: 0x1F3F, - 0x03BF0313: 0x1F40, - 0x03BF0314: 0x1F41, - 0x1F400300: 0x1F42, - 0x1F410300: 0x1F43, - 0x1F400301: 0x1F44, - 0x1F410301: 0x1F45, - 0x039F0313: 0x1F48, - 0x039F0314: 0x1F49, - 0x1F480300: 0x1F4A, - 0x1F490300: 0x1F4B, - 0x1F480301: 0x1F4C, - 0x1F490301: 0x1F4D, - 0x03C50313: 0x1F50, - 0x03C50314: 0x1F51, - 0x1F500300: 0x1F52, - 0x1F510300: 0x1F53, - 0x1F500301: 0x1F54, - 0x1F510301: 0x1F55, - 0x1F500342: 0x1F56, - 0x1F510342: 0x1F57, - 0x03A50314: 0x1F59, - 0x1F590300: 0x1F5B, - 0x1F590301: 0x1F5D, - 0x1F590342: 0x1F5F, - 0x03C90313: 0x1F60, - 0x03C90314: 0x1F61, - 0x1F600300: 0x1F62, - 0x1F610300: 0x1F63, - 0x1F600301: 0x1F64, - 0x1F610301: 0x1F65, - 0x1F600342: 0x1F66, - 0x1F610342: 0x1F67, - 0x03A90313: 0x1F68, - 0x03A90314: 0x1F69, - 0x1F680300: 0x1F6A, - 0x1F690300: 0x1F6B, - 0x1F680301: 0x1F6C, - 0x1F690301: 0x1F6D, - 0x1F680342: 0x1F6E, - 0x1F690342: 0x1F6F, - 0x03B10300: 0x1F70, - 0x03B50300: 0x1F72, - 0x03B70300: 0x1F74, - 0x03B90300: 0x1F76, - 0x03BF0300: 0x1F78, - 0x03C50300: 0x1F7A, - 0x03C90300: 0x1F7C, - 0x1F000345: 0x1F80, - 0x1F010345: 0x1F81, - 0x1F020345: 0x1F82, - 0x1F030345: 0x1F83, - 0x1F040345: 0x1F84, - 0x1F050345: 0x1F85, - 0x1F060345: 0x1F86, - 0x1F070345: 0x1F87, - 0x1F080345: 0x1F88, - 0x1F090345: 0x1F89, - 0x1F0A0345: 0x1F8A, - 0x1F0B0345: 0x1F8B, - 0x1F0C0345: 0x1F8C, - 0x1F0D0345: 0x1F8D, - 0x1F0E0345: 0x1F8E, - 0x1F0F0345: 0x1F8F, - 0x1F200345: 0x1F90, - 0x1F210345: 0x1F91, - 0x1F220345: 0x1F92, - 0x1F230345: 0x1F93, - 0x1F240345: 0x1F94, - 0x1F250345: 0x1F95, - 0x1F260345: 0x1F96, - 0x1F270345: 0x1F97, - 0x1F280345: 0x1F98, - 0x1F290345: 0x1F99, - 0x1F2A0345: 0x1F9A, - 0x1F2B0345: 0x1F9B, - 0x1F2C0345: 0x1F9C, - 0x1F2D0345: 0x1F9D, - 0x1F2E0345: 0x1F9E, - 0x1F2F0345: 0x1F9F, - 0x1F600345: 0x1FA0, - 0x1F610345: 0x1FA1, - 0x1F620345: 0x1FA2, - 0x1F630345: 0x1FA3, - 0x1F640345: 0x1FA4, - 0x1F650345: 0x1FA5, - 0x1F660345: 0x1FA6, - 0x1F670345: 0x1FA7, - 0x1F680345: 0x1FA8, - 0x1F690345: 0x1FA9, - 0x1F6A0345: 0x1FAA, - 0x1F6B0345: 0x1FAB, - 0x1F6C0345: 0x1FAC, - 0x1F6D0345: 0x1FAD, - 0x1F6E0345: 0x1FAE, - 0x1F6F0345: 0x1FAF, - 0x03B10306: 0x1FB0, - 0x03B10304: 0x1FB1, - 0x1F700345: 0x1FB2, - 0x03B10345: 0x1FB3, - 0x03AC0345: 0x1FB4, - 0x03B10342: 0x1FB6, - 0x1FB60345: 0x1FB7, - 0x03910306: 0x1FB8, - 0x03910304: 0x1FB9, - 0x03910300: 0x1FBA, - 0x03910345: 0x1FBC, - 0x00A80342: 0x1FC1, - 0x1F740345: 0x1FC2, - 0x03B70345: 0x1FC3, - 0x03AE0345: 0x1FC4, - 0x03B70342: 0x1FC6, - 0x1FC60345: 0x1FC7, - 0x03950300: 0x1FC8, - 0x03970300: 0x1FCA, - 0x03970345: 0x1FCC, - 0x1FBF0300: 0x1FCD, - 0x1FBF0301: 0x1FCE, - 0x1FBF0342: 0x1FCF, - 0x03B90306: 0x1FD0, - 0x03B90304: 0x1FD1, - 0x03CA0300: 0x1FD2, - 0x03B90342: 0x1FD6, - 0x03CA0342: 0x1FD7, - 0x03990306: 0x1FD8, - 0x03990304: 0x1FD9, - 0x03990300: 0x1FDA, - 0x1FFE0300: 0x1FDD, - 0x1FFE0301: 0x1FDE, - 0x1FFE0342: 0x1FDF, - 0x03C50306: 0x1FE0, - 0x03C50304: 0x1FE1, - 0x03CB0300: 0x1FE2, - 0x03C10313: 0x1FE4, - 0x03C10314: 0x1FE5, - 0x03C50342: 0x1FE6, - 0x03CB0342: 0x1FE7, - 0x03A50306: 0x1FE8, - 0x03A50304: 0x1FE9, - 0x03A50300: 0x1FEA, - 0x03A10314: 0x1FEC, - 0x00A80300: 0x1FED, - 0x1F7C0345: 0x1FF2, - 0x03C90345: 0x1FF3, - 0x03CE0345: 0x1FF4, - 0x03C90342: 0x1FF6, - 0x1FF60345: 0x1FF7, - 0x039F0300: 0x1FF8, - 0x03A90300: 0x1FFA, - 0x03A90345: 0x1FFC, - 0x21900338: 0x219A, - 0x21920338: 0x219B, - 0x21940338: 0x21AE, - 0x21D00338: 0x21CD, - 0x21D40338: 0x21CE, - 0x21D20338: 0x21CF, - 0x22030338: 0x2204, - 0x22080338: 0x2209, - 0x220B0338: 0x220C, - 0x22230338: 0x2224, - 0x22250338: 0x2226, - 0x223C0338: 0x2241, - 0x22430338: 0x2244, - 0x22450338: 0x2247, - 0x22480338: 0x2249, - 0x003D0338: 0x2260, - 0x22610338: 0x2262, - 0x224D0338: 0x226D, - 0x003C0338: 0x226E, - 0x003E0338: 0x226F, - 0x22640338: 0x2270, - 0x22650338: 0x2271, - 0x22720338: 0x2274, - 0x22730338: 0x2275, - 0x22760338: 0x2278, - 0x22770338: 0x2279, - 0x227A0338: 0x2280, - 0x227B0338: 0x2281, - 0x22820338: 0x2284, - 0x22830338: 0x2285, - 0x22860338: 0x2288, - 0x22870338: 0x2289, - 0x22A20338: 0x22AC, - 0x22A80338: 0x22AD, - 0x22A90338: 0x22AE, - 0x22AB0338: 0x22AF, - 0x227C0338: 0x22E0, - 0x227D0338: 0x22E1, - 0x22910338: 0x22E2, - 0x22920338: 0x22E3, - 0x22B20338: 0x22EA, - 0x22B30338: 0x22EB, - 0x22B40338: 0x22EC, - 0x22B50338: 0x22ED, - 0x304B3099: 0x304C, - 0x304D3099: 0x304E, - 0x304F3099: 0x3050, - 0x30513099: 0x3052, - 0x30533099: 0x3054, - 0x30553099: 0x3056, - 0x30573099: 0x3058, - 0x30593099: 0x305A, - 0x305B3099: 0x305C, - 0x305D3099: 0x305E, - 0x305F3099: 0x3060, - 0x30613099: 0x3062, - 0x30643099: 0x3065, - 0x30663099: 0x3067, - 0x30683099: 0x3069, - 0x306F3099: 0x3070, - 0x306F309A: 0x3071, - 0x30723099: 0x3073, - 0x3072309A: 0x3074, - 0x30753099: 0x3076, - 0x3075309A: 0x3077, - 0x30783099: 0x3079, - 0x3078309A: 0x307A, - 0x307B3099: 0x307C, - 0x307B309A: 0x307D, - 0x30463099: 0x3094, - 0x309D3099: 0x309E, - 0x30AB3099: 0x30AC, - 0x30AD3099: 0x30AE, - 0x30AF3099: 0x30B0, - 0x30B13099: 0x30B2, - 0x30B33099: 0x30B4, - 0x30B53099: 0x30B6, - 0x30B73099: 0x30B8, - 0x30B93099: 0x30BA, - 0x30BB3099: 0x30BC, - 0x30BD3099: 0x30BE, - 0x30BF3099: 0x30C0, - 0x30C13099: 0x30C2, - 0x30C43099: 0x30C5, - 0x30C63099: 0x30C7, - 0x30C83099: 0x30C9, - 0x30CF3099: 0x30D0, - 0x30CF309A: 0x30D1, - 0x30D23099: 0x30D3, - 0x30D2309A: 0x30D4, - 0x30D53099: 0x30D6, - 0x30D5309A: 0x30D7, - 0x30D83099: 0x30D9, - 0x30D8309A: 0x30DA, - 0x30DB3099: 0x30DC, - 0x30DB309A: 0x30DD, - 0x30A63099: 0x30F4, - 0x30EF3099: 0x30F7, - 0x30F03099: 0x30F8, - 0x30F13099: 0x30F9, - 0x30F23099: 0x30FA, - 0x30FD3099: 0x30FE, - 0x109910BA: 0x1109A, - 0x109B10BA: 0x1109C, - 0x10A510BA: 0x110AB, - 0x11311127: 0x1112E, - 0x11321127: 0x1112F, - 0x1347133E: 0x1134B, - 0x13471357: 0x1134C, - 0x14B914BA: 0x114BB, - 0x14B914B0: 0x114BC, - 0x14B914BD: 0x114BE, - 0x15B815AF: 0x115BA, - 0x15B915AF: 0x115BB, -} +var recompMap map[uint32]rune +var recompMapOnce sync.Once -// Total size of tables: 53KB (54226 bytes) +const recompMapPacked = "" + + "\x00A\x03\x00\x00\x00\x00\xc0" + // 0x00410300: 0x000000C0 + "\x00A\x03\x01\x00\x00\x00\xc1" + // 0x00410301: 0x000000C1 + "\x00A\x03\x02\x00\x00\x00\xc2" + // 0x00410302: 0x000000C2 + "\x00A\x03\x03\x00\x00\x00\xc3" + // 0x00410303: 0x000000C3 + "\x00A\x03\b\x00\x00\x00\xc4" + // 0x00410308: 0x000000C4 + "\x00A\x03\n\x00\x00\x00\xc5" + // 0x0041030A: 0x000000C5 + "\x00C\x03'\x00\x00\x00\xc7" + // 0x00430327: 0x000000C7 + "\x00E\x03\x00\x00\x00\x00\xc8" + // 0x00450300: 0x000000C8 + "\x00E\x03\x01\x00\x00\x00\xc9" + // 0x00450301: 0x000000C9 + "\x00E\x03\x02\x00\x00\x00\xca" + // 0x00450302: 0x000000CA + "\x00E\x03\b\x00\x00\x00\xcb" + // 0x00450308: 0x000000CB + "\x00I\x03\x00\x00\x00\x00\xcc" + // 0x00490300: 0x000000CC + "\x00I\x03\x01\x00\x00\x00\xcd" + // 0x00490301: 0x000000CD + "\x00I\x03\x02\x00\x00\x00\xce" + // 0x00490302: 0x000000CE + "\x00I\x03\b\x00\x00\x00\xcf" + // 0x00490308: 0x000000CF + "\x00N\x03\x03\x00\x00\x00\xd1" + // 0x004E0303: 0x000000D1 + "\x00O\x03\x00\x00\x00\x00\xd2" + // 0x004F0300: 0x000000D2 + "\x00O\x03\x01\x00\x00\x00\xd3" + // 0x004F0301: 0x000000D3 + "\x00O\x03\x02\x00\x00\x00\xd4" + // 0x004F0302: 0x000000D4 + "\x00O\x03\x03\x00\x00\x00\xd5" + // 0x004F0303: 0x000000D5 + "\x00O\x03\b\x00\x00\x00\xd6" + // 0x004F0308: 0x000000D6 + "\x00U\x03\x00\x00\x00\x00\xd9" + // 0x00550300: 0x000000D9 + "\x00U\x03\x01\x00\x00\x00\xda" + // 0x00550301: 0x000000DA + "\x00U\x03\x02\x00\x00\x00\xdb" + // 0x00550302: 0x000000DB + "\x00U\x03\b\x00\x00\x00\xdc" + // 0x00550308: 0x000000DC + "\x00Y\x03\x01\x00\x00\x00\xdd" + // 0x00590301: 0x000000DD + "\x00a\x03\x00\x00\x00\x00\xe0" + // 0x00610300: 0x000000E0 + "\x00a\x03\x01\x00\x00\x00\xe1" + // 0x00610301: 0x000000E1 + "\x00a\x03\x02\x00\x00\x00\xe2" + // 0x00610302: 0x000000E2 + "\x00a\x03\x03\x00\x00\x00\xe3" + // 0x00610303: 0x000000E3 + "\x00a\x03\b\x00\x00\x00\xe4" + // 0x00610308: 0x000000E4 + "\x00a\x03\n\x00\x00\x00\xe5" + // 0x0061030A: 0x000000E5 + "\x00c\x03'\x00\x00\x00\xe7" + // 0x00630327: 0x000000E7 + "\x00e\x03\x00\x00\x00\x00\xe8" + // 0x00650300: 0x000000E8 + "\x00e\x03\x01\x00\x00\x00\xe9" + // 0x00650301: 0x000000E9 + "\x00e\x03\x02\x00\x00\x00\xea" + // 0x00650302: 0x000000EA + "\x00e\x03\b\x00\x00\x00\xeb" + // 0x00650308: 0x000000EB + "\x00i\x03\x00\x00\x00\x00\xec" + // 0x00690300: 0x000000EC + "\x00i\x03\x01\x00\x00\x00\xed" + // 0x00690301: 0x000000ED + "\x00i\x03\x02\x00\x00\x00\xee" + // 0x00690302: 0x000000EE + "\x00i\x03\b\x00\x00\x00\xef" + // 0x00690308: 0x000000EF + "\x00n\x03\x03\x00\x00\x00\xf1" + // 0x006E0303: 0x000000F1 + "\x00o\x03\x00\x00\x00\x00\xf2" + // 0x006F0300: 0x000000F2 + "\x00o\x03\x01\x00\x00\x00\xf3" + // 0x006F0301: 0x000000F3 + "\x00o\x03\x02\x00\x00\x00\xf4" + // 0x006F0302: 0x000000F4 + "\x00o\x03\x03\x00\x00\x00\xf5" + // 0x006F0303: 0x000000F5 + "\x00o\x03\b\x00\x00\x00\xf6" + // 0x006F0308: 0x000000F6 + "\x00u\x03\x00\x00\x00\x00\xf9" + // 0x00750300: 0x000000F9 + "\x00u\x03\x01\x00\x00\x00\xfa" + // 0x00750301: 0x000000FA + "\x00u\x03\x02\x00\x00\x00\xfb" + // 0x00750302: 0x000000FB + "\x00u\x03\b\x00\x00\x00\xfc" + // 0x00750308: 0x000000FC + "\x00y\x03\x01\x00\x00\x00\xfd" + // 0x00790301: 0x000000FD + "\x00y\x03\b\x00\x00\x00\xff" + // 0x00790308: 0x000000FF + "\x00A\x03\x04\x00\x00\x01\x00" + // 0x00410304: 0x00000100 + "\x00a\x03\x04\x00\x00\x01\x01" + // 0x00610304: 0x00000101 + "\x00A\x03\x06\x00\x00\x01\x02" + // 0x00410306: 0x00000102 + "\x00a\x03\x06\x00\x00\x01\x03" + // 0x00610306: 0x00000103 + "\x00A\x03(\x00\x00\x01\x04" + // 0x00410328: 0x00000104 + "\x00a\x03(\x00\x00\x01\x05" + // 0x00610328: 0x00000105 + "\x00C\x03\x01\x00\x00\x01\x06" + // 0x00430301: 0x00000106 + "\x00c\x03\x01\x00\x00\x01\a" + // 0x00630301: 0x00000107 + "\x00C\x03\x02\x00\x00\x01\b" + // 0x00430302: 0x00000108 + "\x00c\x03\x02\x00\x00\x01\t" + // 0x00630302: 0x00000109 + "\x00C\x03\a\x00\x00\x01\n" + // 0x00430307: 0x0000010A + "\x00c\x03\a\x00\x00\x01\v" + // 0x00630307: 0x0000010B + "\x00C\x03\f\x00\x00\x01\f" + // 0x0043030C: 0x0000010C + "\x00c\x03\f\x00\x00\x01\r" + // 0x0063030C: 0x0000010D + "\x00D\x03\f\x00\x00\x01\x0e" + // 0x0044030C: 0x0000010E + "\x00d\x03\f\x00\x00\x01\x0f" + // 0x0064030C: 0x0000010F + "\x00E\x03\x04\x00\x00\x01\x12" + // 0x00450304: 0x00000112 + "\x00e\x03\x04\x00\x00\x01\x13" + // 0x00650304: 0x00000113 + "\x00E\x03\x06\x00\x00\x01\x14" + // 0x00450306: 0x00000114 + "\x00e\x03\x06\x00\x00\x01\x15" + // 0x00650306: 0x00000115 + "\x00E\x03\a\x00\x00\x01\x16" + // 0x00450307: 0x00000116 + "\x00e\x03\a\x00\x00\x01\x17" + // 0x00650307: 0x00000117 + "\x00E\x03(\x00\x00\x01\x18" + // 0x00450328: 0x00000118 + "\x00e\x03(\x00\x00\x01\x19" + // 0x00650328: 0x00000119 + "\x00E\x03\f\x00\x00\x01\x1a" + // 0x0045030C: 0x0000011A + "\x00e\x03\f\x00\x00\x01\x1b" + // 0x0065030C: 0x0000011B + "\x00G\x03\x02\x00\x00\x01\x1c" + // 0x00470302: 0x0000011C + "\x00g\x03\x02\x00\x00\x01\x1d" + // 0x00670302: 0x0000011D + "\x00G\x03\x06\x00\x00\x01\x1e" + // 0x00470306: 0x0000011E + "\x00g\x03\x06\x00\x00\x01\x1f" + // 0x00670306: 0x0000011F + "\x00G\x03\a\x00\x00\x01 " + // 0x00470307: 0x00000120 + "\x00g\x03\a\x00\x00\x01!" + // 0x00670307: 0x00000121 + "\x00G\x03'\x00\x00\x01\"" + // 0x00470327: 0x00000122 + "\x00g\x03'\x00\x00\x01#" + // 0x00670327: 0x00000123 + "\x00H\x03\x02\x00\x00\x01$" + // 0x00480302: 0x00000124 + "\x00h\x03\x02\x00\x00\x01%" + // 0x00680302: 0x00000125 + "\x00I\x03\x03\x00\x00\x01(" + // 0x00490303: 0x00000128 + "\x00i\x03\x03\x00\x00\x01)" + // 0x00690303: 0x00000129 + "\x00I\x03\x04\x00\x00\x01*" + // 0x00490304: 0x0000012A + "\x00i\x03\x04\x00\x00\x01+" + // 0x00690304: 0x0000012B + "\x00I\x03\x06\x00\x00\x01," + // 0x00490306: 0x0000012C + "\x00i\x03\x06\x00\x00\x01-" + // 0x00690306: 0x0000012D + "\x00I\x03(\x00\x00\x01." + // 0x00490328: 0x0000012E + "\x00i\x03(\x00\x00\x01/" + // 0x00690328: 0x0000012F + "\x00I\x03\a\x00\x00\x010" + // 0x00490307: 0x00000130 + "\x00J\x03\x02\x00\x00\x014" + // 0x004A0302: 0x00000134 + "\x00j\x03\x02\x00\x00\x015" + // 0x006A0302: 0x00000135 + "\x00K\x03'\x00\x00\x016" + // 0x004B0327: 0x00000136 + "\x00k\x03'\x00\x00\x017" + // 0x006B0327: 0x00000137 + "\x00L\x03\x01\x00\x00\x019" + // 0x004C0301: 0x00000139 + "\x00l\x03\x01\x00\x00\x01:" + // 0x006C0301: 0x0000013A + "\x00L\x03'\x00\x00\x01;" + // 0x004C0327: 0x0000013B + "\x00l\x03'\x00\x00\x01<" + // 0x006C0327: 0x0000013C + "\x00L\x03\f\x00\x00\x01=" + // 0x004C030C: 0x0000013D + "\x00l\x03\f\x00\x00\x01>" + // 0x006C030C: 0x0000013E + "\x00N\x03\x01\x00\x00\x01C" + // 0x004E0301: 0x00000143 + "\x00n\x03\x01\x00\x00\x01D" + // 0x006E0301: 0x00000144 + "\x00N\x03'\x00\x00\x01E" + // 0x004E0327: 0x00000145 + "\x00n\x03'\x00\x00\x01F" + // 0x006E0327: 0x00000146 + "\x00N\x03\f\x00\x00\x01G" + // 0x004E030C: 0x00000147 + "\x00n\x03\f\x00\x00\x01H" + // 0x006E030C: 0x00000148 + "\x00O\x03\x04\x00\x00\x01L" + // 0x004F0304: 0x0000014C + "\x00o\x03\x04\x00\x00\x01M" + // 0x006F0304: 0x0000014D + "\x00O\x03\x06\x00\x00\x01N" + // 0x004F0306: 0x0000014E + "\x00o\x03\x06\x00\x00\x01O" + // 0x006F0306: 0x0000014F + "\x00O\x03\v\x00\x00\x01P" + // 0x004F030B: 0x00000150 + "\x00o\x03\v\x00\x00\x01Q" + // 0x006F030B: 0x00000151 + "\x00R\x03\x01\x00\x00\x01T" + // 0x00520301: 0x00000154 + "\x00r\x03\x01\x00\x00\x01U" + // 0x00720301: 0x00000155 + "\x00R\x03'\x00\x00\x01V" + // 0x00520327: 0x00000156 + "\x00r\x03'\x00\x00\x01W" + // 0x00720327: 0x00000157 + "\x00R\x03\f\x00\x00\x01X" + // 0x0052030C: 0x00000158 + "\x00r\x03\f\x00\x00\x01Y" + // 0x0072030C: 0x00000159 + "\x00S\x03\x01\x00\x00\x01Z" + // 0x00530301: 0x0000015A + "\x00s\x03\x01\x00\x00\x01[" + // 0x00730301: 0x0000015B + "\x00S\x03\x02\x00\x00\x01\\" + // 0x00530302: 0x0000015C + "\x00s\x03\x02\x00\x00\x01]" + // 0x00730302: 0x0000015D + "\x00S\x03'\x00\x00\x01^" + // 0x00530327: 0x0000015E + "\x00s\x03'\x00\x00\x01_" + // 0x00730327: 0x0000015F + "\x00S\x03\f\x00\x00\x01`" + // 0x0053030C: 0x00000160 + "\x00s\x03\f\x00\x00\x01a" + // 0x0073030C: 0x00000161 + "\x00T\x03'\x00\x00\x01b" + // 0x00540327: 0x00000162 + "\x00t\x03'\x00\x00\x01c" + // 0x00740327: 0x00000163 + "\x00T\x03\f\x00\x00\x01d" + // 0x0054030C: 0x00000164 + "\x00t\x03\f\x00\x00\x01e" + // 0x0074030C: 0x00000165 + "\x00U\x03\x03\x00\x00\x01h" + // 0x00550303: 0x00000168 + "\x00u\x03\x03\x00\x00\x01i" + // 0x00750303: 0x00000169 + "\x00U\x03\x04\x00\x00\x01j" + // 0x00550304: 0x0000016A + "\x00u\x03\x04\x00\x00\x01k" + // 0x00750304: 0x0000016B + "\x00U\x03\x06\x00\x00\x01l" + // 0x00550306: 0x0000016C + "\x00u\x03\x06\x00\x00\x01m" + // 0x00750306: 0x0000016D + "\x00U\x03\n\x00\x00\x01n" + // 0x0055030A: 0x0000016E + "\x00u\x03\n\x00\x00\x01o" + // 0x0075030A: 0x0000016F + "\x00U\x03\v\x00\x00\x01p" + // 0x0055030B: 0x00000170 + "\x00u\x03\v\x00\x00\x01q" + // 0x0075030B: 0x00000171 + "\x00U\x03(\x00\x00\x01r" + // 0x00550328: 0x00000172 + "\x00u\x03(\x00\x00\x01s" + // 0x00750328: 0x00000173 + "\x00W\x03\x02\x00\x00\x01t" + // 0x00570302: 0x00000174 + "\x00w\x03\x02\x00\x00\x01u" + // 0x00770302: 0x00000175 + "\x00Y\x03\x02\x00\x00\x01v" + // 0x00590302: 0x00000176 + "\x00y\x03\x02\x00\x00\x01w" + // 0x00790302: 0x00000177 + "\x00Y\x03\b\x00\x00\x01x" + // 0x00590308: 0x00000178 + "\x00Z\x03\x01\x00\x00\x01y" + // 0x005A0301: 0x00000179 + "\x00z\x03\x01\x00\x00\x01z" + // 0x007A0301: 0x0000017A + "\x00Z\x03\a\x00\x00\x01{" + // 0x005A0307: 0x0000017B + "\x00z\x03\a\x00\x00\x01|" + // 0x007A0307: 0x0000017C + "\x00Z\x03\f\x00\x00\x01}" + // 0x005A030C: 0x0000017D + "\x00z\x03\f\x00\x00\x01~" + // 0x007A030C: 0x0000017E + "\x00O\x03\x1b\x00\x00\x01\xa0" + // 0x004F031B: 0x000001A0 + "\x00o\x03\x1b\x00\x00\x01\xa1" + // 0x006F031B: 0x000001A1 + "\x00U\x03\x1b\x00\x00\x01\xaf" + // 0x0055031B: 0x000001AF + "\x00u\x03\x1b\x00\x00\x01\xb0" + // 0x0075031B: 0x000001B0 + "\x00A\x03\f\x00\x00\x01\xcd" + // 0x0041030C: 0x000001CD + "\x00a\x03\f\x00\x00\x01\xce" + // 0x0061030C: 0x000001CE + "\x00I\x03\f\x00\x00\x01\xcf" + // 0x0049030C: 0x000001CF + "\x00i\x03\f\x00\x00\x01\xd0" + // 0x0069030C: 0x000001D0 + "\x00O\x03\f\x00\x00\x01\xd1" + // 0x004F030C: 0x000001D1 + "\x00o\x03\f\x00\x00\x01\xd2" + // 0x006F030C: 0x000001D2 + "\x00U\x03\f\x00\x00\x01\xd3" + // 0x0055030C: 0x000001D3 + "\x00u\x03\f\x00\x00\x01\xd4" + // 0x0075030C: 0x000001D4 + "\x00\xdc\x03\x04\x00\x00\x01\xd5" + // 0x00DC0304: 0x000001D5 + "\x00\xfc\x03\x04\x00\x00\x01\xd6" + // 0x00FC0304: 0x000001D6 + "\x00\xdc\x03\x01\x00\x00\x01\xd7" + // 0x00DC0301: 0x000001D7 + "\x00\xfc\x03\x01\x00\x00\x01\xd8" + // 0x00FC0301: 0x000001D8 + "\x00\xdc\x03\f\x00\x00\x01\xd9" + // 0x00DC030C: 0x000001D9 + "\x00\xfc\x03\f\x00\x00\x01\xda" + // 0x00FC030C: 0x000001DA + "\x00\xdc\x03\x00\x00\x00\x01\xdb" + // 0x00DC0300: 0x000001DB + "\x00\xfc\x03\x00\x00\x00\x01\xdc" + // 0x00FC0300: 0x000001DC + "\x00\xc4\x03\x04\x00\x00\x01\xde" + // 0x00C40304: 0x000001DE + "\x00\xe4\x03\x04\x00\x00\x01\xdf" + // 0x00E40304: 0x000001DF + "\x02&\x03\x04\x00\x00\x01\xe0" + // 0x02260304: 0x000001E0 + "\x02'\x03\x04\x00\x00\x01\xe1" + // 0x02270304: 0x000001E1 + "\x00\xc6\x03\x04\x00\x00\x01\xe2" + // 0x00C60304: 0x000001E2 + "\x00\xe6\x03\x04\x00\x00\x01\xe3" + // 0x00E60304: 0x000001E3 + "\x00G\x03\f\x00\x00\x01\xe6" + // 0x0047030C: 0x000001E6 + "\x00g\x03\f\x00\x00\x01\xe7" + // 0x0067030C: 0x000001E7 + "\x00K\x03\f\x00\x00\x01\xe8" + // 0x004B030C: 0x000001E8 + "\x00k\x03\f\x00\x00\x01\xe9" + // 0x006B030C: 0x000001E9 + "\x00O\x03(\x00\x00\x01\xea" + // 0x004F0328: 0x000001EA + "\x00o\x03(\x00\x00\x01\xeb" + // 0x006F0328: 0x000001EB + "\x01\xea\x03\x04\x00\x00\x01\xec" + // 0x01EA0304: 0x000001EC + "\x01\xeb\x03\x04\x00\x00\x01\xed" + // 0x01EB0304: 0x000001ED + "\x01\xb7\x03\f\x00\x00\x01\xee" + // 0x01B7030C: 0x000001EE + "\x02\x92\x03\f\x00\x00\x01\xef" + // 0x0292030C: 0x000001EF + "\x00j\x03\f\x00\x00\x01\xf0" + // 0x006A030C: 0x000001F0 + "\x00G\x03\x01\x00\x00\x01\xf4" + // 0x00470301: 0x000001F4 + "\x00g\x03\x01\x00\x00\x01\xf5" + // 0x00670301: 0x000001F5 + "\x00N\x03\x00\x00\x00\x01\xf8" + // 0x004E0300: 0x000001F8 + "\x00n\x03\x00\x00\x00\x01\xf9" + // 0x006E0300: 0x000001F9 + "\x00\xc5\x03\x01\x00\x00\x01\xfa" + // 0x00C50301: 0x000001FA + "\x00\xe5\x03\x01\x00\x00\x01\xfb" + // 0x00E50301: 0x000001FB + "\x00\xc6\x03\x01\x00\x00\x01\xfc" + // 0x00C60301: 0x000001FC + "\x00\xe6\x03\x01\x00\x00\x01\xfd" + // 0x00E60301: 0x000001FD + "\x00\xd8\x03\x01\x00\x00\x01\xfe" + // 0x00D80301: 0x000001FE + "\x00\xf8\x03\x01\x00\x00\x01\xff" + // 0x00F80301: 0x000001FF + "\x00A\x03\x0f\x00\x00\x02\x00" + // 0x0041030F: 0x00000200 + "\x00a\x03\x0f\x00\x00\x02\x01" + // 0x0061030F: 0x00000201 + "\x00A\x03\x11\x00\x00\x02\x02" + // 0x00410311: 0x00000202 + "\x00a\x03\x11\x00\x00\x02\x03" + // 0x00610311: 0x00000203 + "\x00E\x03\x0f\x00\x00\x02\x04" + // 0x0045030F: 0x00000204 + "\x00e\x03\x0f\x00\x00\x02\x05" + // 0x0065030F: 0x00000205 + "\x00E\x03\x11\x00\x00\x02\x06" + // 0x00450311: 0x00000206 + "\x00e\x03\x11\x00\x00\x02\a" + // 0x00650311: 0x00000207 + "\x00I\x03\x0f\x00\x00\x02\b" + // 0x0049030F: 0x00000208 + "\x00i\x03\x0f\x00\x00\x02\t" + // 0x0069030F: 0x00000209 + "\x00I\x03\x11\x00\x00\x02\n" + // 0x00490311: 0x0000020A + "\x00i\x03\x11\x00\x00\x02\v" + // 0x00690311: 0x0000020B + "\x00O\x03\x0f\x00\x00\x02\f" + // 0x004F030F: 0x0000020C + "\x00o\x03\x0f\x00\x00\x02\r" + // 0x006F030F: 0x0000020D + "\x00O\x03\x11\x00\x00\x02\x0e" + // 0x004F0311: 0x0000020E + "\x00o\x03\x11\x00\x00\x02\x0f" + // 0x006F0311: 0x0000020F + "\x00R\x03\x0f\x00\x00\x02\x10" + // 0x0052030F: 0x00000210 + "\x00r\x03\x0f\x00\x00\x02\x11" + // 0x0072030F: 0x00000211 + "\x00R\x03\x11\x00\x00\x02\x12" + // 0x00520311: 0x00000212 + "\x00r\x03\x11\x00\x00\x02\x13" + // 0x00720311: 0x00000213 + "\x00U\x03\x0f\x00\x00\x02\x14" + // 0x0055030F: 0x00000214 + "\x00u\x03\x0f\x00\x00\x02\x15" + // 0x0075030F: 0x00000215 + "\x00U\x03\x11\x00\x00\x02\x16" + // 0x00550311: 0x00000216 + "\x00u\x03\x11\x00\x00\x02\x17" + // 0x00750311: 0x00000217 + "\x00S\x03&\x00\x00\x02\x18" + // 0x00530326: 0x00000218 + "\x00s\x03&\x00\x00\x02\x19" + // 0x00730326: 0x00000219 + "\x00T\x03&\x00\x00\x02\x1a" + // 0x00540326: 0x0000021A + "\x00t\x03&\x00\x00\x02\x1b" + // 0x00740326: 0x0000021B + "\x00H\x03\f\x00\x00\x02\x1e" + // 0x0048030C: 0x0000021E + "\x00h\x03\f\x00\x00\x02\x1f" + // 0x0068030C: 0x0000021F + "\x00A\x03\a\x00\x00\x02&" + // 0x00410307: 0x00000226 + "\x00a\x03\a\x00\x00\x02'" + // 0x00610307: 0x00000227 + "\x00E\x03'\x00\x00\x02(" + // 0x00450327: 0x00000228 + "\x00e\x03'\x00\x00\x02)" + // 0x00650327: 0x00000229 + "\x00\xd6\x03\x04\x00\x00\x02*" + // 0x00D60304: 0x0000022A + "\x00\xf6\x03\x04\x00\x00\x02+" + // 0x00F60304: 0x0000022B + "\x00\xd5\x03\x04\x00\x00\x02," + // 0x00D50304: 0x0000022C + "\x00\xf5\x03\x04\x00\x00\x02-" + // 0x00F50304: 0x0000022D + "\x00O\x03\a\x00\x00\x02." + // 0x004F0307: 0x0000022E + "\x00o\x03\a\x00\x00\x02/" + // 0x006F0307: 0x0000022F + "\x02.\x03\x04\x00\x00\x020" + // 0x022E0304: 0x00000230 + "\x02/\x03\x04\x00\x00\x021" + // 0x022F0304: 0x00000231 + "\x00Y\x03\x04\x00\x00\x022" + // 0x00590304: 0x00000232 + "\x00y\x03\x04\x00\x00\x023" + // 0x00790304: 0x00000233 + "\x00\xa8\x03\x01\x00\x00\x03\x85" + // 0x00A80301: 0x00000385 + "\x03\x91\x03\x01\x00\x00\x03\x86" + // 0x03910301: 0x00000386 + "\x03\x95\x03\x01\x00\x00\x03\x88" + // 0x03950301: 0x00000388 + "\x03\x97\x03\x01\x00\x00\x03\x89" + // 0x03970301: 0x00000389 + "\x03\x99\x03\x01\x00\x00\x03\x8a" + // 0x03990301: 0x0000038A + "\x03\x9f\x03\x01\x00\x00\x03\x8c" + // 0x039F0301: 0x0000038C + "\x03\xa5\x03\x01\x00\x00\x03\x8e" + // 0x03A50301: 0x0000038E + "\x03\xa9\x03\x01\x00\x00\x03\x8f" + // 0x03A90301: 0x0000038F + "\x03\xca\x03\x01\x00\x00\x03\x90" + // 0x03CA0301: 0x00000390 + "\x03\x99\x03\b\x00\x00\x03\xaa" + // 0x03990308: 0x000003AA + "\x03\xa5\x03\b\x00\x00\x03\xab" + // 0x03A50308: 0x000003AB + "\x03\xb1\x03\x01\x00\x00\x03\xac" + // 0x03B10301: 0x000003AC + "\x03\xb5\x03\x01\x00\x00\x03\xad" + // 0x03B50301: 0x000003AD + "\x03\xb7\x03\x01\x00\x00\x03\xae" + // 0x03B70301: 0x000003AE + "\x03\xb9\x03\x01\x00\x00\x03\xaf" + // 0x03B90301: 0x000003AF + "\x03\xcb\x03\x01\x00\x00\x03\xb0" + // 0x03CB0301: 0x000003B0 + "\x03\xb9\x03\b\x00\x00\x03\xca" + // 0x03B90308: 0x000003CA + "\x03\xc5\x03\b\x00\x00\x03\xcb" + // 0x03C50308: 0x000003CB + "\x03\xbf\x03\x01\x00\x00\x03\xcc" + // 0x03BF0301: 0x000003CC + "\x03\xc5\x03\x01\x00\x00\x03\xcd" + // 0x03C50301: 0x000003CD + "\x03\xc9\x03\x01\x00\x00\x03\xce" + // 0x03C90301: 0x000003CE + "\x03\xd2\x03\x01\x00\x00\x03\xd3" + // 0x03D20301: 0x000003D3 + "\x03\xd2\x03\b\x00\x00\x03\xd4" + // 0x03D20308: 0x000003D4 + "\x04\x15\x03\x00\x00\x00\x04\x00" + // 0x04150300: 0x00000400 + "\x04\x15\x03\b\x00\x00\x04\x01" + // 0x04150308: 0x00000401 + "\x04\x13\x03\x01\x00\x00\x04\x03" + // 0x04130301: 0x00000403 + "\x04\x06\x03\b\x00\x00\x04\a" + // 0x04060308: 0x00000407 + "\x04\x1a\x03\x01\x00\x00\x04\f" + // 0x041A0301: 0x0000040C + "\x04\x18\x03\x00\x00\x00\x04\r" + // 0x04180300: 0x0000040D + "\x04#\x03\x06\x00\x00\x04\x0e" + // 0x04230306: 0x0000040E + "\x04\x18\x03\x06\x00\x00\x04\x19" + // 0x04180306: 0x00000419 + "\x048\x03\x06\x00\x00\x049" + // 0x04380306: 0x00000439 + "\x045\x03\x00\x00\x00\x04P" + // 0x04350300: 0x00000450 + "\x045\x03\b\x00\x00\x04Q" + // 0x04350308: 0x00000451 + "\x043\x03\x01\x00\x00\x04S" + // 0x04330301: 0x00000453 + "\x04V\x03\b\x00\x00\x04W" + // 0x04560308: 0x00000457 + "\x04:\x03\x01\x00\x00\x04\\" + // 0x043A0301: 0x0000045C + "\x048\x03\x00\x00\x00\x04]" + // 0x04380300: 0x0000045D + "\x04C\x03\x06\x00\x00\x04^" + // 0x04430306: 0x0000045E + "\x04t\x03\x0f\x00\x00\x04v" + // 0x0474030F: 0x00000476 + "\x04u\x03\x0f\x00\x00\x04w" + // 0x0475030F: 0x00000477 + "\x04\x16\x03\x06\x00\x00\x04\xc1" + // 0x04160306: 0x000004C1 + "\x046\x03\x06\x00\x00\x04\xc2" + // 0x04360306: 0x000004C2 + "\x04\x10\x03\x06\x00\x00\x04\xd0" + // 0x04100306: 0x000004D0 + "\x040\x03\x06\x00\x00\x04\xd1" + // 0x04300306: 0x000004D1 + "\x04\x10\x03\b\x00\x00\x04\xd2" + // 0x04100308: 0x000004D2 + "\x040\x03\b\x00\x00\x04\xd3" + // 0x04300308: 0x000004D3 + "\x04\x15\x03\x06\x00\x00\x04\xd6" + // 0x04150306: 0x000004D6 + "\x045\x03\x06\x00\x00\x04\xd7" + // 0x04350306: 0x000004D7 + "\x04\xd8\x03\b\x00\x00\x04\xda" + // 0x04D80308: 0x000004DA + "\x04\xd9\x03\b\x00\x00\x04\xdb" + // 0x04D90308: 0x000004DB + "\x04\x16\x03\b\x00\x00\x04\xdc" + // 0x04160308: 0x000004DC + "\x046\x03\b\x00\x00\x04\xdd" + // 0x04360308: 0x000004DD + "\x04\x17\x03\b\x00\x00\x04\xde" + // 0x04170308: 0x000004DE + "\x047\x03\b\x00\x00\x04\xdf" + // 0x04370308: 0x000004DF + "\x04\x18\x03\x04\x00\x00\x04\xe2" + // 0x04180304: 0x000004E2 + "\x048\x03\x04\x00\x00\x04\xe3" + // 0x04380304: 0x000004E3 + "\x04\x18\x03\b\x00\x00\x04\xe4" + // 0x04180308: 0x000004E4 + "\x048\x03\b\x00\x00\x04\xe5" + // 0x04380308: 0x000004E5 + "\x04\x1e\x03\b\x00\x00\x04\xe6" + // 0x041E0308: 0x000004E6 + "\x04>\x03\b\x00\x00\x04\xe7" + // 0x043E0308: 0x000004E7 + "\x04\xe8\x03\b\x00\x00\x04\xea" + // 0x04E80308: 0x000004EA + "\x04\xe9\x03\b\x00\x00\x04\xeb" + // 0x04E90308: 0x000004EB + "\x04-\x03\b\x00\x00\x04\xec" + // 0x042D0308: 0x000004EC + "\x04M\x03\b\x00\x00\x04\xed" + // 0x044D0308: 0x000004ED + "\x04#\x03\x04\x00\x00\x04\xee" + // 0x04230304: 0x000004EE + "\x04C\x03\x04\x00\x00\x04\xef" + // 0x04430304: 0x000004EF + "\x04#\x03\b\x00\x00\x04\xf0" + // 0x04230308: 0x000004F0 + "\x04C\x03\b\x00\x00\x04\xf1" + // 0x04430308: 0x000004F1 + "\x04#\x03\v\x00\x00\x04\xf2" + // 0x0423030B: 0x000004F2 + "\x04C\x03\v\x00\x00\x04\xf3" + // 0x0443030B: 0x000004F3 + "\x04'\x03\b\x00\x00\x04\xf4" + // 0x04270308: 0x000004F4 + "\x04G\x03\b\x00\x00\x04\xf5" + // 0x04470308: 0x000004F5 + "\x04+\x03\b\x00\x00\x04\xf8" + // 0x042B0308: 0x000004F8 + "\x04K\x03\b\x00\x00\x04\xf9" + // 0x044B0308: 0x000004F9 + "\x06'\x06S\x00\x00\x06\"" + // 0x06270653: 0x00000622 + "\x06'\x06T\x00\x00\x06#" + // 0x06270654: 0x00000623 + "\x06H\x06T\x00\x00\x06$" + // 0x06480654: 0x00000624 + "\x06'\x06U\x00\x00\x06%" + // 0x06270655: 0x00000625 + "\x06J\x06T\x00\x00\x06&" + // 0x064A0654: 0x00000626 + "\x06\xd5\x06T\x00\x00\x06\xc0" + // 0x06D50654: 0x000006C0 + "\x06\xc1\x06T\x00\x00\x06\xc2" + // 0x06C10654: 0x000006C2 + "\x06\xd2\x06T\x00\x00\x06\xd3" + // 0x06D20654: 0x000006D3 + "\t(\t<\x00\x00\t)" + // 0x0928093C: 0x00000929 + "\t0\t<\x00\x00\t1" + // 0x0930093C: 0x00000931 + "\t3\t<\x00\x00\t4" + // 0x0933093C: 0x00000934 + "\t\xc7\t\xbe\x00\x00\t\xcb" + // 0x09C709BE: 0x000009CB + "\t\xc7\t\xd7\x00\x00\t\xcc" + // 0x09C709D7: 0x000009CC + "\vG\vV\x00\x00\vH" + // 0x0B470B56: 0x00000B48 + "\vG\v>\x00\x00\vK" + // 0x0B470B3E: 0x00000B4B + "\vG\vW\x00\x00\vL" + // 0x0B470B57: 0x00000B4C + "\v\x92\v\xd7\x00\x00\v\x94" + // 0x0B920BD7: 0x00000B94 + "\v\xc6\v\xbe\x00\x00\v\xca" + // 0x0BC60BBE: 0x00000BCA + "\v\xc7\v\xbe\x00\x00\v\xcb" + // 0x0BC70BBE: 0x00000BCB + "\v\xc6\v\xd7\x00\x00\v\xcc" + // 0x0BC60BD7: 0x00000BCC + "\fF\fV\x00\x00\fH" + // 0x0C460C56: 0x00000C48 + "\f\xbf\f\xd5\x00\x00\f\xc0" + // 0x0CBF0CD5: 0x00000CC0 + "\f\xc6\f\xd5\x00\x00\f\xc7" + // 0x0CC60CD5: 0x00000CC7 + "\f\xc6\f\xd6\x00\x00\f\xc8" + // 0x0CC60CD6: 0x00000CC8 + "\f\xc6\f\xc2\x00\x00\f\xca" + // 0x0CC60CC2: 0x00000CCA + "\f\xca\f\xd5\x00\x00\f\xcb" + // 0x0CCA0CD5: 0x00000CCB + "\rF\r>\x00\x00\rJ" + // 0x0D460D3E: 0x00000D4A + "\rG\r>\x00\x00\rK" + // 0x0D470D3E: 0x00000D4B + "\rF\rW\x00\x00\rL" + // 0x0D460D57: 0x00000D4C + "\r\xd9\r\xca\x00\x00\r\xda" + // 0x0DD90DCA: 0x00000DDA + "\r\xd9\r\xcf\x00\x00\r\xdc" + // 0x0DD90DCF: 0x00000DDC + "\r\xdc\r\xca\x00\x00\r\xdd" + // 0x0DDC0DCA: 0x00000DDD + "\r\xd9\r\xdf\x00\x00\r\xde" + // 0x0DD90DDF: 0x00000DDE + "\x10%\x10.\x00\x00\x10&" + // 0x1025102E: 0x00001026 + "\x1b\x05\x1b5\x00\x00\x1b\x06" + // 0x1B051B35: 0x00001B06 + "\x1b\a\x1b5\x00\x00\x1b\b" + // 0x1B071B35: 0x00001B08 + "\x1b\t\x1b5\x00\x00\x1b\n" + // 0x1B091B35: 0x00001B0A + "\x1b\v\x1b5\x00\x00\x1b\f" + // 0x1B0B1B35: 0x00001B0C + "\x1b\r\x1b5\x00\x00\x1b\x0e" + // 0x1B0D1B35: 0x00001B0E + "\x1b\x11\x1b5\x00\x00\x1b\x12" + // 0x1B111B35: 0x00001B12 + "\x1b:\x1b5\x00\x00\x1b;" + // 0x1B3A1B35: 0x00001B3B + "\x1b<\x1b5\x00\x00\x1b=" + // 0x1B3C1B35: 0x00001B3D + "\x1b>\x1b5\x00\x00\x1b@" + // 0x1B3E1B35: 0x00001B40 + "\x1b?\x1b5\x00\x00\x1bA" + // 0x1B3F1B35: 0x00001B41 + "\x1bB\x1b5\x00\x00\x1bC" + // 0x1B421B35: 0x00001B43 + "\x00A\x03%\x00\x00\x1e\x00" + // 0x00410325: 0x00001E00 + "\x00a\x03%\x00\x00\x1e\x01" + // 0x00610325: 0x00001E01 + "\x00B\x03\a\x00\x00\x1e\x02" + // 0x00420307: 0x00001E02 + "\x00b\x03\a\x00\x00\x1e\x03" + // 0x00620307: 0x00001E03 + "\x00B\x03#\x00\x00\x1e\x04" + // 0x00420323: 0x00001E04 + "\x00b\x03#\x00\x00\x1e\x05" + // 0x00620323: 0x00001E05 + "\x00B\x031\x00\x00\x1e\x06" + // 0x00420331: 0x00001E06 + "\x00b\x031\x00\x00\x1e\a" + // 0x00620331: 0x00001E07 + "\x00\xc7\x03\x01\x00\x00\x1e\b" + // 0x00C70301: 0x00001E08 + "\x00\xe7\x03\x01\x00\x00\x1e\t" + // 0x00E70301: 0x00001E09 + "\x00D\x03\a\x00\x00\x1e\n" + // 0x00440307: 0x00001E0A + "\x00d\x03\a\x00\x00\x1e\v" + // 0x00640307: 0x00001E0B + "\x00D\x03#\x00\x00\x1e\f" + // 0x00440323: 0x00001E0C + "\x00d\x03#\x00\x00\x1e\r" + // 0x00640323: 0x00001E0D + "\x00D\x031\x00\x00\x1e\x0e" + // 0x00440331: 0x00001E0E + "\x00d\x031\x00\x00\x1e\x0f" + // 0x00640331: 0x00001E0F + "\x00D\x03'\x00\x00\x1e\x10" + // 0x00440327: 0x00001E10 + "\x00d\x03'\x00\x00\x1e\x11" + // 0x00640327: 0x00001E11 + "\x00D\x03-\x00\x00\x1e\x12" + // 0x0044032D: 0x00001E12 + "\x00d\x03-\x00\x00\x1e\x13" + // 0x0064032D: 0x00001E13 + "\x01\x12\x03\x00\x00\x00\x1e\x14" + // 0x01120300: 0x00001E14 + "\x01\x13\x03\x00\x00\x00\x1e\x15" + // 0x01130300: 0x00001E15 + "\x01\x12\x03\x01\x00\x00\x1e\x16" + // 0x01120301: 0x00001E16 + "\x01\x13\x03\x01\x00\x00\x1e\x17" + // 0x01130301: 0x00001E17 + "\x00E\x03-\x00\x00\x1e\x18" + // 0x0045032D: 0x00001E18 + "\x00e\x03-\x00\x00\x1e\x19" + // 0x0065032D: 0x00001E19 + "\x00E\x030\x00\x00\x1e\x1a" + // 0x00450330: 0x00001E1A + "\x00e\x030\x00\x00\x1e\x1b" + // 0x00650330: 0x00001E1B + "\x02(\x03\x06\x00\x00\x1e\x1c" + // 0x02280306: 0x00001E1C + "\x02)\x03\x06\x00\x00\x1e\x1d" + // 0x02290306: 0x00001E1D + "\x00F\x03\a\x00\x00\x1e\x1e" + // 0x00460307: 0x00001E1E + "\x00f\x03\a\x00\x00\x1e\x1f" + // 0x00660307: 0x00001E1F + "\x00G\x03\x04\x00\x00\x1e " + // 0x00470304: 0x00001E20 + "\x00g\x03\x04\x00\x00\x1e!" + // 0x00670304: 0x00001E21 + "\x00H\x03\a\x00\x00\x1e\"" + // 0x00480307: 0x00001E22 + "\x00h\x03\a\x00\x00\x1e#" + // 0x00680307: 0x00001E23 + "\x00H\x03#\x00\x00\x1e$" + // 0x00480323: 0x00001E24 + "\x00h\x03#\x00\x00\x1e%" + // 0x00680323: 0x00001E25 + "\x00H\x03\b\x00\x00\x1e&" + // 0x00480308: 0x00001E26 + "\x00h\x03\b\x00\x00\x1e'" + // 0x00680308: 0x00001E27 + "\x00H\x03'\x00\x00\x1e(" + // 0x00480327: 0x00001E28 + "\x00h\x03'\x00\x00\x1e)" + // 0x00680327: 0x00001E29 + "\x00H\x03.\x00\x00\x1e*" + // 0x0048032E: 0x00001E2A + "\x00h\x03.\x00\x00\x1e+" + // 0x0068032E: 0x00001E2B + "\x00I\x030\x00\x00\x1e," + // 0x00490330: 0x00001E2C + "\x00i\x030\x00\x00\x1e-" + // 0x00690330: 0x00001E2D + "\x00\xcf\x03\x01\x00\x00\x1e." + // 0x00CF0301: 0x00001E2E + "\x00\xef\x03\x01\x00\x00\x1e/" + // 0x00EF0301: 0x00001E2F + "\x00K\x03\x01\x00\x00\x1e0" + // 0x004B0301: 0x00001E30 + "\x00k\x03\x01\x00\x00\x1e1" + // 0x006B0301: 0x00001E31 + "\x00K\x03#\x00\x00\x1e2" + // 0x004B0323: 0x00001E32 + "\x00k\x03#\x00\x00\x1e3" + // 0x006B0323: 0x00001E33 + "\x00K\x031\x00\x00\x1e4" + // 0x004B0331: 0x00001E34 + "\x00k\x031\x00\x00\x1e5" + // 0x006B0331: 0x00001E35 + "\x00L\x03#\x00\x00\x1e6" + // 0x004C0323: 0x00001E36 + "\x00l\x03#\x00\x00\x1e7" + // 0x006C0323: 0x00001E37 + "\x1e6\x03\x04\x00\x00\x1e8" + // 0x1E360304: 0x00001E38 + "\x1e7\x03\x04\x00\x00\x1e9" + // 0x1E370304: 0x00001E39 + "\x00L\x031\x00\x00\x1e:" + // 0x004C0331: 0x00001E3A + "\x00l\x031\x00\x00\x1e;" + // 0x006C0331: 0x00001E3B + "\x00L\x03-\x00\x00\x1e<" + // 0x004C032D: 0x00001E3C + "\x00l\x03-\x00\x00\x1e=" + // 0x006C032D: 0x00001E3D + "\x00M\x03\x01\x00\x00\x1e>" + // 0x004D0301: 0x00001E3E + "\x00m\x03\x01\x00\x00\x1e?" + // 0x006D0301: 0x00001E3F + "\x00M\x03\a\x00\x00\x1e@" + // 0x004D0307: 0x00001E40 + "\x00m\x03\a\x00\x00\x1eA" + // 0x006D0307: 0x00001E41 + "\x00M\x03#\x00\x00\x1eB" + // 0x004D0323: 0x00001E42 + "\x00m\x03#\x00\x00\x1eC" + // 0x006D0323: 0x00001E43 + "\x00N\x03\a\x00\x00\x1eD" + // 0x004E0307: 0x00001E44 + "\x00n\x03\a\x00\x00\x1eE" + // 0x006E0307: 0x00001E45 + "\x00N\x03#\x00\x00\x1eF" + // 0x004E0323: 0x00001E46 + "\x00n\x03#\x00\x00\x1eG" + // 0x006E0323: 0x00001E47 + "\x00N\x031\x00\x00\x1eH" + // 0x004E0331: 0x00001E48 + "\x00n\x031\x00\x00\x1eI" + // 0x006E0331: 0x00001E49 + "\x00N\x03-\x00\x00\x1eJ" + // 0x004E032D: 0x00001E4A + "\x00n\x03-\x00\x00\x1eK" + // 0x006E032D: 0x00001E4B + "\x00\xd5\x03\x01\x00\x00\x1eL" + // 0x00D50301: 0x00001E4C + "\x00\xf5\x03\x01\x00\x00\x1eM" + // 0x00F50301: 0x00001E4D + "\x00\xd5\x03\b\x00\x00\x1eN" + // 0x00D50308: 0x00001E4E + "\x00\xf5\x03\b\x00\x00\x1eO" + // 0x00F50308: 0x00001E4F + "\x01L\x03\x00\x00\x00\x1eP" + // 0x014C0300: 0x00001E50 + "\x01M\x03\x00\x00\x00\x1eQ" + // 0x014D0300: 0x00001E51 + "\x01L\x03\x01\x00\x00\x1eR" + // 0x014C0301: 0x00001E52 + "\x01M\x03\x01\x00\x00\x1eS" + // 0x014D0301: 0x00001E53 + "\x00P\x03\x01\x00\x00\x1eT" + // 0x00500301: 0x00001E54 + "\x00p\x03\x01\x00\x00\x1eU" + // 0x00700301: 0x00001E55 + "\x00P\x03\a\x00\x00\x1eV" + // 0x00500307: 0x00001E56 + "\x00p\x03\a\x00\x00\x1eW" + // 0x00700307: 0x00001E57 + "\x00R\x03\a\x00\x00\x1eX" + // 0x00520307: 0x00001E58 + "\x00r\x03\a\x00\x00\x1eY" + // 0x00720307: 0x00001E59 + "\x00R\x03#\x00\x00\x1eZ" + // 0x00520323: 0x00001E5A + "\x00r\x03#\x00\x00\x1e[" + // 0x00720323: 0x00001E5B + "\x1eZ\x03\x04\x00\x00\x1e\\" + // 0x1E5A0304: 0x00001E5C + "\x1e[\x03\x04\x00\x00\x1e]" + // 0x1E5B0304: 0x00001E5D + "\x00R\x031\x00\x00\x1e^" + // 0x00520331: 0x00001E5E + "\x00r\x031\x00\x00\x1e_" + // 0x00720331: 0x00001E5F + "\x00S\x03\a\x00\x00\x1e`" + // 0x00530307: 0x00001E60 + "\x00s\x03\a\x00\x00\x1ea" + // 0x00730307: 0x00001E61 + "\x00S\x03#\x00\x00\x1eb" + // 0x00530323: 0x00001E62 + "\x00s\x03#\x00\x00\x1ec" + // 0x00730323: 0x00001E63 + "\x01Z\x03\a\x00\x00\x1ed" + // 0x015A0307: 0x00001E64 + "\x01[\x03\a\x00\x00\x1ee" + // 0x015B0307: 0x00001E65 + "\x01`\x03\a\x00\x00\x1ef" + // 0x01600307: 0x00001E66 + "\x01a\x03\a\x00\x00\x1eg" + // 0x01610307: 0x00001E67 + "\x1eb\x03\a\x00\x00\x1eh" + // 0x1E620307: 0x00001E68 + "\x1ec\x03\a\x00\x00\x1ei" + // 0x1E630307: 0x00001E69 + "\x00T\x03\a\x00\x00\x1ej" + // 0x00540307: 0x00001E6A + "\x00t\x03\a\x00\x00\x1ek" + // 0x00740307: 0x00001E6B + "\x00T\x03#\x00\x00\x1el" + // 0x00540323: 0x00001E6C + "\x00t\x03#\x00\x00\x1em" + // 0x00740323: 0x00001E6D + "\x00T\x031\x00\x00\x1en" + // 0x00540331: 0x00001E6E + "\x00t\x031\x00\x00\x1eo" + // 0x00740331: 0x00001E6F + "\x00T\x03-\x00\x00\x1ep" + // 0x0054032D: 0x00001E70 + "\x00t\x03-\x00\x00\x1eq" + // 0x0074032D: 0x00001E71 + "\x00U\x03$\x00\x00\x1er" + // 0x00550324: 0x00001E72 + "\x00u\x03$\x00\x00\x1es" + // 0x00750324: 0x00001E73 + "\x00U\x030\x00\x00\x1et" + // 0x00550330: 0x00001E74 + "\x00u\x030\x00\x00\x1eu" + // 0x00750330: 0x00001E75 + "\x00U\x03-\x00\x00\x1ev" + // 0x0055032D: 0x00001E76 + "\x00u\x03-\x00\x00\x1ew" + // 0x0075032D: 0x00001E77 + "\x01h\x03\x01\x00\x00\x1ex" + // 0x01680301: 0x00001E78 + "\x01i\x03\x01\x00\x00\x1ey" + // 0x01690301: 0x00001E79 + "\x01j\x03\b\x00\x00\x1ez" + // 0x016A0308: 0x00001E7A + "\x01k\x03\b\x00\x00\x1e{" + // 0x016B0308: 0x00001E7B + "\x00V\x03\x03\x00\x00\x1e|" + // 0x00560303: 0x00001E7C + "\x00v\x03\x03\x00\x00\x1e}" + // 0x00760303: 0x00001E7D + "\x00V\x03#\x00\x00\x1e~" + // 0x00560323: 0x00001E7E + "\x00v\x03#\x00\x00\x1e\u007f" + // 0x00760323: 0x00001E7F + "\x00W\x03\x00\x00\x00\x1e\x80" + // 0x00570300: 0x00001E80 + "\x00w\x03\x00\x00\x00\x1e\x81" + // 0x00770300: 0x00001E81 + "\x00W\x03\x01\x00\x00\x1e\x82" + // 0x00570301: 0x00001E82 + "\x00w\x03\x01\x00\x00\x1e\x83" + // 0x00770301: 0x00001E83 + "\x00W\x03\b\x00\x00\x1e\x84" + // 0x00570308: 0x00001E84 + "\x00w\x03\b\x00\x00\x1e\x85" + // 0x00770308: 0x00001E85 + "\x00W\x03\a\x00\x00\x1e\x86" + // 0x00570307: 0x00001E86 + "\x00w\x03\a\x00\x00\x1e\x87" + // 0x00770307: 0x00001E87 + "\x00W\x03#\x00\x00\x1e\x88" + // 0x00570323: 0x00001E88 + "\x00w\x03#\x00\x00\x1e\x89" + // 0x00770323: 0x00001E89 + "\x00X\x03\a\x00\x00\x1e\x8a" + // 0x00580307: 0x00001E8A + "\x00x\x03\a\x00\x00\x1e\x8b" + // 0x00780307: 0x00001E8B + "\x00X\x03\b\x00\x00\x1e\x8c" + // 0x00580308: 0x00001E8C + "\x00x\x03\b\x00\x00\x1e\x8d" + // 0x00780308: 0x00001E8D + "\x00Y\x03\a\x00\x00\x1e\x8e" + // 0x00590307: 0x00001E8E + "\x00y\x03\a\x00\x00\x1e\x8f" + // 0x00790307: 0x00001E8F + "\x00Z\x03\x02\x00\x00\x1e\x90" + // 0x005A0302: 0x00001E90 + "\x00z\x03\x02\x00\x00\x1e\x91" + // 0x007A0302: 0x00001E91 + "\x00Z\x03#\x00\x00\x1e\x92" + // 0x005A0323: 0x00001E92 + "\x00z\x03#\x00\x00\x1e\x93" + // 0x007A0323: 0x00001E93 + "\x00Z\x031\x00\x00\x1e\x94" + // 0x005A0331: 0x00001E94 + "\x00z\x031\x00\x00\x1e\x95" + // 0x007A0331: 0x00001E95 + "\x00h\x031\x00\x00\x1e\x96" + // 0x00680331: 0x00001E96 + "\x00t\x03\b\x00\x00\x1e\x97" + // 0x00740308: 0x00001E97 + "\x00w\x03\n\x00\x00\x1e\x98" + // 0x0077030A: 0x00001E98 + "\x00y\x03\n\x00\x00\x1e\x99" + // 0x0079030A: 0x00001E99 + "\x01\u007f\x03\a\x00\x00\x1e\x9b" + // 0x017F0307: 0x00001E9B + "\x00A\x03#\x00\x00\x1e\xa0" + // 0x00410323: 0x00001EA0 + "\x00a\x03#\x00\x00\x1e\xa1" + // 0x00610323: 0x00001EA1 + "\x00A\x03\t\x00\x00\x1e\xa2" + // 0x00410309: 0x00001EA2 + "\x00a\x03\t\x00\x00\x1e\xa3" + // 0x00610309: 0x00001EA3 + "\x00\xc2\x03\x01\x00\x00\x1e\xa4" + // 0x00C20301: 0x00001EA4 + "\x00\xe2\x03\x01\x00\x00\x1e\xa5" + // 0x00E20301: 0x00001EA5 + "\x00\xc2\x03\x00\x00\x00\x1e\xa6" + // 0x00C20300: 0x00001EA6 + "\x00\xe2\x03\x00\x00\x00\x1e\xa7" + // 0x00E20300: 0x00001EA7 + "\x00\xc2\x03\t\x00\x00\x1e\xa8" + // 0x00C20309: 0x00001EA8 + "\x00\xe2\x03\t\x00\x00\x1e\xa9" + // 0x00E20309: 0x00001EA9 + "\x00\xc2\x03\x03\x00\x00\x1e\xaa" + // 0x00C20303: 0x00001EAA + "\x00\xe2\x03\x03\x00\x00\x1e\xab" + // 0x00E20303: 0x00001EAB + "\x1e\xa0\x03\x02\x00\x00\x1e\xac" + // 0x1EA00302: 0x00001EAC + "\x1e\xa1\x03\x02\x00\x00\x1e\xad" + // 0x1EA10302: 0x00001EAD + "\x01\x02\x03\x01\x00\x00\x1e\xae" + // 0x01020301: 0x00001EAE + "\x01\x03\x03\x01\x00\x00\x1e\xaf" + // 0x01030301: 0x00001EAF + "\x01\x02\x03\x00\x00\x00\x1e\xb0" + // 0x01020300: 0x00001EB0 + "\x01\x03\x03\x00\x00\x00\x1e\xb1" + // 0x01030300: 0x00001EB1 + "\x01\x02\x03\t\x00\x00\x1e\xb2" + // 0x01020309: 0x00001EB2 + "\x01\x03\x03\t\x00\x00\x1e\xb3" + // 0x01030309: 0x00001EB3 + "\x01\x02\x03\x03\x00\x00\x1e\xb4" + // 0x01020303: 0x00001EB4 + "\x01\x03\x03\x03\x00\x00\x1e\xb5" + // 0x01030303: 0x00001EB5 + "\x1e\xa0\x03\x06\x00\x00\x1e\xb6" + // 0x1EA00306: 0x00001EB6 + "\x1e\xa1\x03\x06\x00\x00\x1e\xb7" + // 0x1EA10306: 0x00001EB7 + "\x00E\x03#\x00\x00\x1e\xb8" + // 0x00450323: 0x00001EB8 + "\x00e\x03#\x00\x00\x1e\xb9" + // 0x00650323: 0x00001EB9 + "\x00E\x03\t\x00\x00\x1e\xba" + // 0x00450309: 0x00001EBA + "\x00e\x03\t\x00\x00\x1e\xbb" + // 0x00650309: 0x00001EBB + "\x00E\x03\x03\x00\x00\x1e\xbc" + // 0x00450303: 0x00001EBC + "\x00e\x03\x03\x00\x00\x1e\xbd" + // 0x00650303: 0x00001EBD + "\x00\xca\x03\x01\x00\x00\x1e\xbe" + // 0x00CA0301: 0x00001EBE + "\x00\xea\x03\x01\x00\x00\x1e\xbf" + // 0x00EA0301: 0x00001EBF + "\x00\xca\x03\x00\x00\x00\x1e\xc0" + // 0x00CA0300: 0x00001EC0 + "\x00\xea\x03\x00\x00\x00\x1e\xc1" + // 0x00EA0300: 0x00001EC1 + "\x00\xca\x03\t\x00\x00\x1e\xc2" + // 0x00CA0309: 0x00001EC2 + "\x00\xea\x03\t\x00\x00\x1e\xc3" + // 0x00EA0309: 0x00001EC3 + "\x00\xca\x03\x03\x00\x00\x1e\xc4" + // 0x00CA0303: 0x00001EC4 + "\x00\xea\x03\x03\x00\x00\x1e\xc5" + // 0x00EA0303: 0x00001EC5 + "\x1e\xb8\x03\x02\x00\x00\x1e\xc6" + // 0x1EB80302: 0x00001EC6 + "\x1e\xb9\x03\x02\x00\x00\x1e\xc7" + // 0x1EB90302: 0x00001EC7 + "\x00I\x03\t\x00\x00\x1e\xc8" + // 0x00490309: 0x00001EC8 + "\x00i\x03\t\x00\x00\x1e\xc9" + // 0x00690309: 0x00001EC9 + "\x00I\x03#\x00\x00\x1e\xca" + // 0x00490323: 0x00001ECA + "\x00i\x03#\x00\x00\x1e\xcb" + // 0x00690323: 0x00001ECB + "\x00O\x03#\x00\x00\x1e\xcc" + // 0x004F0323: 0x00001ECC + "\x00o\x03#\x00\x00\x1e\xcd" + // 0x006F0323: 0x00001ECD + "\x00O\x03\t\x00\x00\x1e\xce" + // 0x004F0309: 0x00001ECE + "\x00o\x03\t\x00\x00\x1e\xcf" + // 0x006F0309: 0x00001ECF + "\x00\xd4\x03\x01\x00\x00\x1e\xd0" + // 0x00D40301: 0x00001ED0 + "\x00\xf4\x03\x01\x00\x00\x1e\xd1" + // 0x00F40301: 0x00001ED1 + "\x00\xd4\x03\x00\x00\x00\x1e\xd2" + // 0x00D40300: 0x00001ED2 + "\x00\xf4\x03\x00\x00\x00\x1e\xd3" + // 0x00F40300: 0x00001ED3 + "\x00\xd4\x03\t\x00\x00\x1e\xd4" + // 0x00D40309: 0x00001ED4 + "\x00\xf4\x03\t\x00\x00\x1e\xd5" + // 0x00F40309: 0x00001ED5 + "\x00\xd4\x03\x03\x00\x00\x1e\xd6" + // 0x00D40303: 0x00001ED6 + "\x00\xf4\x03\x03\x00\x00\x1e\xd7" + // 0x00F40303: 0x00001ED7 + "\x1e\xcc\x03\x02\x00\x00\x1e\xd8" + // 0x1ECC0302: 0x00001ED8 + "\x1e\xcd\x03\x02\x00\x00\x1e\xd9" + // 0x1ECD0302: 0x00001ED9 + "\x01\xa0\x03\x01\x00\x00\x1e\xda" + // 0x01A00301: 0x00001EDA + "\x01\xa1\x03\x01\x00\x00\x1e\xdb" + // 0x01A10301: 0x00001EDB + "\x01\xa0\x03\x00\x00\x00\x1e\xdc" + // 0x01A00300: 0x00001EDC + "\x01\xa1\x03\x00\x00\x00\x1e\xdd" + // 0x01A10300: 0x00001EDD + "\x01\xa0\x03\t\x00\x00\x1e\xde" + // 0x01A00309: 0x00001EDE + "\x01\xa1\x03\t\x00\x00\x1e\xdf" + // 0x01A10309: 0x00001EDF + "\x01\xa0\x03\x03\x00\x00\x1e\xe0" + // 0x01A00303: 0x00001EE0 + "\x01\xa1\x03\x03\x00\x00\x1e\xe1" + // 0x01A10303: 0x00001EE1 + "\x01\xa0\x03#\x00\x00\x1e\xe2" + // 0x01A00323: 0x00001EE2 + "\x01\xa1\x03#\x00\x00\x1e\xe3" + // 0x01A10323: 0x00001EE3 + "\x00U\x03#\x00\x00\x1e\xe4" + // 0x00550323: 0x00001EE4 + "\x00u\x03#\x00\x00\x1e\xe5" + // 0x00750323: 0x00001EE5 + "\x00U\x03\t\x00\x00\x1e\xe6" + // 0x00550309: 0x00001EE6 + "\x00u\x03\t\x00\x00\x1e\xe7" + // 0x00750309: 0x00001EE7 + "\x01\xaf\x03\x01\x00\x00\x1e\xe8" + // 0x01AF0301: 0x00001EE8 + "\x01\xb0\x03\x01\x00\x00\x1e\xe9" + // 0x01B00301: 0x00001EE9 + "\x01\xaf\x03\x00\x00\x00\x1e\xea" + // 0x01AF0300: 0x00001EEA + "\x01\xb0\x03\x00\x00\x00\x1e\xeb" + // 0x01B00300: 0x00001EEB + "\x01\xaf\x03\t\x00\x00\x1e\xec" + // 0x01AF0309: 0x00001EEC + "\x01\xb0\x03\t\x00\x00\x1e\xed" + // 0x01B00309: 0x00001EED + "\x01\xaf\x03\x03\x00\x00\x1e\xee" + // 0x01AF0303: 0x00001EEE + "\x01\xb0\x03\x03\x00\x00\x1e\xef" + // 0x01B00303: 0x00001EEF + "\x01\xaf\x03#\x00\x00\x1e\xf0" + // 0x01AF0323: 0x00001EF0 + "\x01\xb0\x03#\x00\x00\x1e\xf1" + // 0x01B00323: 0x00001EF1 + "\x00Y\x03\x00\x00\x00\x1e\xf2" + // 0x00590300: 0x00001EF2 + "\x00y\x03\x00\x00\x00\x1e\xf3" + // 0x00790300: 0x00001EF3 + "\x00Y\x03#\x00\x00\x1e\xf4" + // 0x00590323: 0x00001EF4 + "\x00y\x03#\x00\x00\x1e\xf5" + // 0x00790323: 0x00001EF5 + "\x00Y\x03\t\x00\x00\x1e\xf6" + // 0x00590309: 0x00001EF6 + "\x00y\x03\t\x00\x00\x1e\xf7" + // 0x00790309: 0x00001EF7 + "\x00Y\x03\x03\x00\x00\x1e\xf8" + // 0x00590303: 0x00001EF8 + "\x00y\x03\x03\x00\x00\x1e\xf9" + // 0x00790303: 0x00001EF9 + "\x03\xb1\x03\x13\x00\x00\x1f\x00" + // 0x03B10313: 0x00001F00 + "\x03\xb1\x03\x14\x00\x00\x1f\x01" + // 0x03B10314: 0x00001F01 + "\x1f\x00\x03\x00\x00\x00\x1f\x02" + // 0x1F000300: 0x00001F02 + "\x1f\x01\x03\x00\x00\x00\x1f\x03" + // 0x1F010300: 0x00001F03 + "\x1f\x00\x03\x01\x00\x00\x1f\x04" + // 0x1F000301: 0x00001F04 + "\x1f\x01\x03\x01\x00\x00\x1f\x05" + // 0x1F010301: 0x00001F05 + "\x1f\x00\x03B\x00\x00\x1f\x06" + // 0x1F000342: 0x00001F06 + "\x1f\x01\x03B\x00\x00\x1f\a" + // 0x1F010342: 0x00001F07 + "\x03\x91\x03\x13\x00\x00\x1f\b" + // 0x03910313: 0x00001F08 + "\x03\x91\x03\x14\x00\x00\x1f\t" + // 0x03910314: 0x00001F09 + "\x1f\b\x03\x00\x00\x00\x1f\n" + // 0x1F080300: 0x00001F0A + "\x1f\t\x03\x00\x00\x00\x1f\v" + // 0x1F090300: 0x00001F0B + "\x1f\b\x03\x01\x00\x00\x1f\f" + // 0x1F080301: 0x00001F0C + "\x1f\t\x03\x01\x00\x00\x1f\r" + // 0x1F090301: 0x00001F0D + "\x1f\b\x03B\x00\x00\x1f\x0e" + // 0x1F080342: 0x00001F0E + "\x1f\t\x03B\x00\x00\x1f\x0f" + // 0x1F090342: 0x00001F0F + "\x03\xb5\x03\x13\x00\x00\x1f\x10" + // 0x03B50313: 0x00001F10 + "\x03\xb5\x03\x14\x00\x00\x1f\x11" + // 0x03B50314: 0x00001F11 + "\x1f\x10\x03\x00\x00\x00\x1f\x12" + // 0x1F100300: 0x00001F12 + "\x1f\x11\x03\x00\x00\x00\x1f\x13" + // 0x1F110300: 0x00001F13 + "\x1f\x10\x03\x01\x00\x00\x1f\x14" + // 0x1F100301: 0x00001F14 + "\x1f\x11\x03\x01\x00\x00\x1f\x15" + // 0x1F110301: 0x00001F15 + "\x03\x95\x03\x13\x00\x00\x1f\x18" + // 0x03950313: 0x00001F18 + "\x03\x95\x03\x14\x00\x00\x1f\x19" + // 0x03950314: 0x00001F19 + "\x1f\x18\x03\x00\x00\x00\x1f\x1a" + // 0x1F180300: 0x00001F1A + "\x1f\x19\x03\x00\x00\x00\x1f\x1b" + // 0x1F190300: 0x00001F1B + "\x1f\x18\x03\x01\x00\x00\x1f\x1c" + // 0x1F180301: 0x00001F1C + "\x1f\x19\x03\x01\x00\x00\x1f\x1d" + // 0x1F190301: 0x00001F1D + "\x03\xb7\x03\x13\x00\x00\x1f " + // 0x03B70313: 0x00001F20 + "\x03\xb7\x03\x14\x00\x00\x1f!" + // 0x03B70314: 0x00001F21 + "\x1f \x03\x00\x00\x00\x1f\"" + // 0x1F200300: 0x00001F22 + "\x1f!\x03\x00\x00\x00\x1f#" + // 0x1F210300: 0x00001F23 + "\x1f \x03\x01\x00\x00\x1f$" + // 0x1F200301: 0x00001F24 + "\x1f!\x03\x01\x00\x00\x1f%" + // 0x1F210301: 0x00001F25 + "\x1f \x03B\x00\x00\x1f&" + // 0x1F200342: 0x00001F26 + "\x1f!\x03B\x00\x00\x1f'" + // 0x1F210342: 0x00001F27 + "\x03\x97\x03\x13\x00\x00\x1f(" + // 0x03970313: 0x00001F28 + "\x03\x97\x03\x14\x00\x00\x1f)" + // 0x03970314: 0x00001F29 + "\x1f(\x03\x00\x00\x00\x1f*" + // 0x1F280300: 0x00001F2A + "\x1f)\x03\x00\x00\x00\x1f+" + // 0x1F290300: 0x00001F2B + "\x1f(\x03\x01\x00\x00\x1f," + // 0x1F280301: 0x00001F2C + "\x1f)\x03\x01\x00\x00\x1f-" + // 0x1F290301: 0x00001F2D + "\x1f(\x03B\x00\x00\x1f." + // 0x1F280342: 0x00001F2E + "\x1f)\x03B\x00\x00\x1f/" + // 0x1F290342: 0x00001F2F + "\x03\xb9\x03\x13\x00\x00\x1f0" + // 0x03B90313: 0x00001F30 + "\x03\xb9\x03\x14\x00\x00\x1f1" + // 0x03B90314: 0x00001F31 + "\x1f0\x03\x00\x00\x00\x1f2" + // 0x1F300300: 0x00001F32 + "\x1f1\x03\x00\x00\x00\x1f3" + // 0x1F310300: 0x00001F33 + "\x1f0\x03\x01\x00\x00\x1f4" + // 0x1F300301: 0x00001F34 + "\x1f1\x03\x01\x00\x00\x1f5" + // 0x1F310301: 0x00001F35 + "\x1f0\x03B\x00\x00\x1f6" + // 0x1F300342: 0x00001F36 + "\x1f1\x03B\x00\x00\x1f7" + // 0x1F310342: 0x00001F37 + "\x03\x99\x03\x13\x00\x00\x1f8" + // 0x03990313: 0x00001F38 + "\x03\x99\x03\x14\x00\x00\x1f9" + // 0x03990314: 0x00001F39 + "\x1f8\x03\x00\x00\x00\x1f:" + // 0x1F380300: 0x00001F3A + "\x1f9\x03\x00\x00\x00\x1f;" + // 0x1F390300: 0x00001F3B + "\x1f8\x03\x01\x00\x00\x1f<" + // 0x1F380301: 0x00001F3C + "\x1f9\x03\x01\x00\x00\x1f=" + // 0x1F390301: 0x00001F3D + "\x1f8\x03B\x00\x00\x1f>" + // 0x1F380342: 0x00001F3E + "\x1f9\x03B\x00\x00\x1f?" + // 0x1F390342: 0x00001F3F + "\x03\xbf\x03\x13\x00\x00\x1f@" + // 0x03BF0313: 0x00001F40 + "\x03\xbf\x03\x14\x00\x00\x1fA" + // 0x03BF0314: 0x00001F41 + "\x1f@\x03\x00\x00\x00\x1fB" + // 0x1F400300: 0x00001F42 + "\x1fA\x03\x00\x00\x00\x1fC" + // 0x1F410300: 0x00001F43 + "\x1f@\x03\x01\x00\x00\x1fD" + // 0x1F400301: 0x00001F44 + "\x1fA\x03\x01\x00\x00\x1fE" + // 0x1F410301: 0x00001F45 + "\x03\x9f\x03\x13\x00\x00\x1fH" + // 0x039F0313: 0x00001F48 + "\x03\x9f\x03\x14\x00\x00\x1fI" + // 0x039F0314: 0x00001F49 + "\x1fH\x03\x00\x00\x00\x1fJ" + // 0x1F480300: 0x00001F4A + "\x1fI\x03\x00\x00\x00\x1fK" + // 0x1F490300: 0x00001F4B + "\x1fH\x03\x01\x00\x00\x1fL" + // 0x1F480301: 0x00001F4C + "\x1fI\x03\x01\x00\x00\x1fM" + // 0x1F490301: 0x00001F4D + "\x03\xc5\x03\x13\x00\x00\x1fP" + // 0x03C50313: 0x00001F50 + "\x03\xc5\x03\x14\x00\x00\x1fQ" + // 0x03C50314: 0x00001F51 + "\x1fP\x03\x00\x00\x00\x1fR" + // 0x1F500300: 0x00001F52 + "\x1fQ\x03\x00\x00\x00\x1fS" + // 0x1F510300: 0x00001F53 + "\x1fP\x03\x01\x00\x00\x1fT" + // 0x1F500301: 0x00001F54 + "\x1fQ\x03\x01\x00\x00\x1fU" + // 0x1F510301: 0x00001F55 + "\x1fP\x03B\x00\x00\x1fV" + // 0x1F500342: 0x00001F56 + "\x1fQ\x03B\x00\x00\x1fW" + // 0x1F510342: 0x00001F57 + "\x03\xa5\x03\x14\x00\x00\x1fY" + // 0x03A50314: 0x00001F59 + "\x1fY\x03\x00\x00\x00\x1f[" + // 0x1F590300: 0x00001F5B + "\x1fY\x03\x01\x00\x00\x1f]" + // 0x1F590301: 0x00001F5D + "\x1fY\x03B\x00\x00\x1f_" + // 0x1F590342: 0x00001F5F + "\x03\xc9\x03\x13\x00\x00\x1f`" + // 0x03C90313: 0x00001F60 + "\x03\xc9\x03\x14\x00\x00\x1fa" + // 0x03C90314: 0x00001F61 + "\x1f`\x03\x00\x00\x00\x1fb" + // 0x1F600300: 0x00001F62 + "\x1fa\x03\x00\x00\x00\x1fc" + // 0x1F610300: 0x00001F63 + "\x1f`\x03\x01\x00\x00\x1fd" + // 0x1F600301: 0x00001F64 + "\x1fa\x03\x01\x00\x00\x1fe" + // 0x1F610301: 0x00001F65 + "\x1f`\x03B\x00\x00\x1ff" + // 0x1F600342: 0x00001F66 + "\x1fa\x03B\x00\x00\x1fg" + // 0x1F610342: 0x00001F67 + "\x03\xa9\x03\x13\x00\x00\x1fh" + // 0x03A90313: 0x00001F68 + "\x03\xa9\x03\x14\x00\x00\x1fi" + // 0x03A90314: 0x00001F69 + "\x1fh\x03\x00\x00\x00\x1fj" + // 0x1F680300: 0x00001F6A + "\x1fi\x03\x00\x00\x00\x1fk" + // 0x1F690300: 0x00001F6B + "\x1fh\x03\x01\x00\x00\x1fl" + // 0x1F680301: 0x00001F6C + "\x1fi\x03\x01\x00\x00\x1fm" + // 0x1F690301: 0x00001F6D + "\x1fh\x03B\x00\x00\x1fn" + // 0x1F680342: 0x00001F6E + "\x1fi\x03B\x00\x00\x1fo" + // 0x1F690342: 0x00001F6F + "\x03\xb1\x03\x00\x00\x00\x1fp" + // 0x03B10300: 0x00001F70 + "\x03\xb5\x03\x00\x00\x00\x1fr" + // 0x03B50300: 0x00001F72 + "\x03\xb7\x03\x00\x00\x00\x1ft" + // 0x03B70300: 0x00001F74 + "\x03\xb9\x03\x00\x00\x00\x1fv" + // 0x03B90300: 0x00001F76 + "\x03\xbf\x03\x00\x00\x00\x1fx" + // 0x03BF0300: 0x00001F78 + "\x03\xc5\x03\x00\x00\x00\x1fz" + // 0x03C50300: 0x00001F7A + "\x03\xc9\x03\x00\x00\x00\x1f|" + // 0x03C90300: 0x00001F7C + "\x1f\x00\x03E\x00\x00\x1f\x80" + // 0x1F000345: 0x00001F80 + "\x1f\x01\x03E\x00\x00\x1f\x81" + // 0x1F010345: 0x00001F81 + "\x1f\x02\x03E\x00\x00\x1f\x82" + // 0x1F020345: 0x00001F82 + "\x1f\x03\x03E\x00\x00\x1f\x83" + // 0x1F030345: 0x00001F83 + "\x1f\x04\x03E\x00\x00\x1f\x84" + // 0x1F040345: 0x00001F84 + "\x1f\x05\x03E\x00\x00\x1f\x85" + // 0x1F050345: 0x00001F85 + "\x1f\x06\x03E\x00\x00\x1f\x86" + // 0x1F060345: 0x00001F86 + "\x1f\a\x03E\x00\x00\x1f\x87" + // 0x1F070345: 0x00001F87 + "\x1f\b\x03E\x00\x00\x1f\x88" + // 0x1F080345: 0x00001F88 + "\x1f\t\x03E\x00\x00\x1f\x89" + // 0x1F090345: 0x00001F89 + "\x1f\n\x03E\x00\x00\x1f\x8a" + // 0x1F0A0345: 0x00001F8A + "\x1f\v\x03E\x00\x00\x1f\x8b" + // 0x1F0B0345: 0x00001F8B + "\x1f\f\x03E\x00\x00\x1f\x8c" + // 0x1F0C0345: 0x00001F8C + "\x1f\r\x03E\x00\x00\x1f\x8d" + // 0x1F0D0345: 0x00001F8D + "\x1f\x0e\x03E\x00\x00\x1f\x8e" + // 0x1F0E0345: 0x00001F8E + "\x1f\x0f\x03E\x00\x00\x1f\x8f" + // 0x1F0F0345: 0x00001F8F + "\x1f \x03E\x00\x00\x1f\x90" + // 0x1F200345: 0x00001F90 + "\x1f!\x03E\x00\x00\x1f\x91" + // 0x1F210345: 0x00001F91 + "\x1f\"\x03E\x00\x00\x1f\x92" + // 0x1F220345: 0x00001F92 + "\x1f#\x03E\x00\x00\x1f\x93" + // 0x1F230345: 0x00001F93 + "\x1f$\x03E\x00\x00\x1f\x94" + // 0x1F240345: 0x00001F94 + "\x1f%\x03E\x00\x00\x1f\x95" + // 0x1F250345: 0x00001F95 + "\x1f&\x03E\x00\x00\x1f\x96" + // 0x1F260345: 0x00001F96 + "\x1f'\x03E\x00\x00\x1f\x97" + // 0x1F270345: 0x00001F97 + "\x1f(\x03E\x00\x00\x1f\x98" + // 0x1F280345: 0x00001F98 + "\x1f)\x03E\x00\x00\x1f\x99" + // 0x1F290345: 0x00001F99 + "\x1f*\x03E\x00\x00\x1f\x9a" + // 0x1F2A0345: 0x00001F9A + "\x1f+\x03E\x00\x00\x1f\x9b" + // 0x1F2B0345: 0x00001F9B + "\x1f,\x03E\x00\x00\x1f\x9c" + // 0x1F2C0345: 0x00001F9C + "\x1f-\x03E\x00\x00\x1f\x9d" + // 0x1F2D0345: 0x00001F9D + "\x1f.\x03E\x00\x00\x1f\x9e" + // 0x1F2E0345: 0x00001F9E + "\x1f/\x03E\x00\x00\x1f\x9f" + // 0x1F2F0345: 0x00001F9F + "\x1f`\x03E\x00\x00\x1f\xa0" + // 0x1F600345: 0x00001FA0 + "\x1fa\x03E\x00\x00\x1f\xa1" + // 0x1F610345: 0x00001FA1 + "\x1fb\x03E\x00\x00\x1f\xa2" + // 0x1F620345: 0x00001FA2 + "\x1fc\x03E\x00\x00\x1f\xa3" + // 0x1F630345: 0x00001FA3 + "\x1fd\x03E\x00\x00\x1f\xa4" + // 0x1F640345: 0x00001FA4 + "\x1fe\x03E\x00\x00\x1f\xa5" + // 0x1F650345: 0x00001FA5 + "\x1ff\x03E\x00\x00\x1f\xa6" + // 0x1F660345: 0x00001FA6 + "\x1fg\x03E\x00\x00\x1f\xa7" + // 0x1F670345: 0x00001FA7 + "\x1fh\x03E\x00\x00\x1f\xa8" + // 0x1F680345: 0x00001FA8 + "\x1fi\x03E\x00\x00\x1f\xa9" + // 0x1F690345: 0x00001FA9 + "\x1fj\x03E\x00\x00\x1f\xaa" + // 0x1F6A0345: 0x00001FAA + "\x1fk\x03E\x00\x00\x1f\xab" + // 0x1F6B0345: 0x00001FAB + "\x1fl\x03E\x00\x00\x1f\xac" + // 0x1F6C0345: 0x00001FAC + "\x1fm\x03E\x00\x00\x1f\xad" + // 0x1F6D0345: 0x00001FAD + "\x1fn\x03E\x00\x00\x1f\xae" + // 0x1F6E0345: 0x00001FAE + "\x1fo\x03E\x00\x00\x1f\xaf" + // 0x1F6F0345: 0x00001FAF + "\x03\xb1\x03\x06\x00\x00\x1f\xb0" + // 0x03B10306: 0x00001FB0 + "\x03\xb1\x03\x04\x00\x00\x1f\xb1" + // 0x03B10304: 0x00001FB1 + "\x1fp\x03E\x00\x00\x1f\xb2" + // 0x1F700345: 0x00001FB2 + "\x03\xb1\x03E\x00\x00\x1f\xb3" + // 0x03B10345: 0x00001FB3 + "\x03\xac\x03E\x00\x00\x1f\xb4" + // 0x03AC0345: 0x00001FB4 + "\x03\xb1\x03B\x00\x00\x1f\xb6" + // 0x03B10342: 0x00001FB6 + "\x1f\xb6\x03E\x00\x00\x1f\xb7" + // 0x1FB60345: 0x00001FB7 + "\x03\x91\x03\x06\x00\x00\x1f\xb8" + // 0x03910306: 0x00001FB8 + "\x03\x91\x03\x04\x00\x00\x1f\xb9" + // 0x03910304: 0x00001FB9 + "\x03\x91\x03\x00\x00\x00\x1f\xba" + // 0x03910300: 0x00001FBA + "\x03\x91\x03E\x00\x00\x1f\xbc" + // 0x03910345: 0x00001FBC + "\x00\xa8\x03B\x00\x00\x1f\xc1" + // 0x00A80342: 0x00001FC1 + "\x1ft\x03E\x00\x00\x1f\xc2" + // 0x1F740345: 0x00001FC2 + "\x03\xb7\x03E\x00\x00\x1f\xc3" + // 0x03B70345: 0x00001FC3 + "\x03\xae\x03E\x00\x00\x1f\xc4" + // 0x03AE0345: 0x00001FC4 + "\x03\xb7\x03B\x00\x00\x1f\xc6" + // 0x03B70342: 0x00001FC6 + "\x1f\xc6\x03E\x00\x00\x1f\xc7" + // 0x1FC60345: 0x00001FC7 + "\x03\x95\x03\x00\x00\x00\x1f\xc8" + // 0x03950300: 0x00001FC8 + "\x03\x97\x03\x00\x00\x00\x1f\xca" + // 0x03970300: 0x00001FCA + "\x03\x97\x03E\x00\x00\x1f\xcc" + // 0x03970345: 0x00001FCC + "\x1f\xbf\x03\x00\x00\x00\x1f\xcd" + // 0x1FBF0300: 0x00001FCD + "\x1f\xbf\x03\x01\x00\x00\x1f\xce" + // 0x1FBF0301: 0x00001FCE + "\x1f\xbf\x03B\x00\x00\x1f\xcf" + // 0x1FBF0342: 0x00001FCF + "\x03\xb9\x03\x06\x00\x00\x1f\xd0" + // 0x03B90306: 0x00001FD0 + "\x03\xb9\x03\x04\x00\x00\x1f\xd1" + // 0x03B90304: 0x00001FD1 + "\x03\xca\x03\x00\x00\x00\x1f\xd2" + // 0x03CA0300: 0x00001FD2 + "\x03\xb9\x03B\x00\x00\x1f\xd6" + // 0x03B90342: 0x00001FD6 + "\x03\xca\x03B\x00\x00\x1f\xd7" + // 0x03CA0342: 0x00001FD7 + "\x03\x99\x03\x06\x00\x00\x1f\xd8" + // 0x03990306: 0x00001FD8 + "\x03\x99\x03\x04\x00\x00\x1f\xd9" + // 0x03990304: 0x00001FD9 + "\x03\x99\x03\x00\x00\x00\x1f\xda" + // 0x03990300: 0x00001FDA + "\x1f\xfe\x03\x00\x00\x00\x1f\xdd" + // 0x1FFE0300: 0x00001FDD + "\x1f\xfe\x03\x01\x00\x00\x1f\xde" + // 0x1FFE0301: 0x00001FDE + "\x1f\xfe\x03B\x00\x00\x1f\xdf" + // 0x1FFE0342: 0x00001FDF + "\x03\xc5\x03\x06\x00\x00\x1f\xe0" + // 0x03C50306: 0x00001FE0 + "\x03\xc5\x03\x04\x00\x00\x1f\xe1" + // 0x03C50304: 0x00001FE1 + "\x03\xcb\x03\x00\x00\x00\x1f\xe2" + // 0x03CB0300: 0x00001FE2 + "\x03\xc1\x03\x13\x00\x00\x1f\xe4" + // 0x03C10313: 0x00001FE4 + "\x03\xc1\x03\x14\x00\x00\x1f\xe5" + // 0x03C10314: 0x00001FE5 + "\x03\xc5\x03B\x00\x00\x1f\xe6" + // 0x03C50342: 0x00001FE6 + "\x03\xcb\x03B\x00\x00\x1f\xe7" + // 0x03CB0342: 0x00001FE7 + "\x03\xa5\x03\x06\x00\x00\x1f\xe8" + // 0x03A50306: 0x00001FE8 + "\x03\xa5\x03\x04\x00\x00\x1f\xe9" + // 0x03A50304: 0x00001FE9 + "\x03\xa5\x03\x00\x00\x00\x1f\xea" + // 0x03A50300: 0x00001FEA + "\x03\xa1\x03\x14\x00\x00\x1f\xec" + // 0x03A10314: 0x00001FEC + "\x00\xa8\x03\x00\x00\x00\x1f\xed" + // 0x00A80300: 0x00001FED + "\x1f|\x03E\x00\x00\x1f\xf2" + // 0x1F7C0345: 0x00001FF2 + "\x03\xc9\x03E\x00\x00\x1f\xf3" + // 0x03C90345: 0x00001FF3 + "\x03\xce\x03E\x00\x00\x1f\xf4" + // 0x03CE0345: 0x00001FF4 + "\x03\xc9\x03B\x00\x00\x1f\xf6" + // 0x03C90342: 0x00001FF6 + "\x1f\xf6\x03E\x00\x00\x1f\xf7" + // 0x1FF60345: 0x00001FF7 + "\x03\x9f\x03\x00\x00\x00\x1f\xf8" + // 0x039F0300: 0x00001FF8 + "\x03\xa9\x03\x00\x00\x00\x1f\xfa" + // 0x03A90300: 0x00001FFA + "\x03\xa9\x03E\x00\x00\x1f\xfc" + // 0x03A90345: 0x00001FFC + "!\x90\x038\x00\x00!\x9a" + // 0x21900338: 0x0000219A + "!\x92\x038\x00\x00!\x9b" + // 0x21920338: 0x0000219B + "!\x94\x038\x00\x00!\xae" + // 0x21940338: 0x000021AE + "!\xd0\x038\x00\x00!\xcd" + // 0x21D00338: 0x000021CD + "!\xd4\x038\x00\x00!\xce" + // 0x21D40338: 0x000021CE + "!\xd2\x038\x00\x00!\xcf" + // 0x21D20338: 0x000021CF + "\"\x03\x038\x00\x00\"\x04" + // 0x22030338: 0x00002204 + "\"\b\x038\x00\x00\"\t" + // 0x22080338: 0x00002209 + "\"\v\x038\x00\x00\"\f" + // 0x220B0338: 0x0000220C + "\"#\x038\x00\x00\"$" + // 0x22230338: 0x00002224 + "\"%\x038\x00\x00\"&" + // 0x22250338: 0x00002226 + "\"<\x038\x00\x00\"A" + // 0x223C0338: 0x00002241 + "\"C\x038\x00\x00\"D" + // 0x22430338: 0x00002244 + "\"E\x038\x00\x00\"G" + // 0x22450338: 0x00002247 + "\"H\x038\x00\x00\"I" + // 0x22480338: 0x00002249 + "\x00=\x038\x00\x00\"`" + // 0x003D0338: 0x00002260 + "\"a\x038\x00\x00\"b" + // 0x22610338: 0x00002262 + "\"M\x038\x00\x00\"m" + // 0x224D0338: 0x0000226D + "\x00<\x038\x00\x00\"n" + // 0x003C0338: 0x0000226E + "\x00>\x038\x00\x00\"o" + // 0x003E0338: 0x0000226F + "\"d\x038\x00\x00\"p" + // 0x22640338: 0x00002270 + "\"e\x038\x00\x00\"q" + // 0x22650338: 0x00002271 + "\"r\x038\x00\x00\"t" + // 0x22720338: 0x00002274 + "\"s\x038\x00\x00\"u" + // 0x22730338: 0x00002275 + "\"v\x038\x00\x00\"x" + // 0x22760338: 0x00002278 + "\"w\x038\x00\x00\"y" + // 0x22770338: 0x00002279 + "\"z\x038\x00\x00\"\x80" + // 0x227A0338: 0x00002280 + "\"{\x038\x00\x00\"\x81" + // 0x227B0338: 0x00002281 + "\"\x82\x038\x00\x00\"\x84" + // 0x22820338: 0x00002284 + "\"\x83\x038\x00\x00\"\x85" + // 0x22830338: 0x00002285 + "\"\x86\x038\x00\x00\"\x88" + // 0x22860338: 0x00002288 + "\"\x87\x038\x00\x00\"\x89" + // 0x22870338: 0x00002289 + "\"\xa2\x038\x00\x00\"\xac" + // 0x22A20338: 0x000022AC + "\"\xa8\x038\x00\x00\"\xad" + // 0x22A80338: 0x000022AD + "\"\xa9\x038\x00\x00\"\xae" + // 0x22A90338: 0x000022AE + "\"\xab\x038\x00\x00\"\xaf" + // 0x22AB0338: 0x000022AF + "\"|\x038\x00\x00\"\xe0" + // 0x227C0338: 0x000022E0 + "\"}\x038\x00\x00\"\xe1" + // 0x227D0338: 0x000022E1 + "\"\x91\x038\x00\x00\"\xe2" + // 0x22910338: 0x000022E2 + "\"\x92\x038\x00\x00\"\xe3" + // 0x22920338: 0x000022E3 + "\"\xb2\x038\x00\x00\"\xea" + // 0x22B20338: 0x000022EA + "\"\xb3\x038\x00\x00\"\xeb" + // 0x22B30338: 0x000022EB + "\"\xb4\x038\x00\x00\"\xec" + // 0x22B40338: 0x000022EC + "\"\xb5\x038\x00\x00\"\xed" + // 0x22B50338: 0x000022ED + "0K0\x99\x00\x000L" + // 0x304B3099: 0x0000304C + "0M0\x99\x00\x000N" + // 0x304D3099: 0x0000304E + "0O0\x99\x00\x000P" + // 0x304F3099: 0x00003050 + "0Q0\x99\x00\x000R" + // 0x30513099: 0x00003052 + "0S0\x99\x00\x000T" + // 0x30533099: 0x00003054 + "0U0\x99\x00\x000V" + // 0x30553099: 0x00003056 + "0W0\x99\x00\x000X" + // 0x30573099: 0x00003058 + "0Y0\x99\x00\x000Z" + // 0x30593099: 0x0000305A + "0[0\x99\x00\x000\\" + // 0x305B3099: 0x0000305C + "0]0\x99\x00\x000^" + // 0x305D3099: 0x0000305E + "0_0\x99\x00\x000`" + // 0x305F3099: 0x00003060 + "0a0\x99\x00\x000b" + // 0x30613099: 0x00003062 + "0d0\x99\x00\x000e" + // 0x30643099: 0x00003065 + "0f0\x99\x00\x000g" + // 0x30663099: 0x00003067 + "0h0\x99\x00\x000i" + // 0x30683099: 0x00003069 + "0o0\x99\x00\x000p" + // 0x306F3099: 0x00003070 + "0o0\x9a\x00\x000q" + // 0x306F309A: 0x00003071 + "0r0\x99\x00\x000s" + // 0x30723099: 0x00003073 + "0r0\x9a\x00\x000t" + // 0x3072309A: 0x00003074 + "0u0\x99\x00\x000v" + // 0x30753099: 0x00003076 + "0u0\x9a\x00\x000w" + // 0x3075309A: 0x00003077 + "0x0\x99\x00\x000y" + // 0x30783099: 0x00003079 + "0x0\x9a\x00\x000z" + // 0x3078309A: 0x0000307A + "0{0\x99\x00\x000|" + // 0x307B3099: 0x0000307C + "0{0\x9a\x00\x000}" + // 0x307B309A: 0x0000307D + "0F0\x99\x00\x000\x94" + // 0x30463099: 0x00003094 + "0\x9d0\x99\x00\x000\x9e" + // 0x309D3099: 0x0000309E + "0\xab0\x99\x00\x000\xac" + // 0x30AB3099: 0x000030AC + "0\xad0\x99\x00\x000\xae" + // 0x30AD3099: 0x000030AE + "0\xaf0\x99\x00\x000\xb0" + // 0x30AF3099: 0x000030B0 + "0\xb10\x99\x00\x000\xb2" + // 0x30B13099: 0x000030B2 + "0\xb30\x99\x00\x000\xb4" + // 0x30B33099: 0x000030B4 + "0\xb50\x99\x00\x000\xb6" + // 0x30B53099: 0x000030B6 + "0\xb70\x99\x00\x000\xb8" + // 0x30B73099: 0x000030B8 + "0\xb90\x99\x00\x000\xba" + // 0x30B93099: 0x000030BA + "0\xbb0\x99\x00\x000\xbc" + // 0x30BB3099: 0x000030BC + "0\xbd0\x99\x00\x000\xbe" + // 0x30BD3099: 0x000030BE + "0\xbf0\x99\x00\x000\xc0" + // 0x30BF3099: 0x000030C0 + "0\xc10\x99\x00\x000\xc2" + // 0x30C13099: 0x000030C2 + "0\xc40\x99\x00\x000\xc5" + // 0x30C43099: 0x000030C5 + "0\xc60\x99\x00\x000\xc7" + // 0x30C63099: 0x000030C7 + "0\xc80\x99\x00\x000\xc9" + // 0x30C83099: 0x000030C9 + "0\xcf0\x99\x00\x000\xd0" + // 0x30CF3099: 0x000030D0 + "0\xcf0\x9a\x00\x000\xd1" + // 0x30CF309A: 0x000030D1 + "0\xd20\x99\x00\x000\xd3" + // 0x30D23099: 0x000030D3 + "0\xd20\x9a\x00\x000\xd4" + // 0x30D2309A: 0x000030D4 + "0\xd50\x99\x00\x000\xd6" + // 0x30D53099: 0x000030D6 + "0\xd50\x9a\x00\x000\xd7" + // 0x30D5309A: 0x000030D7 + "0\xd80\x99\x00\x000\xd9" + // 0x30D83099: 0x000030D9 + "0\xd80\x9a\x00\x000\xda" + // 0x30D8309A: 0x000030DA + "0\xdb0\x99\x00\x000\xdc" + // 0x30DB3099: 0x000030DC + "0\xdb0\x9a\x00\x000\xdd" + // 0x30DB309A: 0x000030DD + "0\xa60\x99\x00\x000\xf4" + // 0x30A63099: 0x000030F4 + "0\xef0\x99\x00\x000\xf7" + // 0x30EF3099: 0x000030F7 + "0\xf00\x99\x00\x000\xf8" + // 0x30F03099: 0x000030F8 + "0\xf10\x99\x00\x000\xf9" + // 0x30F13099: 0x000030F9 + "0\xf20\x99\x00\x000\xfa" + // 0x30F23099: 0x000030FA + "0\xfd0\x99\x00\x000\xfe" + // 0x30FD3099: 0x000030FE + "\x10\x99\x10\xba\x00\x01\x10\x9a" + // 0x109910BA: 0x0001109A + "\x10\x9b\x10\xba\x00\x01\x10\x9c" + // 0x109B10BA: 0x0001109C + "\x10\xa5\x10\xba\x00\x01\x10\xab" + // 0x10A510BA: 0x000110AB + "\x111\x11'\x00\x01\x11." + // 0x11311127: 0x0001112E + "\x112\x11'\x00\x01\x11/" + // 0x11321127: 0x0001112F + "\x13G\x13>\x00\x01\x13K" + // 0x1347133E: 0x0001134B + "\x13G\x13W\x00\x01\x13L" + // 0x13471357: 0x0001134C + "\x14\xb9\x14\xba\x00\x01\x14\xbb" + // 0x14B914BA: 0x000114BB + "\x14\xb9\x14\xb0\x00\x01\x14\xbc" + // 0x14B914B0: 0x000114BC + "\x14\xb9\x14\xbd\x00\x01\x14\xbe" + // 0x14B914BD: 0x000114BE + "\x15\xb8\x15\xaf\x00\x01\x15\xba" + // 0x15B815AF: 0x000115BA + "\x15\xb9\x15\xaf\x00\x01\x15\xbb" + // 0x15B915AF: 0x000115BB + "" + // Total size of tables: 53KB (54226 bytes) diff --git a/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go b/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go index a01274a..9429069 100644 --- a/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go +++ b/vendor/golang.org/x/text/unicode/norm/tables9.0.0.go @@ -4,6 +4,8 @@ package norm +import "sync" + const ( // Version is the Unicode edition from which the tables are derived. Version = "9.0.0" @@ -6687,947 +6689,949 @@ var nfkcSparseValues = [875]valueRange{ } // recompMap: 7520 bytes (entries only) -var recompMap = map[uint32]rune{ - 0x00410300: 0x00C0, - 0x00410301: 0x00C1, - 0x00410302: 0x00C2, - 0x00410303: 0x00C3, - 0x00410308: 0x00C4, - 0x0041030A: 0x00C5, - 0x00430327: 0x00C7, - 0x00450300: 0x00C8, - 0x00450301: 0x00C9, - 0x00450302: 0x00CA, - 0x00450308: 0x00CB, - 0x00490300: 0x00CC, - 0x00490301: 0x00CD, - 0x00490302: 0x00CE, - 0x00490308: 0x00CF, - 0x004E0303: 0x00D1, - 0x004F0300: 0x00D2, - 0x004F0301: 0x00D3, - 0x004F0302: 0x00D4, - 0x004F0303: 0x00D5, - 0x004F0308: 0x00D6, - 0x00550300: 0x00D9, - 0x00550301: 0x00DA, - 0x00550302: 0x00DB, - 0x00550308: 0x00DC, - 0x00590301: 0x00DD, - 0x00610300: 0x00E0, - 0x00610301: 0x00E1, - 0x00610302: 0x00E2, - 0x00610303: 0x00E3, - 0x00610308: 0x00E4, - 0x0061030A: 0x00E5, - 0x00630327: 0x00E7, - 0x00650300: 0x00E8, - 0x00650301: 0x00E9, - 0x00650302: 0x00EA, - 0x00650308: 0x00EB, - 0x00690300: 0x00EC, - 0x00690301: 0x00ED, - 0x00690302: 0x00EE, - 0x00690308: 0x00EF, - 0x006E0303: 0x00F1, - 0x006F0300: 0x00F2, - 0x006F0301: 0x00F3, - 0x006F0302: 0x00F4, - 0x006F0303: 0x00F5, - 0x006F0308: 0x00F6, - 0x00750300: 0x00F9, - 0x00750301: 0x00FA, - 0x00750302: 0x00FB, - 0x00750308: 0x00FC, - 0x00790301: 0x00FD, - 0x00790308: 0x00FF, - 0x00410304: 0x0100, - 0x00610304: 0x0101, - 0x00410306: 0x0102, - 0x00610306: 0x0103, - 0x00410328: 0x0104, - 0x00610328: 0x0105, - 0x00430301: 0x0106, - 0x00630301: 0x0107, - 0x00430302: 0x0108, - 0x00630302: 0x0109, - 0x00430307: 0x010A, - 0x00630307: 0x010B, - 0x0043030C: 0x010C, - 0x0063030C: 0x010D, - 0x0044030C: 0x010E, - 0x0064030C: 0x010F, - 0x00450304: 0x0112, - 0x00650304: 0x0113, - 0x00450306: 0x0114, - 0x00650306: 0x0115, - 0x00450307: 0x0116, - 0x00650307: 0x0117, - 0x00450328: 0x0118, - 0x00650328: 0x0119, - 0x0045030C: 0x011A, - 0x0065030C: 0x011B, - 0x00470302: 0x011C, - 0x00670302: 0x011D, - 0x00470306: 0x011E, - 0x00670306: 0x011F, - 0x00470307: 0x0120, - 0x00670307: 0x0121, - 0x00470327: 0x0122, - 0x00670327: 0x0123, - 0x00480302: 0x0124, - 0x00680302: 0x0125, - 0x00490303: 0x0128, - 0x00690303: 0x0129, - 0x00490304: 0x012A, - 0x00690304: 0x012B, - 0x00490306: 0x012C, - 0x00690306: 0x012D, - 0x00490328: 0x012E, - 0x00690328: 0x012F, - 0x00490307: 0x0130, - 0x004A0302: 0x0134, - 0x006A0302: 0x0135, - 0x004B0327: 0x0136, - 0x006B0327: 0x0137, - 0x004C0301: 0x0139, - 0x006C0301: 0x013A, - 0x004C0327: 0x013B, - 0x006C0327: 0x013C, - 0x004C030C: 0x013D, - 0x006C030C: 0x013E, - 0x004E0301: 0x0143, - 0x006E0301: 0x0144, - 0x004E0327: 0x0145, - 0x006E0327: 0x0146, - 0x004E030C: 0x0147, - 0x006E030C: 0x0148, - 0x004F0304: 0x014C, - 0x006F0304: 0x014D, - 0x004F0306: 0x014E, - 0x006F0306: 0x014F, - 0x004F030B: 0x0150, - 0x006F030B: 0x0151, - 0x00520301: 0x0154, - 0x00720301: 0x0155, - 0x00520327: 0x0156, - 0x00720327: 0x0157, - 0x0052030C: 0x0158, - 0x0072030C: 0x0159, - 0x00530301: 0x015A, - 0x00730301: 0x015B, - 0x00530302: 0x015C, - 0x00730302: 0x015D, - 0x00530327: 0x015E, - 0x00730327: 0x015F, - 0x0053030C: 0x0160, - 0x0073030C: 0x0161, - 0x00540327: 0x0162, - 0x00740327: 0x0163, - 0x0054030C: 0x0164, - 0x0074030C: 0x0165, - 0x00550303: 0x0168, - 0x00750303: 0x0169, - 0x00550304: 0x016A, - 0x00750304: 0x016B, - 0x00550306: 0x016C, - 0x00750306: 0x016D, - 0x0055030A: 0x016E, - 0x0075030A: 0x016F, - 0x0055030B: 0x0170, - 0x0075030B: 0x0171, - 0x00550328: 0x0172, - 0x00750328: 0x0173, - 0x00570302: 0x0174, - 0x00770302: 0x0175, - 0x00590302: 0x0176, - 0x00790302: 0x0177, - 0x00590308: 0x0178, - 0x005A0301: 0x0179, - 0x007A0301: 0x017A, - 0x005A0307: 0x017B, - 0x007A0307: 0x017C, - 0x005A030C: 0x017D, - 0x007A030C: 0x017E, - 0x004F031B: 0x01A0, - 0x006F031B: 0x01A1, - 0x0055031B: 0x01AF, - 0x0075031B: 0x01B0, - 0x0041030C: 0x01CD, - 0x0061030C: 0x01CE, - 0x0049030C: 0x01CF, - 0x0069030C: 0x01D0, - 0x004F030C: 0x01D1, - 0x006F030C: 0x01D2, - 0x0055030C: 0x01D3, - 0x0075030C: 0x01D4, - 0x00DC0304: 0x01D5, - 0x00FC0304: 0x01D6, - 0x00DC0301: 0x01D7, - 0x00FC0301: 0x01D8, - 0x00DC030C: 0x01D9, - 0x00FC030C: 0x01DA, - 0x00DC0300: 0x01DB, - 0x00FC0300: 0x01DC, - 0x00C40304: 0x01DE, - 0x00E40304: 0x01DF, - 0x02260304: 0x01E0, - 0x02270304: 0x01E1, - 0x00C60304: 0x01E2, - 0x00E60304: 0x01E3, - 0x0047030C: 0x01E6, - 0x0067030C: 0x01E7, - 0x004B030C: 0x01E8, - 0x006B030C: 0x01E9, - 0x004F0328: 0x01EA, - 0x006F0328: 0x01EB, - 0x01EA0304: 0x01EC, - 0x01EB0304: 0x01ED, - 0x01B7030C: 0x01EE, - 0x0292030C: 0x01EF, - 0x006A030C: 0x01F0, - 0x00470301: 0x01F4, - 0x00670301: 0x01F5, - 0x004E0300: 0x01F8, - 0x006E0300: 0x01F9, - 0x00C50301: 0x01FA, - 0x00E50301: 0x01FB, - 0x00C60301: 0x01FC, - 0x00E60301: 0x01FD, - 0x00D80301: 0x01FE, - 0x00F80301: 0x01FF, - 0x0041030F: 0x0200, - 0x0061030F: 0x0201, - 0x00410311: 0x0202, - 0x00610311: 0x0203, - 0x0045030F: 0x0204, - 0x0065030F: 0x0205, - 0x00450311: 0x0206, - 0x00650311: 0x0207, - 0x0049030F: 0x0208, - 0x0069030F: 0x0209, - 0x00490311: 0x020A, - 0x00690311: 0x020B, - 0x004F030F: 0x020C, - 0x006F030F: 0x020D, - 0x004F0311: 0x020E, - 0x006F0311: 0x020F, - 0x0052030F: 0x0210, - 0x0072030F: 0x0211, - 0x00520311: 0x0212, - 0x00720311: 0x0213, - 0x0055030F: 0x0214, - 0x0075030F: 0x0215, - 0x00550311: 0x0216, - 0x00750311: 0x0217, - 0x00530326: 0x0218, - 0x00730326: 0x0219, - 0x00540326: 0x021A, - 0x00740326: 0x021B, - 0x0048030C: 0x021E, - 0x0068030C: 0x021F, - 0x00410307: 0x0226, - 0x00610307: 0x0227, - 0x00450327: 0x0228, - 0x00650327: 0x0229, - 0x00D60304: 0x022A, - 0x00F60304: 0x022B, - 0x00D50304: 0x022C, - 0x00F50304: 0x022D, - 0x004F0307: 0x022E, - 0x006F0307: 0x022F, - 0x022E0304: 0x0230, - 0x022F0304: 0x0231, - 0x00590304: 0x0232, - 0x00790304: 0x0233, - 0x00A80301: 0x0385, - 0x03910301: 0x0386, - 0x03950301: 0x0388, - 0x03970301: 0x0389, - 0x03990301: 0x038A, - 0x039F0301: 0x038C, - 0x03A50301: 0x038E, - 0x03A90301: 0x038F, - 0x03CA0301: 0x0390, - 0x03990308: 0x03AA, - 0x03A50308: 0x03AB, - 0x03B10301: 0x03AC, - 0x03B50301: 0x03AD, - 0x03B70301: 0x03AE, - 0x03B90301: 0x03AF, - 0x03CB0301: 0x03B0, - 0x03B90308: 0x03CA, - 0x03C50308: 0x03CB, - 0x03BF0301: 0x03CC, - 0x03C50301: 0x03CD, - 0x03C90301: 0x03CE, - 0x03D20301: 0x03D3, - 0x03D20308: 0x03D4, - 0x04150300: 0x0400, - 0x04150308: 0x0401, - 0x04130301: 0x0403, - 0x04060308: 0x0407, - 0x041A0301: 0x040C, - 0x04180300: 0x040D, - 0x04230306: 0x040E, - 0x04180306: 0x0419, - 0x04380306: 0x0439, - 0x04350300: 0x0450, - 0x04350308: 0x0451, - 0x04330301: 0x0453, - 0x04560308: 0x0457, - 0x043A0301: 0x045C, - 0x04380300: 0x045D, - 0x04430306: 0x045E, - 0x0474030F: 0x0476, - 0x0475030F: 0x0477, - 0x04160306: 0x04C1, - 0x04360306: 0x04C2, - 0x04100306: 0x04D0, - 0x04300306: 0x04D1, - 0x04100308: 0x04D2, - 0x04300308: 0x04D3, - 0x04150306: 0x04D6, - 0x04350306: 0x04D7, - 0x04D80308: 0x04DA, - 0x04D90308: 0x04DB, - 0x04160308: 0x04DC, - 0x04360308: 0x04DD, - 0x04170308: 0x04DE, - 0x04370308: 0x04DF, - 0x04180304: 0x04E2, - 0x04380304: 0x04E3, - 0x04180308: 0x04E4, - 0x04380308: 0x04E5, - 0x041E0308: 0x04E6, - 0x043E0308: 0x04E7, - 0x04E80308: 0x04EA, - 0x04E90308: 0x04EB, - 0x042D0308: 0x04EC, - 0x044D0308: 0x04ED, - 0x04230304: 0x04EE, - 0x04430304: 0x04EF, - 0x04230308: 0x04F0, - 0x04430308: 0x04F1, - 0x0423030B: 0x04F2, - 0x0443030B: 0x04F3, - 0x04270308: 0x04F4, - 0x04470308: 0x04F5, - 0x042B0308: 0x04F8, - 0x044B0308: 0x04F9, - 0x06270653: 0x0622, - 0x06270654: 0x0623, - 0x06480654: 0x0624, - 0x06270655: 0x0625, - 0x064A0654: 0x0626, - 0x06D50654: 0x06C0, - 0x06C10654: 0x06C2, - 0x06D20654: 0x06D3, - 0x0928093C: 0x0929, - 0x0930093C: 0x0931, - 0x0933093C: 0x0934, - 0x09C709BE: 0x09CB, - 0x09C709D7: 0x09CC, - 0x0B470B56: 0x0B48, - 0x0B470B3E: 0x0B4B, - 0x0B470B57: 0x0B4C, - 0x0B920BD7: 0x0B94, - 0x0BC60BBE: 0x0BCA, - 0x0BC70BBE: 0x0BCB, - 0x0BC60BD7: 0x0BCC, - 0x0C460C56: 0x0C48, - 0x0CBF0CD5: 0x0CC0, - 0x0CC60CD5: 0x0CC7, - 0x0CC60CD6: 0x0CC8, - 0x0CC60CC2: 0x0CCA, - 0x0CCA0CD5: 0x0CCB, - 0x0D460D3E: 0x0D4A, - 0x0D470D3E: 0x0D4B, - 0x0D460D57: 0x0D4C, - 0x0DD90DCA: 0x0DDA, - 0x0DD90DCF: 0x0DDC, - 0x0DDC0DCA: 0x0DDD, - 0x0DD90DDF: 0x0DDE, - 0x1025102E: 0x1026, - 0x1B051B35: 0x1B06, - 0x1B071B35: 0x1B08, - 0x1B091B35: 0x1B0A, - 0x1B0B1B35: 0x1B0C, - 0x1B0D1B35: 0x1B0E, - 0x1B111B35: 0x1B12, - 0x1B3A1B35: 0x1B3B, - 0x1B3C1B35: 0x1B3D, - 0x1B3E1B35: 0x1B40, - 0x1B3F1B35: 0x1B41, - 0x1B421B35: 0x1B43, - 0x00410325: 0x1E00, - 0x00610325: 0x1E01, - 0x00420307: 0x1E02, - 0x00620307: 0x1E03, - 0x00420323: 0x1E04, - 0x00620323: 0x1E05, - 0x00420331: 0x1E06, - 0x00620331: 0x1E07, - 0x00C70301: 0x1E08, - 0x00E70301: 0x1E09, - 0x00440307: 0x1E0A, - 0x00640307: 0x1E0B, - 0x00440323: 0x1E0C, - 0x00640323: 0x1E0D, - 0x00440331: 0x1E0E, - 0x00640331: 0x1E0F, - 0x00440327: 0x1E10, - 0x00640327: 0x1E11, - 0x0044032D: 0x1E12, - 0x0064032D: 0x1E13, - 0x01120300: 0x1E14, - 0x01130300: 0x1E15, - 0x01120301: 0x1E16, - 0x01130301: 0x1E17, - 0x0045032D: 0x1E18, - 0x0065032D: 0x1E19, - 0x00450330: 0x1E1A, - 0x00650330: 0x1E1B, - 0x02280306: 0x1E1C, - 0x02290306: 0x1E1D, - 0x00460307: 0x1E1E, - 0x00660307: 0x1E1F, - 0x00470304: 0x1E20, - 0x00670304: 0x1E21, - 0x00480307: 0x1E22, - 0x00680307: 0x1E23, - 0x00480323: 0x1E24, - 0x00680323: 0x1E25, - 0x00480308: 0x1E26, - 0x00680308: 0x1E27, - 0x00480327: 0x1E28, - 0x00680327: 0x1E29, - 0x0048032E: 0x1E2A, - 0x0068032E: 0x1E2B, - 0x00490330: 0x1E2C, - 0x00690330: 0x1E2D, - 0x00CF0301: 0x1E2E, - 0x00EF0301: 0x1E2F, - 0x004B0301: 0x1E30, - 0x006B0301: 0x1E31, - 0x004B0323: 0x1E32, - 0x006B0323: 0x1E33, - 0x004B0331: 0x1E34, - 0x006B0331: 0x1E35, - 0x004C0323: 0x1E36, - 0x006C0323: 0x1E37, - 0x1E360304: 0x1E38, - 0x1E370304: 0x1E39, - 0x004C0331: 0x1E3A, - 0x006C0331: 0x1E3B, - 0x004C032D: 0x1E3C, - 0x006C032D: 0x1E3D, - 0x004D0301: 0x1E3E, - 0x006D0301: 0x1E3F, - 0x004D0307: 0x1E40, - 0x006D0307: 0x1E41, - 0x004D0323: 0x1E42, - 0x006D0323: 0x1E43, - 0x004E0307: 0x1E44, - 0x006E0307: 0x1E45, - 0x004E0323: 0x1E46, - 0x006E0323: 0x1E47, - 0x004E0331: 0x1E48, - 0x006E0331: 0x1E49, - 0x004E032D: 0x1E4A, - 0x006E032D: 0x1E4B, - 0x00D50301: 0x1E4C, - 0x00F50301: 0x1E4D, - 0x00D50308: 0x1E4E, - 0x00F50308: 0x1E4F, - 0x014C0300: 0x1E50, - 0x014D0300: 0x1E51, - 0x014C0301: 0x1E52, - 0x014D0301: 0x1E53, - 0x00500301: 0x1E54, - 0x00700301: 0x1E55, - 0x00500307: 0x1E56, - 0x00700307: 0x1E57, - 0x00520307: 0x1E58, - 0x00720307: 0x1E59, - 0x00520323: 0x1E5A, - 0x00720323: 0x1E5B, - 0x1E5A0304: 0x1E5C, - 0x1E5B0304: 0x1E5D, - 0x00520331: 0x1E5E, - 0x00720331: 0x1E5F, - 0x00530307: 0x1E60, - 0x00730307: 0x1E61, - 0x00530323: 0x1E62, - 0x00730323: 0x1E63, - 0x015A0307: 0x1E64, - 0x015B0307: 0x1E65, - 0x01600307: 0x1E66, - 0x01610307: 0x1E67, - 0x1E620307: 0x1E68, - 0x1E630307: 0x1E69, - 0x00540307: 0x1E6A, - 0x00740307: 0x1E6B, - 0x00540323: 0x1E6C, - 0x00740323: 0x1E6D, - 0x00540331: 0x1E6E, - 0x00740331: 0x1E6F, - 0x0054032D: 0x1E70, - 0x0074032D: 0x1E71, - 0x00550324: 0x1E72, - 0x00750324: 0x1E73, - 0x00550330: 0x1E74, - 0x00750330: 0x1E75, - 0x0055032D: 0x1E76, - 0x0075032D: 0x1E77, - 0x01680301: 0x1E78, - 0x01690301: 0x1E79, - 0x016A0308: 0x1E7A, - 0x016B0308: 0x1E7B, - 0x00560303: 0x1E7C, - 0x00760303: 0x1E7D, - 0x00560323: 0x1E7E, - 0x00760323: 0x1E7F, - 0x00570300: 0x1E80, - 0x00770300: 0x1E81, - 0x00570301: 0x1E82, - 0x00770301: 0x1E83, - 0x00570308: 0x1E84, - 0x00770308: 0x1E85, - 0x00570307: 0x1E86, - 0x00770307: 0x1E87, - 0x00570323: 0x1E88, - 0x00770323: 0x1E89, - 0x00580307: 0x1E8A, - 0x00780307: 0x1E8B, - 0x00580308: 0x1E8C, - 0x00780308: 0x1E8D, - 0x00590307: 0x1E8E, - 0x00790307: 0x1E8F, - 0x005A0302: 0x1E90, - 0x007A0302: 0x1E91, - 0x005A0323: 0x1E92, - 0x007A0323: 0x1E93, - 0x005A0331: 0x1E94, - 0x007A0331: 0x1E95, - 0x00680331: 0x1E96, - 0x00740308: 0x1E97, - 0x0077030A: 0x1E98, - 0x0079030A: 0x1E99, - 0x017F0307: 0x1E9B, - 0x00410323: 0x1EA0, - 0x00610323: 0x1EA1, - 0x00410309: 0x1EA2, - 0x00610309: 0x1EA3, - 0x00C20301: 0x1EA4, - 0x00E20301: 0x1EA5, - 0x00C20300: 0x1EA6, - 0x00E20300: 0x1EA7, - 0x00C20309: 0x1EA8, - 0x00E20309: 0x1EA9, - 0x00C20303: 0x1EAA, - 0x00E20303: 0x1EAB, - 0x1EA00302: 0x1EAC, - 0x1EA10302: 0x1EAD, - 0x01020301: 0x1EAE, - 0x01030301: 0x1EAF, - 0x01020300: 0x1EB0, - 0x01030300: 0x1EB1, - 0x01020309: 0x1EB2, - 0x01030309: 0x1EB3, - 0x01020303: 0x1EB4, - 0x01030303: 0x1EB5, - 0x1EA00306: 0x1EB6, - 0x1EA10306: 0x1EB7, - 0x00450323: 0x1EB8, - 0x00650323: 0x1EB9, - 0x00450309: 0x1EBA, - 0x00650309: 0x1EBB, - 0x00450303: 0x1EBC, - 0x00650303: 0x1EBD, - 0x00CA0301: 0x1EBE, - 0x00EA0301: 0x1EBF, - 0x00CA0300: 0x1EC0, - 0x00EA0300: 0x1EC1, - 0x00CA0309: 0x1EC2, - 0x00EA0309: 0x1EC3, - 0x00CA0303: 0x1EC4, - 0x00EA0303: 0x1EC5, - 0x1EB80302: 0x1EC6, - 0x1EB90302: 0x1EC7, - 0x00490309: 0x1EC8, - 0x00690309: 0x1EC9, - 0x00490323: 0x1ECA, - 0x00690323: 0x1ECB, - 0x004F0323: 0x1ECC, - 0x006F0323: 0x1ECD, - 0x004F0309: 0x1ECE, - 0x006F0309: 0x1ECF, - 0x00D40301: 0x1ED0, - 0x00F40301: 0x1ED1, - 0x00D40300: 0x1ED2, - 0x00F40300: 0x1ED3, - 0x00D40309: 0x1ED4, - 0x00F40309: 0x1ED5, - 0x00D40303: 0x1ED6, - 0x00F40303: 0x1ED7, - 0x1ECC0302: 0x1ED8, - 0x1ECD0302: 0x1ED9, - 0x01A00301: 0x1EDA, - 0x01A10301: 0x1EDB, - 0x01A00300: 0x1EDC, - 0x01A10300: 0x1EDD, - 0x01A00309: 0x1EDE, - 0x01A10309: 0x1EDF, - 0x01A00303: 0x1EE0, - 0x01A10303: 0x1EE1, - 0x01A00323: 0x1EE2, - 0x01A10323: 0x1EE3, - 0x00550323: 0x1EE4, - 0x00750323: 0x1EE5, - 0x00550309: 0x1EE6, - 0x00750309: 0x1EE7, - 0x01AF0301: 0x1EE8, - 0x01B00301: 0x1EE9, - 0x01AF0300: 0x1EEA, - 0x01B00300: 0x1EEB, - 0x01AF0309: 0x1EEC, - 0x01B00309: 0x1EED, - 0x01AF0303: 0x1EEE, - 0x01B00303: 0x1EEF, - 0x01AF0323: 0x1EF0, - 0x01B00323: 0x1EF1, - 0x00590300: 0x1EF2, - 0x00790300: 0x1EF3, - 0x00590323: 0x1EF4, - 0x00790323: 0x1EF5, - 0x00590309: 0x1EF6, - 0x00790309: 0x1EF7, - 0x00590303: 0x1EF8, - 0x00790303: 0x1EF9, - 0x03B10313: 0x1F00, - 0x03B10314: 0x1F01, - 0x1F000300: 0x1F02, - 0x1F010300: 0x1F03, - 0x1F000301: 0x1F04, - 0x1F010301: 0x1F05, - 0x1F000342: 0x1F06, - 0x1F010342: 0x1F07, - 0x03910313: 0x1F08, - 0x03910314: 0x1F09, - 0x1F080300: 0x1F0A, - 0x1F090300: 0x1F0B, - 0x1F080301: 0x1F0C, - 0x1F090301: 0x1F0D, - 0x1F080342: 0x1F0E, - 0x1F090342: 0x1F0F, - 0x03B50313: 0x1F10, - 0x03B50314: 0x1F11, - 0x1F100300: 0x1F12, - 0x1F110300: 0x1F13, - 0x1F100301: 0x1F14, - 0x1F110301: 0x1F15, - 0x03950313: 0x1F18, - 0x03950314: 0x1F19, - 0x1F180300: 0x1F1A, - 0x1F190300: 0x1F1B, - 0x1F180301: 0x1F1C, - 0x1F190301: 0x1F1D, - 0x03B70313: 0x1F20, - 0x03B70314: 0x1F21, - 0x1F200300: 0x1F22, - 0x1F210300: 0x1F23, - 0x1F200301: 0x1F24, - 0x1F210301: 0x1F25, - 0x1F200342: 0x1F26, - 0x1F210342: 0x1F27, - 0x03970313: 0x1F28, - 0x03970314: 0x1F29, - 0x1F280300: 0x1F2A, - 0x1F290300: 0x1F2B, - 0x1F280301: 0x1F2C, - 0x1F290301: 0x1F2D, - 0x1F280342: 0x1F2E, - 0x1F290342: 0x1F2F, - 0x03B90313: 0x1F30, - 0x03B90314: 0x1F31, - 0x1F300300: 0x1F32, - 0x1F310300: 0x1F33, - 0x1F300301: 0x1F34, - 0x1F310301: 0x1F35, - 0x1F300342: 0x1F36, - 0x1F310342: 0x1F37, - 0x03990313: 0x1F38, - 0x03990314: 0x1F39, - 0x1F380300: 0x1F3A, - 0x1F390300: 0x1F3B, - 0x1F380301: 0x1F3C, - 0x1F390301: 0x1F3D, - 0x1F380342: 0x1F3E, - 0x1F390342: 0x1F3F, - 0x03BF0313: 0x1F40, - 0x03BF0314: 0x1F41, - 0x1F400300: 0x1F42, - 0x1F410300: 0x1F43, - 0x1F400301: 0x1F44, - 0x1F410301: 0x1F45, - 0x039F0313: 0x1F48, - 0x039F0314: 0x1F49, - 0x1F480300: 0x1F4A, - 0x1F490300: 0x1F4B, - 0x1F480301: 0x1F4C, - 0x1F490301: 0x1F4D, - 0x03C50313: 0x1F50, - 0x03C50314: 0x1F51, - 0x1F500300: 0x1F52, - 0x1F510300: 0x1F53, - 0x1F500301: 0x1F54, - 0x1F510301: 0x1F55, - 0x1F500342: 0x1F56, - 0x1F510342: 0x1F57, - 0x03A50314: 0x1F59, - 0x1F590300: 0x1F5B, - 0x1F590301: 0x1F5D, - 0x1F590342: 0x1F5F, - 0x03C90313: 0x1F60, - 0x03C90314: 0x1F61, - 0x1F600300: 0x1F62, - 0x1F610300: 0x1F63, - 0x1F600301: 0x1F64, - 0x1F610301: 0x1F65, - 0x1F600342: 0x1F66, - 0x1F610342: 0x1F67, - 0x03A90313: 0x1F68, - 0x03A90314: 0x1F69, - 0x1F680300: 0x1F6A, - 0x1F690300: 0x1F6B, - 0x1F680301: 0x1F6C, - 0x1F690301: 0x1F6D, - 0x1F680342: 0x1F6E, - 0x1F690342: 0x1F6F, - 0x03B10300: 0x1F70, - 0x03B50300: 0x1F72, - 0x03B70300: 0x1F74, - 0x03B90300: 0x1F76, - 0x03BF0300: 0x1F78, - 0x03C50300: 0x1F7A, - 0x03C90300: 0x1F7C, - 0x1F000345: 0x1F80, - 0x1F010345: 0x1F81, - 0x1F020345: 0x1F82, - 0x1F030345: 0x1F83, - 0x1F040345: 0x1F84, - 0x1F050345: 0x1F85, - 0x1F060345: 0x1F86, - 0x1F070345: 0x1F87, - 0x1F080345: 0x1F88, - 0x1F090345: 0x1F89, - 0x1F0A0345: 0x1F8A, - 0x1F0B0345: 0x1F8B, - 0x1F0C0345: 0x1F8C, - 0x1F0D0345: 0x1F8D, - 0x1F0E0345: 0x1F8E, - 0x1F0F0345: 0x1F8F, - 0x1F200345: 0x1F90, - 0x1F210345: 0x1F91, - 0x1F220345: 0x1F92, - 0x1F230345: 0x1F93, - 0x1F240345: 0x1F94, - 0x1F250345: 0x1F95, - 0x1F260345: 0x1F96, - 0x1F270345: 0x1F97, - 0x1F280345: 0x1F98, - 0x1F290345: 0x1F99, - 0x1F2A0345: 0x1F9A, - 0x1F2B0345: 0x1F9B, - 0x1F2C0345: 0x1F9C, - 0x1F2D0345: 0x1F9D, - 0x1F2E0345: 0x1F9E, - 0x1F2F0345: 0x1F9F, - 0x1F600345: 0x1FA0, - 0x1F610345: 0x1FA1, - 0x1F620345: 0x1FA2, - 0x1F630345: 0x1FA3, - 0x1F640345: 0x1FA4, - 0x1F650345: 0x1FA5, - 0x1F660345: 0x1FA6, - 0x1F670345: 0x1FA7, - 0x1F680345: 0x1FA8, - 0x1F690345: 0x1FA9, - 0x1F6A0345: 0x1FAA, - 0x1F6B0345: 0x1FAB, - 0x1F6C0345: 0x1FAC, - 0x1F6D0345: 0x1FAD, - 0x1F6E0345: 0x1FAE, - 0x1F6F0345: 0x1FAF, - 0x03B10306: 0x1FB0, - 0x03B10304: 0x1FB1, - 0x1F700345: 0x1FB2, - 0x03B10345: 0x1FB3, - 0x03AC0345: 0x1FB4, - 0x03B10342: 0x1FB6, - 0x1FB60345: 0x1FB7, - 0x03910306: 0x1FB8, - 0x03910304: 0x1FB9, - 0x03910300: 0x1FBA, - 0x03910345: 0x1FBC, - 0x00A80342: 0x1FC1, - 0x1F740345: 0x1FC2, - 0x03B70345: 0x1FC3, - 0x03AE0345: 0x1FC4, - 0x03B70342: 0x1FC6, - 0x1FC60345: 0x1FC7, - 0x03950300: 0x1FC8, - 0x03970300: 0x1FCA, - 0x03970345: 0x1FCC, - 0x1FBF0300: 0x1FCD, - 0x1FBF0301: 0x1FCE, - 0x1FBF0342: 0x1FCF, - 0x03B90306: 0x1FD0, - 0x03B90304: 0x1FD1, - 0x03CA0300: 0x1FD2, - 0x03B90342: 0x1FD6, - 0x03CA0342: 0x1FD7, - 0x03990306: 0x1FD8, - 0x03990304: 0x1FD9, - 0x03990300: 0x1FDA, - 0x1FFE0300: 0x1FDD, - 0x1FFE0301: 0x1FDE, - 0x1FFE0342: 0x1FDF, - 0x03C50306: 0x1FE0, - 0x03C50304: 0x1FE1, - 0x03CB0300: 0x1FE2, - 0x03C10313: 0x1FE4, - 0x03C10314: 0x1FE5, - 0x03C50342: 0x1FE6, - 0x03CB0342: 0x1FE7, - 0x03A50306: 0x1FE8, - 0x03A50304: 0x1FE9, - 0x03A50300: 0x1FEA, - 0x03A10314: 0x1FEC, - 0x00A80300: 0x1FED, - 0x1F7C0345: 0x1FF2, - 0x03C90345: 0x1FF3, - 0x03CE0345: 0x1FF4, - 0x03C90342: 0x1FF6, - 0x1FF60345: 0x1FF7, - 0x039F0300: 0x1FF8, - 0x03A90300: 0x1FFA, - 0x03A90345: 0x1FFC, - 0x21900338: 0x219A, - 0x21920338: 0x219B, - 0x21940338: 0x21AE, - 0x21D00338: 0x21CD, - 0x21D40338: 0x21CE, - 0x21D20338: 0x21CF, - 0x22030338: 0x2204, - 0x22080338: 0x2209, - 0x220B0338: 0x220C, - 0x22230338: 0x2224, - 0x22250338: 0x2226, - 0x223C0338: 0x2241, - 0x22430338: 0x2244, - 0x22450338: 0x2247, - 0x22480338: 0x2249, - 0x003D0338: 0x2260, - 0x22610338: 0x2262, - 0x224D0338: 0x226D, - 0x003C0338: 0x226E, - 0x003E0338: 0x226F, - 0x22640338: 0x2270, - 0x22650338: 0x2271, - 0x22720338: 0x2274, - 0x22730338: 0x2275, - 0x22760338: 0x2278, - 0x22770338: 0x2279, - 0x227A0338: 0x2280, - 0x227B0338: 0x2281, - 0x22820338: 0x2284, - 0x22830338: 0x2285, - 0x22860338: 0x2288, - 0x22870338: 0x2289, - 0x22A20338: 0x22AC, - 0x22A80338: 0x22AD, - 0x22A90338: 0x22AE, - 0x22AB0338: 0x22AF, - 0x227C0338: 0x22E0, - 0x227D0338: 0x22E1, - 0x22910338: 0x22E2, - 0x22920338: 0x22E3, - 0x22B20338: 0x22EA, - 0x22B30338: 0x22EB, - 0x22B40338: 0x22EC, - 0x22B50338: 0x22ED, - 0x304B3099: 0x304C, - 0x304D3099: 0x304E, - 0x304F3099: 0x3050, - 0x30513099: 0x3052, - 0x30533099: 0x3054, - 0x30553099: 0x3056, - 0x30573099: 0x3058, - 0x30593099: 0x305A, - 0x305B3099: 0x305C, - 0x305D3099: 0x305E, - 0x305F3099: 0x3060, - 0x30613099: 0x3062, - 0x30643099: 0x3065, - 0x30663099: 0x3067, - 0x30683099: 0x3069, - 0x306F3099: 0x3070, - 0x306F309A: 0x3071, - 0x30723099: 0x3073, - 0x3072309A: 0x3074, - 0x30753099: 0x3076, - 0x3075309A: 0x3077, - 0x30783099: 0x3079, - 0x3078309A: 0x307A, - 0x307B3099: 0x307C, - 0x307B309A: 0x307D, - 0x30463099: 0x3094, - 0x309D3099: 0x309E, - 0x30AB3099: 0x30AC, - 0x30AD3099: 0x30AE, - 0x30AF3099: 0x30B0, - 0x30B13099: 0x30B2, - 0x30B33099: 0x30B4, - 0x30B53099: 0x30B6, - 0x30B73099: 0x30B8, - 0x30B93099: 0x30BA, - 0x30BB3099: 0x30BC, - 0x30BD3099: 0x30BE, - 0x30BF3099: 0x30C0, - 0x30C13099: 0x30C2, - 0x30C43099: 0x30C5, - 0x30C63099: 0x30C7, - 0x30C83099: 0x30C9, - 0x30CF3099: 0x30D0, - 0x30CF309A: 0x30D1, - 0x30D23099: 0x30D3, - 0x30D2309A: 0x30D4, - 0x30D53099: 0x30D6, - 0x30D5309A: 0x30D7, - 0x30D83099: 0x30D9, - 0x30D8309A: 0x30DA, - 0x30DB3099: 0x30DC, - 0x30DB309A: 0x30DD, - 0x30A63099: 0x30F4, - 0x30EF3099: 0x30F7, - 0x30F03099: 0x30F8, - 0x30F13099: 0x30F9, - 0x30F23099: 0x30FA, - 0x30FD3099: 0x30FE, - 0x109910BA: 0x1109A, - 0x109B10BA: 0x1109C, - 0x10A510BA: 0x110AB, - 0x11311127: 0x1112E, - 0x11321127: 0x1112F, - 0x1347133E: 0x1134B, - 0x13471357: 0x1134C, - 0x14B914BA: 0x114BB, - 0x14B914B0: 0x114BC, - 0x14B914BD: 0x114BE, - 0x15B815AF: 0x115BA, - 0x15B915AF: 0x115BB, -} +var recompMap map[uint32]rune +var recompMapOnce sync.Once -// Total size of tables: 53KB (54006 bytes) +const recompMapPacked = "" + + "\x00A\x03\x00\x00\x00\x00\xc0" + // 0x00410300: 0x000000C0 + "\x00A\x03\x01\x00\x00\x00\xc1" + // 0x00410301: 0x000000C1 + "\x00A\x03\x02\x00\x00\x00\xc2" + // 0x00410302: 0x000000C2 + "\x00A\x03\x03\x00\x00\x00\xc3" + // 0x00410303: 0x000000C3 + "\x00A\x03\b\x00\x00\x00\xc4" + // 0x00410308: 0x000000C4 + "\x00A\x03\n\x00\x00\x00\xc5" + // 0x0041030A: 0x000000C5 + "\x00C\x03'\x00\x00\x00\xc7" + // 0x00430327: 0x000000C7 + "\x00E\x03\x00\x00\x00\x00\xc8" + // 0x00450300: 0x000000C8 + "\x00E\x03\x01\x00\x00\x00\xc9" + // 0x00450301: 0x000000C9 + "\x00E\x03\x02\x00\x00\x00\xca" + // 0x00450302: 0x000000CA + "\x00E\x03\b\x00\x00\x00\xcb" + // 0x00450308: 0x000000CB + "\x00I\x03\x00\x00\x00\x00\xcc" + // 0x00490300: 0x000000CC + "\x00I\x03\x01\x00\x00\x00\xcd" + // 0x00490301: 0x000000CD + "\x00I\x03\x02\x00\x00\x00\xce" + // 0x00490302: 0x000000CE + "\x00I\x03\b\x00\x00\x00\xcf" + // 0x00490308: 0x000000CF + "\x00N\x03\x03\x00\x00\x00\xd1" + // 0x004E0303: 0x000000D1 + "\x00O\x03\x00\x00\x00\x00\xd2" + // 0x004F0300: 0x000000D2 + "\x00O\x03\x01\x00\x00\x00\xd3" + // 0x004F0301: 0x000000D3 + "\x00O\x03\x02\x00\x00\x00\xd4" + // 0x004F0302: 0x000000D4 + "\x00O\x03\x03\x00\x00\x00\xd5" + // 0x004F0303: 0x000000D5 + "\x00O\x03\b\x00\x00\x00\xd6" + // 0x004F0308: 0x000000D6 + "\x00U\x03\x00\x00\x00\x00\xd9" + // 0x00550300: 0x000000D9 + "\x00U\x03\x01\x00\x00\x00\xda" + // 0x00550301: 0x000000DA + "\x00U\x03\x02\x00\x00\x00\xdb" + // 0x00550302: 0x000000DB + "\x00U\x03\b\x00\x00\x00\xdc" + // 0x00550308: 0x000000DC + "\x00Y\x03\x01\x00\x00\x00\xdd" + // 0x00590301: 0x000000DD + "\x00a\x03\x00\x00\x00\x00\xe0" + // 0x00610300: 0x000000E0 + "\x00a\x03\x01\x00\x00\x00\xe1" + // 0x00610301: 0x000000E1 + "\x00a\x03\x02\x00\x00\x00\xe2" + // 0x00610302: 0x000000E2 + "\x00a\x03\x03\x00\x00\x00\xe3" + // 0x00610303: 0x000000E3 + "\x00a\x03\b\x00\x00\x00\xe4" + // 0x00610308: 0x000000E4 + "\x00a\x03\n\x00\x00\x00\xe5" + // 0x0061030A: 0x000000E5 + "\x00c\x03'\x00\x00\x00\xe7" + // 0x00630327: 0x000000E7 + "\x00e\x03\x00\x00\x00\x00\xe8" + // 0x00650300: 0x000000E8 + "\x00e\x03\x01\x00\x00\x00\xe9" + // 0x00650301: 0x000000E9 + "\x00e\x03\x02\x00\x00\x00\xea" + // 0x00650302: 0x000000EA + "\x00e\x03\b\x00\x00\x00\xeb" + // 0x00650308: 0x000000EB + "\x00i\x03\x00\x00\x00\x00\xec" + // 0x00690300: 0x000000EC + "\x00i\x03\x01\x00\x00\x00\xed" + // 0x00690301: 0x000000ED + "\x00i\x03\x02\x00\x00\x00\xee" + // 0x00690302: 0x000000EE + "\x00i\x03\b\x00\x00\x00\xef" + // 0x00690308: 0x000000EF + "\x00n\x03\x03\x00\x00\x00\xf1" + // 0x006E0303: 0x000000F1 + "\x00o\x03\x00\x00\x00\x00\xf2" + // 0x006F0300: 0x000000F2 + "\x00o\x03\x01\x00\x00\x00\xf3" + // 0x006F0301: 0x000000F3 + "\x00o\x03\x02\x00\x00\x00\xf4" + // 0x006F0302: 0x000000F4 + "\x00o\x03\x03\x00\x00\x00\xf5" + // 0x006F0303: 0x000000F5 + "\x00o\x03\b\x00\x00\x00\xf6" + // 0x006F0308: 0x000000F6 + "\x00u\x03\x00\x00\x00\x00\xf9" + // 0x00750300: 0x000000F9 + "\x00u\x03\x01\x00\x00\x00\xfa" + // 0x00750301: 0x000000FA + "\x00u\x03\x02\x00\x00\x00\xfb" + // 0x00750302: 0x000000FB + "\x00u\x03\b\x00\x00\x00\xfc" + // 0x00750308: 0x000000FC + "\x00y\x03\x01\x00\x00\x00\xfd" + // 0x00790301: 0x000000FD + "\x00y\x03\b\x00\x00\x00\xff" + // 0x00790308: 0x000000FF + "\x00A\x03\x04\x00\x00\x01\x00" + // 0x00410304: 0x00000100 + "\x00a\x03\x04\x00\x00\x01\x01" + // 0x00610304: 0x00000101 + "\x00A\x03\x06\x00\x00\x01\x02" + // 0x00410306: 0x00000102 + "\x00a\x03\x06\x00\x00\x01\x03" + // 0x00610306: 0x00000103 + "\x00A\x03(\x00\x00\x01\x04" + // 0x00410328: 0x00000104 + "\x00a\x03(\x00\x00\x01\x05" + // 0x00610328: 0x00000105 + "\x00C\x03\x01\x00\x00\x01\x06" + // 0x00430301: 0x00000106 + "\x00c\x03\x01\x00\x00\x01\a" + // 0x00630301: 0x00000107 + "\x00C\x03\x02\x00\x00\x01\b" + // 0x00430302: 0x00000108 + "\x00c\x03\x02\x00\x00\x01\t" + // 0x00630302: 0x00000109 + "\x00C\x03\a\x00\x00\x01\n" + // 0x00430307: 0x0000010A + "\x00c\x03\a\x00\x00\x01\v" + // 0x00630307: 0x0000010B + "\x00C\x03\f\x00\x00\x01\f" + // 0x0043030C: 0x0000010C + "\x00c\x03\f\x00\x00\x01\r" + // 0x0063030C: 0x0000010D + "\x00D\x03\f\x00\x00\x01\x0e" + // 0x0044030C: 0x0000010E + "\x00d\x03\f\x00\x00\x01\x0f" + // 0x0064030C: 0x0000010F + "\x00E\x03\x04\x00\x00\x01\x12" + // 0x00450304: 0x00000112 + "\x00e\x03\x04\x00\x00\x01\x13" + // 0x00650304: 0x00000113 + "\x00E\x03\x06\x00\x00\x01\x14" + // 0x00450306: 0x00000114 + "\x00e\x03\x06\x00\x00\x01\x15" + // 0x00650306: 0x00000115 + "\x00E\x03\a\x00\x00\x01\x16" + // 0x00450307: 0x00000116 + "\x00e\x03\a\x00\x00\x01\x17" + // 0x00650307: 0x00000117 + "\x00E\x03(\x00\x00\x01\x18" + // 0x00450328: 0x00000118 + "\x00e\x03(\x00\x00\x01\x19" + // 0x00650328: 0x00000119 + "\x00E\x03\f\x00\x00\x01\x1a" + // 0x0045030C: 0x0000011A + "\x00e\x03\f\x00\x00\x01\x1b" + // 0x0065030C: 0x0000011B + "\x00G\x03\x02\x00\x00\x01\x1c" + // 0x00470302: 0x0000011C + "\x00g\x03\x02\x00\x00\x01\x1d" + // 0x00670302: 0x0000011D + "\x00G\x03\x06\x00\x00\x01\x1e" + // 0x00470306: 0x0000011E + "\x00g\x03\x06\x00\x00\x01\x1f" + // 0x00670306: 0x0000011F + "\x00G\x03\a\x00\x00\x01 " + // 0x00470307: 0x00000120 + "\x00g\x03\a\x00\x00\x01!" + // 0x00670307: 0x00000121 + "\x00G\x03'\x00\x00\x01\"" + // 0x00470327: 0x00000122 + "\x00g\x03'\x00\x00\x01#" + // 0x00670327: 0x00000123 + "\x00H\x03\x02\x00\x00\x01$" + // 0x00480302: 0x00000124 + "\x00h\x03\x02\x00\x00\x01%" + // 0x00680302: 0x00000125 + "\x00I\x03\x03\x00\x00\x01(" + // 0x00490303: 0x00000128 + "\x00i\x03\x03\x00\x00\x01)" + // 0x00690303: 0x00000129 + "\x00I\x03\x04\x00\x00\x01*" + // 0x00490304: 0x0000012A + "\x00i\x03\x04\x00\x00\x01+" + // 0x00690304: 0x0000012B + "\x00I\x03\x06\x00\x00\x01," + // 0x00490306: 0x0000012C + "\x00i\x03\x06\x00\x00\x01-" + // 0x00690306: 0x0000012D + "\x00I\x03(\x00\x00\x01." + // 0x00490328: 0x0000012E + "\x00i\x03(\x00\x00\x01/" + // 0x00690328: 0x0000012F + "\x00I\x03\a\x00\x00\x010" + // 0x00490307: 0x00000130 + "\x00J\x03\x02\x00\x00\x014" + // 0x004A0302: 0x00000134 + "\x00j\x03\x02\x00\x00\x015" + // 0x006A0302: 0x00000135 + "\x00K\x03'\x00\x00\x016" + // 0x004B0327: 0x00000136 + "\x00k\x03'\x00\x00\x017" + // 0x006B0327: 0x00000137 + "\x00L\x03\x01\x00\x00\x019" + // 0x004C0301: 0x00000139 + "\x00l\x03\x01\x00\x00\x01:" + // 0x006C0301: 0x0000013A + "\x00L\x03'\x00\x00\x01;" + // 0x004C0327: 0x0000013B + "\x00l\x03'\x00\x00\x01<" + // 0x006C0327: 0x0000013C + "\x00L\x03\f\x00\x00\x01=" + // 0x004C030C: 0x0000013D + "\x00l\x03\f\x00\x00\x01>" + // 0x006C030C: 0x0000013E + "\x00N\x03\x01\x00\x00\x01C" + // 0x004E0301: 0x00000143 + "\x00n\x03\x01\x00\x00\x01D" + // 0x006E0301: 0x00000144 + "\x00N\x03'\x00\x00\x01E" + // 0x004E0327: 0x00000145 + "\x00n\x03'\x00\x00\x01F" + // 0x006E0327: 0x00000146 + "\x00N\x03\f\x00\x00\x01G" + // 0x004E030C: 0x00000147 + "\x00n\x03\f\x00\x00\x01H" + // 0x006E030C: 0x00000148 + "\x00O\x03\x04\x00\x00\x01L" + // 0x004F0304: 0x0000014C + "\x00o\x03\x04\x00\x00\x01M" + // 0x006F0304: 0x0000014D + "\x00O\x03\x06\x00\x00\x01N" + // 0x004F0306: 0x0000014E + "\x00o\x03\x06\x00\x00\x01O" + // 0x006F0306: 0x0000014F + "\x00O\x03\v\x00\x00\x01P" + // 0x004F030B: 0x00000150 + "\x00o\x03\v\x00\x00\x01Q" + // 0x006F030B: 0x00000151 + "\x00R\x03\x01\x00\x00\x01T" + // 0x00520301: 0x00000154 + "\x00r\x03\x01\x00\x00\x01U" + // 0x00720301: 0x00000155 + "\x00R\x03'\x00\x00\x01V" + // 0x00520327: 0x00000156 + "\x00r\x03'\x00\x00\x01W" + // 0x00720327: 0x00000157 + "\x00R\x03\f\x00\x00\x01X" + // 0x0052030C: 0x00000158 + "\x00r\x03\f\x00\x00\x01Y" + // 0x0072030C: 0x00000159 + "\x00S\x03\x01\x00\x00\x01Z" + // 0x00530301: 0x0000015A + "\x00s\x03\x01\x00\x00\x01[" + // 0x00730301: 0x0000015B + "\x00S\x03\x02\x00\x00\x01\\" + // 0x00530302: 0x0000015C + "\x00s\x03\x02\x00\x00\x01]" + // 0x00730302: 0x0000015D + "\x00S\x03'\x00\x00\x01^" + // 0x00530327: 0x0000015E + "\x00s\x03'\x00\x00\x01_" + // 0x00730327: 0x0000015F + "\x00S\x03\f\x00\x00\x01`" + // 0x0053030C: 0x00000160 + "\x00s\x03\f\x00\x00\x01a" + // 0x0073030C: 0x00000161 + "\x00T\x03'\x00\x00\x01b" + // 0x00540327: 0x00000162 + "\x00t\x03'\x00\x00\x01c" + // 0x00740327: 0x00000163 + "\x00T\x03\f\x00\x00\x01d" + // 0x0054030C: 0x00000164 + "\x00t\x03\f\x00\x00\x01e" + // 0x0074030C: 0x00000165 + "\x00U\x03\x03\x00\x00\x01h" + // 0x00550303: 0x00000168 + "\x00u\x03\x03\x00\x00\x01i" + // 0x00750303: 0x00000169 + "\x00U\x03\x04\x00\x00\x01j" + // 0x00550304: 0x0000016A + "\x00u\x03\x04\x00\x00\x01k" + // 0x00750304: 0x0000016B + "\x00U\x03\x06\x00\x00\x01l" + // 0x00550306: 0x0000016C + "\x00u\x03\x06\x00\x00\x01m" + // 0x00750306: 0x0000016D + "\x00U\x03\n\x00\x00\x01n" + // 0x0055030A: 0x0000016E + "\x00u\x03\n\x00\x00\x01o" + // 0x0075030A: 0x0000016F + "\x00U\x03\v\x00\x00\x01p" + // 0x0055030B: 0x00000170 + "\x00u\x03\v\x00\x00\x01q" + // 0x0075030B: 0x00000171 + "\x00U\x03(\x00\x00\x01r" + // 0x00550328: 0x00000172 + "\x00u\x03(\x00\x00\x01s" + // 0x00750328: 0x00000173 + "\x00W\x03\x02\x00\x00\x01t" + // 0x00570302: 0x00000174 + "\x00w\x03\x02\x00\x00\x01u" + // 0x00770302: 0x00000175 + "\x00Y\x03\x02\x00\x00\x01v" + // 0x00590302: 0x00000176 + "\x00y\x03\x02\x00\x00\x01w" + // 0x00790302: 0x00000177 + "\x00Y\x03\b\x00\x00\x01x" + // 0x00590308: 0x00000178 + "\x00Z\x03\x01\x00\x00\x01y" + // 0x005A0301: 0x00000179 + "\x00z\x03\x01\x00\x00\x01z" + // 0x007A0301: 0x0000017A + "\x00Z\x03\a\x00\x00\x01{" + // 0x005A0307: 0x0000017B + "\x00z\x03\a\x00\x00\x01|" + // 0x007A0307: 0x0000017C + "\x00Z\x03\f\x00\x00\x01}" + // 0x005A030C: 0x0000017D + "\x00z\x03\f\x00\x00\x01~" + // 0x007A030C: 0x0000017E + "\x00O\x03\x1b\x00\x00\x01\xa0" + // 0x004F031B: 0x000001A0 + "\x00o\x03\x1b\x00\x00\x01\xa1" + // 0x006F031B: 0x000001A1 + "\x00U\x03\x1b\x00\x00\x01\xaf" + // 0x0055031B: 0x000001AF + "\x00u\x03\x1b\x00\x00\x01\xb0" + // 0x0075031B: 0x000001B0 + "\x00A\x03\f\x00\x00\x01\xcd" + // 0x0041030C: 0x000001CD + "\x00a\x03\f\x00\x00\x01\xce" + // 0x0061030C: 0x000001CE + "\x00I\x03\f\x00\x00\x01\xcf" + // 0x0049030C: 0x000001CF + "\x00i\x03\f\x00\x00\x01\xd0" + // 0x0069030C: 0x000001D0 + "\x00O\x03\f\x00\x00\x01\xd1" + // 0x004F030C: 0x000001D1 + "\x00o\x03\f\x00\x00\x01\xd2" + // 0x006F030C: 0x000001D2 + "\x00U\x03\f\x00\x00\x01\xd3" + // 0x0055030C: 0x000001D3 + "\x00u\x03\f\x00\x00\x01\xd4" + // 0x0075030C: 0x000001D4 + "\x00\xdc\x03\x04\x00\x00\x01\xd5" + // 0x00DC0304: 0x000001D5 + "\x00\xfc\x03\x04\x00\x00\x01\xd6" + // 0x00FC0304: 0x000001D6 + "\x00\xdc\x03\x01\x00\x00\x01\xd7" + // 0x00DC0301: 0x000001D7 + "\x00\xfc\x03\x01\x00\x00\x01\xd8" + // 0x00FC0301: 0x000001D8 + "\x00\xdc\x03\f\x00\x00\x01\xd9" + // 0x00DC030C: 0x000001D9 + "\x00\xfc\x03\f\x00\x00\x01\xda" + // 0x00FC030C: 0x000001DA + "\x00\xdc\x03\x00\x00\x00\x01\xdb" + // 0x00DC0300: 0x000001DB + "\x00\xfc\x03\x00\x00\x00\x01\xdc" + // 0x00FC0300: 0x000001DC + "\x00\xc4\x03\x04\x00\x00\x01\xde" + // 0x00C40304: 0x000001DE + "\x00\xe4\x03\x04\x00\x00\x01\xdf" + // 0x00E40304: 0x000001DF + "\x02&\x03\x04\x00\x00\x01\xe0" + // 0x02260304: 0x000001E0 + "\x02'\x03\x04\x00\x00\x01\xe1" + // 0x02270304: 0x000001E1 + "\x00\xc6\x03\x04\x00\x00\x01\xe2" + // 0x00C60304: 0x000001E2 + "\x00\xe6\x03\x04\x00\x00\x01\xe3" + // 0x00E60304: 0x000001E3 + "\x00G\x03\f\x00\x00\x01\xe6" + // 0x0047030C: 0x000001E6 + "\x00g\x03\f\x00\x00\x01\xe7" + // 0x0067030C: 0x000001E7 + "\x00K\x03\f\x00\x00\x01\xe8" + // 0x004B030C: 0x000001E8 + "\x00k\x03\f\x00\x00\x01\xe9" + // 0x006B030C: 0x000001E9 + "\x00O\x03(\x00\x00\x01\xea" + // 0x004F0328: 0x000001EA + "\x00o\x03(\x00\x00\x01\xeb" + // 0x006F0328: 0x000001EB + "\x01\xea\x03\x04\x00\x00\x01\xec" + // 0x01EA0304: 0x000001EC + "\x01\xeb\x03\x04\x00\x00\x01\xed" + // 0x01EB0304: 0x000001ED + "\x01\xb7\x03\f\x00\x00\x01\xee" + // 0x01B7030C: 0x000001EE + "\x02\x92\x03\f\x00\x00\x01\xef" + // 0x0292030C: 0x000001EF + "\x00j\x03\f\x00\x00\x01\xf0" + // 0x006A030C: 0x000001F0 + "\x00G\x03\x01\x00\x00\x01\xf4" + // 0x00470301: 0x000001F4 + "\x00g\x03\x01\x00\x00\x01\xf5" + // 0x00670301: 0x000001F5 + "\x00N\x03\x00\x00\x00\x01\xf8" + // 0x004E0300: 0x000001F8 + "\x00n\x03\x00\x00\x00\x01\xf9" + // 0x006E0300: 0x000001F9 + "\x00\xc5\x03\x01\x00\x00\x01\xfa" + // 0x00C50301: 0x000001FA + "\x00\xe5\x03\x01\x00\x00\x01\xfb" + // 0x00E50301: 0x000001FB + "\x00\xc6\x03\x01\x00\x00\x01\xfc" + // 0x00C60301: 0x000001FC + "\x00\xe6\x03\x01\x00\x00\x01\xfd" + // 0x00E60301: 0x000001FD + "\x00\xd8\x03\x01\x00\x00\x01\xfe" + // 0x00D80301: 0x000001FE + "\x00\xf8\x03\x01\x00\x00\x01\xff" + // 0x00F80301: 0x000001FF + "\x00A\x03\x0f\x00\x00\x02\x00" + // 0x0041030F: 0x00000200 + "\x00a\x03\x0f\x00\x00\x02\x01" + // 0x0061030F: 0x00000201 + "\x00A\x03\x11\x00\x00\x02\x02" + // 0x00410311: 0x00000202 + "\x00a\x03\x11\x00\x00\x02\x03" + // 0x00610311: 0x00000203 + "\x00E\x03\x0f\x00\x00\x02\x04" + // 0x0045030F: 0x00000204 + "\x00e\x03\x0f\x00\x00\x02\x05" + // 0x0065030F: 0x00000205 + "\x00E\x03\x11\x00\x00\x02\x06" + // 0x00450311: 0x00000206 + "\x00e\x03\x11\x00\x00\x02\a" + // 0x00650311: 0x00000207 + "\x00I\x03\x0f\x00\x00\x02\b" + // 0x0049030F: 0x00000208 + "\x00i\x03\x0f\x00\x00\x02\t" + // 0x0069030F: 0x00000209 + "\x00I\x03\x11\x00\x00\x02\n" + // 0x00490311: 0x0000020A + "\x00i\x03\x11\x00\x00\x02\v" + // 0x00690311: 0x0000020B + "\x00O\x03\x0f\x00\x00\x02\f" + // 0x004F030F: 0x0000020C + "\x00o\x03\x0f\x00\x00\x02\r" + // 0x006F030F: 0x0000020D + "\x00O\x03\x11\x00\x00\x02\x0e" + // 0x004F0311: 0x0000020E + "\x00o\x03\x11\x00\x00\x02\x0f" + // 0x006F0311: 0x0000020F + "\x00R\x03\x0f\x00\x00\x02\x10" + // 0x0052030F: 0x00000210 + "\x00r\x03\x0f\x00\x00\x02\x11" + // 0x0072030F: 0x00000211 + "\x00R\x03\x11\x00\x00\x02\x12" + // 0x00520311: 0x00000212 + "\x00r\x03\x11\x00\x00\x02\x13" + // 0x00720311: 0x00000213 + "\x00U\x03\x0f\x00\x00\x02\x14" + // 0x0055030F: 0x00000214 + "\x00u\x03\x0f\x00\x00\x02\x15" + // 0x0075030F: 0x00000215 + "\x00U\x03\x11\x00\x00\x02\x16" + // 0x00550311: 0x00000216 + "\x00u\x03\x11\x00\x00\x02\x17" + // 0x00750311: 0x00000217 + "\x00S\x03&\x00\x00\x02\x18" + // 0x00530326: 0x00000218 + "\x00s\x03&\x00\x00\x02\x19" + // 0x00730326: 0x00000219 + "\x00T\x03&\x00\x00\x02\x1a" + // 0x00540326: 0x0000021A + "\x00t\x03&\x00\x00\x02\x1b" + // 0x00740326: 0x0000021B + "\x00H\x03\f\x00\x00\x02\x1e" + // 0x0048030C: 0x0000021E + "\x00h\x03\f\x00\x00\x02\x1f" + // 0x0068030C: 0x0000021F + "\x00A\x03\a\x00\x00\x02&" + // 0x00410307: 0x00000226 + "\x00a\x03\a\x00\x00\x02'" + // 0x00610307: 0x00000227 + "\x00E\x03'\x00\x00\x02(" + // 0x00450327: 0x00000228 + "\x00e\x03'\x00\x00\x02)" + // 0x00650327: 0x00000229 + "\x00\xd6\x03\x04\x00\x00\x02*" + // 0x00D60304: 0x0000022A + "\x00\xf6\x03\x04\x00\x00\x02+" + // 0x00F60304: 0x0000022B + "\x00\xd5\x03\x04\x00\x00\x02," + // 0x00D50304: 0x0000022C + "\x00\xf5\x03\x04\x00\x00\x02-" + // 0x00F50304: 0x0000022D + "\x00O\x03\a\x00\x00\x02." + // 0x004F0307: 0x0000022E + "\x00o\x03\a\x00\x00\x02/" + // 0x006F0307: 0x0000022F + "\x02.\x03\x04\x00\x00\x020" + // 0x022E0304: 0x00000230 + "\x02/\x03\x04\x00\x00\x021" + // 0x022F0304: 0x00000231 + "\x00Y\x03\x04\x00\x00\x022" + // 0x00590304: 0x00000232 + "\x00y\x03\x04\x00\x00\x023" + // 0x00790304: 0x00000233 + "\x00\xa8\x03\x01\x00\x00\x03\x85" + // 0x00A80301: 0x00000385 + "\x03\x91\x03\x01\x00\x00\x03\x86" + // 0x03910301: 0x00000386 + "\x03\x95\x03\x01\x00\x00\x03\x88" + // 0x03950301: 0x00000388 + "\x03\x97\x03\x01\x00\x00\x03\x89" + // 0x03970301: 0x00000389 + "\x03\x99\x03\x01\x00\x00\x03\x8a" + // 0x03990301: 0x0000038A + "\x03\x9f\x03\x01\x00\x00\x03\x8c" + // 0x039F0301: 0x0000038C + "\x03\xa5\x03\x01\x00\x00\x03\x8e" + // 0x03A50301: 0x0000038E + "\x03\xa9\x03\x01\x00\x00\x03\x8f" + // 0x03A90301: 0x0000038F + "\x03\xca\x03\x01\x00\x00\x03\x90" + // 0x03CA0301: 0x00000390 + "\x03\x99\x03\b\x00\x00\x03\xaa" + // 0x03990308: 0x000003AA + "\x03\xa5\x03\b\x00\x00\x03\xab" + // 0x03A50308: 0x000003AB + "\x03\xb1\x03\x01\x00\x00\x03\xac" + // 0x03B10301: 0x000003AC + "\x03\xb5\x03\x01\x00\x00\x03\xad" + // 0x03B50301: 0x000003AD + "\x03\xb7\x03\x01\x00\x00\x03\xae" + // 0x03B70301: 0x000003AE + "\x03\xb9\x03\x01\x00\x00\x03\xaf" + // 0x03B90301: 0x000003AF + "\x03\xcb\x03\x01\x00\x00\x03\xb0" + // 0x03CB0301: 0x000003B0 + "\x03\xb9\x03\b\x00\x00\x03\xca" + // 0x03B90308: 0x000003CA + "\x03\xc5\x03\b\x00\x00\x03\xcb" + // 0x03C50308: 0x000003CB + "\x03\xbf\x03\x01\x00\x00\x03\xcc" + // 0x03BF0301: 0x000003CC + "\x03\xc5\x03\x01\x00\x00\x03\xcd" + // 0x03C50301: 0x000003CD + "\x03\xc9\x03\x01\x00\x00\x03\xce" + // 0x03C90301: 0x000003CE + "\x03\xd2\x03\x01\x00\x00\x03\xd3" + // 0x03D20301: 0x000003D3 + "\x03\xd2\x03\b\x00\x00\x03\xd4" + // 0x03D20308: 0x000003D4 + "\x04\x15\x03\x00\x00\x00\x04\x00" + // 0x04150300: 0x00000400 + "\x04\x15\x03\b\x00\x00\x04\x01" + // 0x04150308: 0x00000401 + "\x04\x13\x03\x01\x00\x00\x04\x03" + // 0x04130301: 0x00000403 + "\x04\x06\x03\b\x00\x00\x04\a" + // 0x04060308: 0x00000407 + "\x04\x1a\x03\x01\x00\x00\x04\f" + // 0x041A0301: 0x0000040C + "\x04\x18\x03\x00\x00\x00\x04\r" + // 0x04180300: 0x0000040D + "\x04#\x03\x06\x00\x00\x04\x0e" + // 0x04230306: 0x0000040E + "\x04\x18\x03\x06\x00\x00\x04\x19" + // 0x04180306: 0x00000419 + "\x048\x03\x06\x00\x00\x049" + // 0x04380306: 0x00000439 + "\x045\x03\x00\x00\x00\x04P" + // 0x04350300: 0x00000450 + "\x045\x03\b\x00\x00\x04Q" + // 0x04350308: 0x00000451 + "\x043\x03\x01\x00\x00\x04S" + // 0x04330301: 0x00000453 + "\x04V\x03\b\x00\x00\x04W" + // 0x04560308: 0x00000457 + "\x04:\x03\x01\x00\x00\x04\\" + // 0x043A0301: 0x0000045C + "\x048\x03\x00\x00\x00\x04]" + // 0x04380300: 0x0000045D + "\x04C\x03\x06\x00\x00\x04^" + // 0x04430306: 0x0000045E + "\x04t\x03\x0f\x00\x00\x04v" + // 0x0474030F: 0x00000476 + "\x04u\x03\x0f\x00\x00\x04w" + // 0x0475030F: 0x00000477 + "\x04\x16\x03\x06\x00\x00\x04\xc1" + // 0x04160306: 0x000004C1 + "\x046\x03\x06\x00\x00\x04\xc2" + // 0x04360306: 0x000004C2 + "\x04\x10\x03\x06\x00\x00\x04\xd0" + // 0x04100306: 0x000004D0 + "\x040\x03\x06\x00\x00\x04\xd1" + // 0x04300306: 0x000004D1 + "\x04\x10\x03\b\x00\x00\x04\xd2" + // 0x04100308: 0x000004D2 + "\x040\x03\b\x00\x00\x04\xd3" + // 0x04300308: 0x000004D3 + "\x04\x15\x03\x06\x00\x00\x04\xd6" + // 0x04150306: 0x000004D6 + "\x045\x03\x06\x00\x00\x04\xd7" + // 0x04350306: 0x000004D7 + "\x04\xd8\x03\b\x00\x00\x04\xda" + // 0x04D80308: 0x000004DA + "\x04\xd9\x03\b\x00\x00\x04\xdb" + // 0x04D90308: 0x000004DB + "\x04\x16\x03\b\x00\x00\x04\xdc" + // 0x04160308: 0x000004DC + "\x046\x03\b\x00\x00\x04\xdd" + // 0x04360308: 0x000004DD + "\x04\x17\x03\b\x00\x00\x04\xde" + // 0x04170308: 0x000004DE + "\x047\x03\b\x00\x00\x04\xdf" + // 0x04370308: 0x000004DF + "\x04\x18\x03\x04\x00\x00\x04\xe2" + // 0x04180304: 0x000004E2 + "\x048\x03\x04\x00\x00\x04\xe3" + // 0x04380304: 0x000004E3 + "\x04\x18\x03\b\x00\x00\x04\xe4" + // 0x04180308: 0x000004E4 + "\x048\x03\b\x00\x00\x04\xe5" + // 0x04380308: 0x000004E5 + "\x04\x1e\x03\b\x00\x00\x04\xe6" + // 0x041E0308: 0x000004E6 + "\x04>\x03\b\x00\x00\x04\xe7" + // 0x043E0308: 0x000004E7 + "\x04\xe8\x03\b\x00\x00\x04\xea" + // 0x04E80308: 0x000004EA + "\x04\xe9\x03\b\x00\x00\x04\xeb" + // 0x04E90308: 0x000004EB + "\x04-\x03\b\x00\x00\x04\xec" + // 0x042D0308: 0x000004EC + "\x04M\x03\b\x00\x00\x04\xed" + // 0x044D0308: 0x000004ED + "\x04#\x03\x04\x00\x00\x04\xee" + // 0x04230304: 0x000004EE + "\x04C\x03\x04\x00\x00\x04\xef" + // 0x04430304: 0x000004EF + "\x04#\x03\b\x00\x00\x04\xf0" + // 0x04230308: 0x000004F0 + "\x04C\x03\b\x00\x00\x04\xf1" + // 0x04430308: 0x000004F1 + "\x04#\x03\v\x00\x00\x04\xf2" + // 0x0423030B: 0x000004F2 + "\x04C\x03\v\x00\x00\x04\xf3" + // 0x0443030B: 0x000004F3 + "\x04'\x03\b\x00\x00\x04\xf4" + // 0x04270308: 0x000004F4 + "\x04G\x03\b\x00\x00\x04\xf5" + // 0x04470308: 0x000004F5 + "\x04+\x03\b\x00\x00\x04\xf8" + // 0x042B0308: 0x000004F8 + "\x04K\x03\b\x00\x00\x04\xf9" + // 0x044B0308: 0x000004F9 + "\x06'\x06S\x00\x00\x06\"" + // 0x06270653: 0x00000622 + "\x06'\x06T\x00\x00\x06#" + // 0x06270654: 0x00000623 + "\x06H\x06T\x00\x00\x06$" + // 0x06480654: 0x00000624 + "\x06'\x06U\x00\x00\x06%" + // 0x06270655: 0x00000625 + "\x06J\x06T\x00\x00\x06&" + // 0x064A0654: 0x00000626 + "\x06\xd5\x06T\x00\x00\x06\xc0" + // 0x06D50654: 0x000006C0 + "\x06\xc1\x06T\x00\x00\x06\xc2" + // 0x06C10654: 0x000006C2 + "\x06\xd2\x06T\x00\x00\x06\xd3" + // 0x06D20654: 0x000006D3 + "\t(\t<\x00\x00\t)" + // 0x0928093C: 0x00000929 + "\t0\t<\x00\x00\t1" + // 0x0930093C: 0x00000931 + "\t3\t<\x00\x00\t4" + // 0x0933093C: 0x00000934 + "\t\xc7\t\xbe\x00\x00\t\xcb" + // 0x09C709BE: 0x000009CB + "\t\xc7\t\xd7\x00\x00\t\xcc" + // 0x09C709D7: 0x000009CC + "\vG\vV\x00\x00\vH" + // 0x0B470B56: 0x00000B48 + "\vG\v>\x00\x00\vK" + // 0x0B470B3E: 0x00000B4B + "\vG\vW\x00\x00\vL" + // 0x0B470B57: 0x00000B4C + "\v\x92\v\xd7\x00\x00\v\x94" + // 0x0B920BD7: 0x00000B94 + "\v\xc6\v\xbe\x00\x00\v\xca" + // 0x0BC60BBE: 0x00000BCA + "\v\xc7\v\xbe\x00\x00\v\xcb" + // 0x0BC70BBE: 0x00000BCB + "\v\xc6\v\xd7\x00\x00\v\xcc" + // 0x0BC60BD7: 0x00000BCC + "\fF\fV\x00\x00\fH" + // 0x0C460C56: 0x00000C48 + "\f\xbf\f\xd5\x00\x00\f\xc0" + // 0x0CBF0CD5: 0x00000CC0 + "\f\xc6\f\xd5\x00\x00\f\xc7" + // 0x0CC60CD5: 0x00000CC7 + "\f\xc6\f\xd6\x00\x00\f\xc8" + // 0x0CC60CD6: 0x00000CC8 + "\f\xc6\f\xc2\x00\x00\f\xca" + // 0x0CC60CC2: 0x00000CCA + "\f\xca\f\xd5\x00\x00\f\xcb" + // 0x0CCA0CD5: 0x00000CCB + "\rF\r>\x00\x00\rJ" + // 0x0D460D3E: 0x00000D4A + "\rG\r>\x00\x00\rK" + // 0x0D470D3E: 0x00000D4B + "\rF\rW\x00\x00\rL" + // 0x0D460D57: 0x00000D4C + "\r\xd9\r\xca\x00\x00\r\xda" + // 0x0DD90DCA: 0x00000DDA + "\r\xd9\r\xcf\x00\x00\r\xdc" + // 0x0DD90DCF: 0x00000DDC + "\r\xdc\r\xca\x00\x00\r\xdd" + // 0x0DDC0DCA: 0x00000DDD + "\r\xd9\r\xdf\x00\x00\r\xde" + // 0x0DD90DDF: 0x00000DDE + "\x10%\x10.\x00\x00\x10&" + // 0x1025102E: 0x00001026 + "\x1b\x05\x1b5\x00\x00\x1b\x06" + // 0x1B051B35: 0x00001B06 + "\x1b\a\x1b5\x00\x00\x1b\b" + // 0x1B071B35: 0x00001B08 + "\x1b\t\x1b5\x00\x00\x1b\n" + // 0x1B091B35: 0x00001B0A + "\x1b\v\x1b5\x00\x00\x1b\f" + // 0x1B0B1B35: 0x00001B0C + "\x1b\r\x1b5\x00\x00\x1b\x0e" + // 0x1B0D1B35: 0x00001B0E + "\x1b\x11\x1b5\x00\x00\x1b\x12" + // 0x1B111B35: 0x00001B12 + "\x1b:\x1b5\x00\x00\x1b;" + // 0x1B3A1B35: 0x00001B3B + "\x1b<\x1b5\x00\x00\x1b=" + // 0x1B3C1B35: 0x00001B3D + "\x1b>\x1b5\x00\x00\x1b@" + // 0x1B3E1B35: 0x00001B40 + "\x1b?\x1b5\x00\x00\x1bA" + // 0x1B3F1B35: 0x00001B41 + "\x1bB\x1b5\x00\x00\x1bC" + // 0x1B421B35: 0x00001B43 + "\x00A\x03%\x00\x00\x1e\x00" + // 0x00410325: 0x00001E00 + "\x00a\x03%\x00\x00\x1e\x01" + // 0x00610325: 0x00001E01 + "\x00B\x03\a\x00\x00\x1e\x02" + // 0x00420307: 0x00001E02 + "\x00b\x03\a\x00\x00\x1e\x03" + // 0x00620307: 0x00001E03 + "\x00B\x03#\x00\x00\x1e\x04" + // 0x00420323: 0x00001E04 + "\x00b\x03#\x00\x00\x1e\x05" + // 0x00620323: 0x00001E05 + "\x00B\x031\x00\x00\x1e\x06" + // 0x00420331: 0x00001E06 + "\x00b\x031\x00\x00\x1e\a" + // 0x00620331: 0x00001E07 + "\x00\xc7\x03\x01\x00\x00\x1e\b" + // 0x00C70301: 0x00001E08 + "\x00\xe7\x03\x01\x00\x00\x1e\t" + // 0x00E70301: 0x00001E09 + "\x00D\x03\a\x00\x00\x1e\n" + // 0x00440307: 0x00001E0A + "\x00d\x03\a\x00\x00\x1e\v" + // 0x00640307: 0x00001E0B + "\x00D\x03#\x00\x00\x1e\f" + // 0x00440323: 0x00001E0C + "\x00d\x03#\x00\x00\x1e\r" + // 0x00640323: 0x00001E0D + "\x00D\x031\x00\x00\x1e\x0e" + // 0x00440331: 0x00001E0E + "\x00d\x031\x00\x00\x1e\x0f" + // 0x00640331: 0x00001E0F + "\x00D\x03'\x00\x00\x1e\x10" + // 0x00440327: 0x00001E10 + "\x00d\x03'\x00\x00\x1e\x11" + // 0x00640327: 0x00001E11 + "\x00D\x03-\x00\x00\x1e\x12" + // 0x0044032D: 0x00001E12 + "\x00d\x03-\x00\x00\x1e\x13" + // 0x0064032D: 0x00001E13 + "\x01\x12\x03\x00\x00\x00\x1e\x14" + // 0x01120300: 0x00001E14 + "\x01\x13\x03\x00\x00\x00\x1e\x15" + // 0x01130300: 0x00001E15 + "\x01\x12\x03\x01\x00\x00\x1e\x16" + // 0x01120301: 0x00001E16 + "\x01\x13\x03\x01\x00\x00\x1e\x17" + // 0x01130301: 0x00001E17 + "\x00E\x03-\x00\x00\x1e\x18" + // 0x0045032D: 0x00001E18 + "\x00e\x03-\x00\x00\x1e\x19" + // 0x0065032D: 0x00001E19 + "\x00E\x030\x00\x00\x1e\x1a" + // 0x00450330: 0x00001E1A + "\x00e\x030\x00\x00\x1e\x1b" + // 0x00650330: 0x00001E1B + "\x02(\x03\x06\x00\x00\x1e\x1c" + // 0x02280306: 0x00001E1C + "\x02)\x03\x06\x00\x00\x1e\x1d" + // 0x02290306: 0x00001E1D + "\x00F\x03\a\x00\x00\x1e\x1e" + // 0x00460307: 0x00001E1E + "\x00f\x03\a\x00\x00\x1e\x1f" + // 0x00660307: 0x00001E1F + "\x00G\x03\x04\x00\x00\x1e " + // 0x00470304: 0x00001E20 + "\x00g\x03\x04\x00\x00\x1e!" + // 0x00670304: 0x00001E21 + "\x00H\x03\a\x00\x00\x1e\"" + // 0x00480307: 0x00001E22 + "\x00h\x03\a\x00\x00\x1e#" + // 0x00680307: 0x00001E23 + "\x00H\x03#\x00\x00\x1e$" + // 0x00480323: 0x00001E24 + "\x00h\x03#\x00\x00\x1e%" + // 0x00680323: 0x00001E25 + "\x00H\x03\b\x00\x00\x1e&" + // 0x00480308: 0x00001E26 + "\x00h\x03\b\x00\x00\x1e'" + // 0x00680308: 0x00001E27 + "\x00H\x03'\x00\x00\x1e(" + // 0x00480327: 0x00001E28 + "\x00h\x03'\x00\x00\x1e)" + // 0x00680327: 0x00001E29 + "\x00H\x03.\x00\x00\x1e*" + // 0x0048032E: 0x00001E2A + "\x00h\x03.\x00\x00\x1e+" + // 0x0068032E: 0x00001E2B + "\x00I\x030\x00\x00\x1e," + // 0x00490330: 0x00001E2C + "\x00i\x030\x00\x00\x1e-" + // 0x00690330: 0x00001E2D + "\x00\xcf\x03\x01\x00\x00\x1e." + // 0x00CF0301: 0x00001E2E + "\x00\xef\x03\x01\x00\x00\x1e/" + // 0x00EF0301: 0x00001E2F + "\x00K\x03\x01\x00\x00\x1e0" + // 0x004B0301: 0x00001E30 + "\x00k\x03\x01\x00\x00\x1e1" + // 0x006B0301: 0x00001E31 + "\x00K\x03#\x00\x00\x1e2" + // 0x004B0323: 0x00001E32 + "\x00k\x03#\x00\x00\x1e3" + // 0x006B0323: 0x00001E33 + "\x00K\x031\x00\x00\x1e4" + // 0x004B0331: 0x00001E34 + "\x00k\x031\x00\x00\x1e5" + // 0x006B0331: 0x00001E35 + "\x00L\x03#\x00\x00\x1e6" + // 0x004C0323: 0x00001E36 + "\x00l\x03#\x00\x00\x1e7" + // 0x006C0323: 0x00001E37 + "\x1e6\x03\x04\x00\x00\x1e8" + // 0x1E360304: 0x00001E38 + "\x1e7\x03\x04\x00\x00\x1e9" + // 0x1E370304: 0x00001E39 + "\x00L\x031\x00\x00\x1e:" + // 0x004C0331: 0x00001E3A + "\x00l\x031\x00\x00\x1e;" + // 0x006C0331: 0x00001E3B + "\x00L\x03-\x00\x00\x1e<" + // 0x004C032D: 0x00001E3C + "\x00l\x03-\x00\x00\x1e=" + // 0x006C032D: 0x00001E3D + "\x00M\x03\x01\x00\x00\x1e>" + // 0x004D0301: 0x00001E3E + "\x00m\x03\x01\x00\x00\x1e?" + // 0x006D0301: 0x00001E3F + "\x00M\x03\a\x00\x00\x1e@" + // 0x004D0307: 0x00001E40 + "\x00m\x03\a\x00\x00\x1eA" + // 0x006D0307: 0x00001E41 + "\x00M\x03#\x00\x00\x1eB" + // 0x004D0323: 0x00001E42 + "\x00m\x03#\x00\x00\x1eC" + // 0x006D0323: 0x00001E43 + "\x00N\x03\a\x00\x00\x1eD" + // 0x004E0307: 0x00001E44 + "\x00n\x03\a\x00\x00\x1eE" + // 0x006E0307: 0x00001E45 + "\x00N\x03#\x00\x00\x1eF" + // 0x004E0323: 0x00001E46 + "\x00n\x03#\x00\x00\x1eG" + // 0x006E0323: 0x00001E47 + "\x00N\x031\x00\x00\x1eH" + // 0x004E0331: 0x00001E48 + "\x00n\x031\x00\x00\x1eI" + // 0x006E0331: 0x00001E49 + "\x00N\x03-\x00\x00\x1eJ" + // 0x004E032D: 0x00001E4A + "\x00n\x03-\x00\x00\x1eK" + // 0x006E032D: 0x00001E4B + "\x00\xd5\x03\x01\x00\x00\x1eL" + // 0x00D50301: 0x00001E4C + "\x00\xf5\x03\x01\x00\x00\x1eM" + // 0x00F50301: 0x00001E4D + "\x00\xd5\x03\b\x00\x00\x1eN" + // 0x00D50308: 0x00001E4E + "\x00\xf5\x03\b\x00\x00\x1eO" + // 0x00F50308: 0x00001E4F + "\x01L\x03\x00\x00\x00\x1eP" + // 0x014C0300: 0x00001E50 + "\x01M\x03\x00\x00\x00\x1eQ" + // 0x014D0300: 0x00001E51 + "\x01L\x03\x01\x00\x00\x1eR" + // 0x014C0301: 0x00001E52 + "\x01M\x03\x01\x00\x00\x1eS" + // 0x014D0301: 0x00001E53 + "\x00P\x03\x01\x00\x00\x1eT" + // 0x00500301: 0x00001E54 + "\x00p\x03\x01\x00\x00\x1eU" + // 0x00700301: 0x00001E55 + "\x00P\x03\a\x00\x00\x1eV" + // 0x00500307: 0x00001E56 + "\x00p\x03\a\x00\x00\x1eW" + // 0x00700307: 0x00001E57 + "\x00R\x03\a\x00\x00\x1eX" + // 0x00520307: 0x00001E58 + "\x00r\x03\a\x00\x00\x1eY" + // 0x00720307: 0x00001E59 + "\x00R\x03#\x00\x00\x1eZ" + // 0x00520323: 0x00001E5A + "\x00r\x03#\x00\x00\x1e[" + // 0x00720323: 0x00001E5B + "\x1eZ\x03\x04\x00\x00\x1e\\" + // 0x1E5A0304: 0x00001E5C + "\x1e[\x03\x04\x00\x00\x1e]" + // 0x1E5B0304: 0x00001E5D + "\x00R\x031\x00\x00\x1e^" + // 0x00520331: 0x00001E5E + "\x00r\x031\x00\x00\x1e_" + // 0x00720331: 0x00001E5F + "\x00S\x03\a\x00\x00\x1e`" + // 0x00530307: 0x00001E60 + "\x00s\x03\a\x00\x00\x1ea" + // 0x00730307: 0x00001E61 + "\x00S\x03#\x00\x00\x1eb" + // 0x00530323: 0x00001E62 + "\x00s\x03#\x00\x00\x1ec" + // 0x00730323: 0x00001E63 + "\x01Z\x03\a\x00\x00\x1ed" + // 0x015A0307: 0x00001E64 + "\x01[\x03\a\x00\x00\x1ee" + // 0x015B0307: 0x00001E65 + "\x01`\x03\a\x00\x00\x1ef" + // 0x01600307: 0x00001E66 + "\x01a\x03\a\x00\x00\x1eg" + // 0x01610307: 0x00001E67 + "\x1eb\x03\a\x00\x00\x1eh" + // 0x1E620307: 0x00001E68 + "\x1ec\x03\a\x00\x00\x1ei" + // 0x1E630307: 0x00001E69 + "\x00T\x03\a\x00\x00\x1ej" + // 0x00540307: 0x00001E6A + "\x00t\x03\a\x00\x00\x1ek" + // 0x00740307: 0x00001E6B + "\x00T\x03#\x00\x00\x1el" + // 0x00540323: 0x00001E6C + "\x00t\x03#\x00\x00\x1em" + // 0x00740323: 0x00001E6D + "\x00T\x031\x00\x00\x1en" + // 0x00540331: 0x00001E6E + "\x00t\x031\x00\x00\x1eo" + // 0x00740331: 0x00001E6F + "\x00T\x03-\x00\x00\x1ep" + // 0x0054032D: 0x00001E70 + "\x00t\x03-\x00\x00\x1eq" + // 0x0074032D: 0x00001E71 + "\x00U\x03$\x00\x00\x1er" + // 0x00550324: 0x00001E72 + "\x00u\x03$\x00\x00\x1es" + // 0x00750324: 0x00001E73 + "\x00U\x030\x00\x00\x1et" + // 0x00550330: 0x00001E74 + "\x00u\x030\x00\x00\x1eu" + // 0x00750330: 0x00001E75 + "\x00U\x03-\x00\x00\x1ev" + // 0x0055032D: 0x00001E76 + "\x00u\x03-\x00\x00\x1ew" + // 0x0075032D: 0x00001E77 + "\x01h\x03\x01\x00\x00\x1ex" + // 0x01680301: 0x00001E78 + "\x01i\x03\x01\x00\x00\x1ey" + // 0x01690301: 0x00001E79 + "\x01j\x03\b\x00\x00\x1ez" + // 0x016A0308: 0x00001E7A + "\x01k\x03\b\x00\x00\x1e{" + // 0x016B0308: 0x00001E7B + "\x00V\x03\x03\x00\x00\x1e|" + // 0x00560303: 0x00001E7C + "\x00v\x03\x03\x00\x00\x1e}" + // 0x00760303: 0x00001E7D + "\x00V\x03#\x00\x00\x1e~" + // 0x00560323: 0x00001E7E + "\x00v\x03#\x00\x00\x1e\u007f" + // 0x00760323: 0x00001E7F + "\x00W\x03\x00\x00\x00\x1e\x80" + // 0x00570300: 0x00001E80 + "\x00w\x03\x00\x00\x00\x1e\x81" + // 0x00770300: 0x00001E81 + "\x00W\x03\x01\x00\x00\x1e\x82" + // 0x00570301: 0x00001E82 + "\x00w\x03\x01\x00\x00\x1e\x83" + // 0x00770301: 0x00001E83 + "\x00W\x03\b\x00\x00\x1e\x84" + // 0x00570308: 0x00001E84 + "\x00w\x03\b\x00\x00\x1e\x85" + // 0x00770308: 0x00001E85 + "\x00W\x03\a\x00\x00\x1e\x86" + // 0x00570307: 0x00001E86 + "\x00w\x03\a\x00\x00\x1e\x87" + // 0x00770307: 0x00001E87 + "\x00W\x03#\x00\x00\x1e\x88" + // 0x00570323: 0x00001E88 + "\x00w\x03#\x00\x00\x1e\x89" + // 0x00770323: 0x00001E89 + "\x00X\x03\a\x00\x00\x1e\x8a" + // 0x00580307: 0x00001E8A + "\x00x\x03\a\x00\x00\x1e\x8b" + // 0x00780307: 0x00001E8B + "\x00X\x03\b\x00\x00\x1e\x8c" + // 0x00580308: 0x00001E8C + "\x00x\x03\b\x00\x00\x1e\x8d" + // 0x00780308: 0x00001E8D + "\x00Y\x03\a\x00\x00\x1e\x8e" + // 0x00590307: 0x00001E8E + "\x00y\x03\a\x00\x00\x1e\x8f" + // 0x00790307: 0x00001E8F + "\x00Z\x03\x02\x00\x00\x1e\x90" + // 0x005A0302: 0x00001E90 + "\x00z\x03\x02\x00\x00\x1e\x91" + // 0x007A0302: 0x00001E91 + "\x00Z\x03#\x00\x00\x1e\x92" + // 0x005A0323: 0x00001E92 + "\x00z\x03#\x00\x00\x1e\x93" + // 0x007A0323: 0x00001E93 + "\x00Z\x031\x00\x00\x1e\x94" + // 0x005A0331: 0x00001E94 + "\x00z\x031\x00\x00\x1e\x95" + // 0x007A0331: 0x00001E95 + "\x00h\x031\x00\x00\x1e\x96" + // 0x00680331: 0x00001E96 + "\x00t\x03\b\x00\x00\x1e\x97" + // 0x00740308: 0x00001E97 + "\x00w\x03\n\x00\x00\x1e\x98" + // 0x0077030A: 0x00001E98 + "\x00y\x03\n\x00\x00\x1e\x99" + // 0x0079030A: 0x00001E99 + "\x01\u007f\x03\a\x00\x00\x1e\x9b" + // 0x017F0307: 0x00001E9B + "\x00A\x03#\x00\x00\x1e\xa0" + // 0x00410323: 0x00001EA0 + "\x00a\x03#\x00\x00\x1e\xa1" + // 0x00610323: 0x00001EA1 + "\x00A\x03\t\x00\x00\x1e\xa2" + // 0x00410309: 0x00001EA2 + "\x00a\x03\t\x00\x00\x1e\xa3" + // 0x00610309: 0x00001EA3 + "\x00\xc2\x03\x01\x00\x00\x1e\xa4" + // 0x00C20301: 0x00001EA4 + "\x00\xe2\x03\x01\x00\x00\x1e\xa5" + // 0x00E20301: 0x00001EA5 + "\x00\xc2\x03\x00\x00\x00\x1e\xa6" + // 0x00C20300: 0x00001EA6 + "\x00\xe2\x03\x00\x00\x00\x1e\xa7" + // 0x00E20300: 0x00001EA7 + "\x00\xc2\x03\t\x00\x00\x1e\xa8" + // 0x00C20309: 0x00001EA8 + "\x00\xe2\x03\t\x00\x00\x1e\xa9" + // 0x00E20309: 0x00001EA9 + "\x00\xc2\x03\x03\x00\x00\x1e\xaa" + // 0x00C20303: 0x00001EAA + "\x00\xe2\x03\x03\x00\x00\x1e\xab" + // 0x00E20303: 0x00001EAB + "\x1e\xa0\x03\x02\x00\x00\x1e\xac" + // 0x1EA00302: 0x00001EAC + "\x1e\xa1\x03\x02\x00\x00\x1e\xad" + // 0x1EA10302: 0x00001EAD + "\x01\x02\x03\x01\x00\x00\x1e\xae" + // 0x01020301: 0x00001EAE + "\x01\x03\x03\x01\x00\x00\x1e\xaf" + // 0x01030301: 0x00001EAF + "\x01\x02\x03\x00\x00\x00\x1e\xb0" + // 0x01020300: 0x00001EB0 + "\x01\x03\x03\x00\x00\x00\x1e\xb1" + // 0x01030300: 0x00001EB1 + "\x01\x02\x03\t\x00\x00\x1e\xb2" + // 0x01020309: 0x00001EB2 + "\x01\x03\x03\t\x00\x00\x1e\xb3" + // 0x01030309: 0x00001EB3 + "\x01\x02\x03\x03\x00\x00\x1e\xb4" + // 0x01020303: 0x00001EB4 + "\x01\x03\x03\x03\x00\x00\x1e\xb5" + // 0x01030303: 0x00001EB5 + "\x1e\xa0\x03\x06\x00\x00\x1e\xb6" + // 0x1EA00306: 0x00001EB6 + "\x1e\xa1\x03\x06\x00\x00\x1e\xb7" + // 0x1EA10306: 0x00001EB7 + "\x00E\x03#\x00\x00\x1e\xb8" + // 0x00450323: 0x00001EB8 + "\x00e\x03#\x00\x00\x1e\xb9" + // 0x00650323: 0x00001EB9 + "\x00E\x03\t\x00\x00\x1e\xba" + // 0x00450309: 0x00001EBA + "\x00e\x03\t\x00\x00\x1e\xbb" + // 0x00650309: 0x00001EBB + "\x00E\x03\x03\x00\x00\x1e\xbc" + // 0x00450303: 0x00001EBC + "\x00e\x03\x03\x00\x00\x1e\xbd" + // 0x00650303: 0x00001EBD + "\x00\xca\x03\x01\x00\x00\x1e\xbe" + // 0x00CA0301: 0x00001EBE + "\x00\xea\x03\x01\x00\x00\x1e\xbf" + // 0x00EA0301: 0x00001EBF + "\x00\xca\x03\x00\x00\x00\x1e\xc0" + // 0x00CA0300: 0x00001EC0 + "\x00\xea\x03\x00\x00\x00\x1e\xc1" + // 0x00EA0300: 0x00001EC1 + "\x00\xca\x03\t\x00\x00\x1e\xc2" + // 0x00CA0309: 0x00001EC2 + "\x00\xea\x03\t\x00\x00\x1e\xc3" + // 0x00EA0309: 0x00001EC3 + "\x00\xca\x03\x03\x00\x00\x1e\xc4" + // 0x00CA0303: 0x00001EC4 + "\x00\xea\x03\x03\x00\x00\x1e\xc5" + // 0x00EA0303: 0x00001EC5 + "\x1e\xb8\x03\x02\x00\x00\x1e\xc6" + // 0x1EB80302: 0x00001EC6 + "\x1e\xb9\x03\x02\x00\x00\x1e\xc7" + // 0x1EB90302: 0x00001EC7 + "\x00I\x03\t\x00\x00\x1e\xc8" + // 0x00490309: 0x00001EC8 + "\x00i\x03\t\x00\x00\x1e\xc9" + // 0x00690309: 0x00001EC9 + "\x00I\x03#\x00\x00\x1e\xca" + // 0x00490323: 0x00001ECA + "\x00i\x03#\x00\x00\x1e\xcb" + // 0x00690323: 0x00001ECB + "\x00O\x03#\x00\x00\x1e\xcc" + // 0x004F0323: 0x00001ECC + "\x00o\x03#\x00\x00\x1e\xcd" + // 0x006F0323: 0x00001ECD + "\x00O\x03\t\x00\x00\x1e\xce" + // 0x004F0309: 0x00001ECE + "\x00o\x03\t\x00\x00\x1e\xcf" + // 0x006F0309: 0x00001ECF + "\x00\xd4\x03\x01\x00\x00\x1e\xd0" + // 0x00D40301: 0x00001ED0 + "\x00\xf4\x03\x01\x00\x00\x1e\xd1" + // 0x00F40301: 0x00001ED1 + "\x00\xd4\x03\x00\x00\x00\x1e\xd2" + // 0x00D40300: 0x00001ED2 + "\x00\xf4\x03\x00\x00\x00\x1e\xd3" + // 0x00F40300: 0x00001ED3 + "\x00\xd4\x03\t\x00\x00\x1e\xd4" + // 0x00D40309: 0x00001ED4 + "\x00\xf4\x03\t\x00\x00\x1e\xd5" + // 0x00F40309: 0x00001ED5 + "\x00\xd4\x03\x03\x00\x00\x1e\xd6" + // 0x00D40303: 0x00001ED6 + "\x00\xf4\x03\x03\x00\x00\x1e\xd7" + // 0x00F40303: 0x00001ED7 + "\x1e\xcc\x03\x02\x00\x00\x1e\xd8" + // 0x1ECC0302: 0x00001ED8 + "\x1e\xcd\x03\x02\x00\x00\x1e\xd9" + // 0x1ECD0302: 0x00001ED9 + "\x01\xa0\x03\x01\x00\x00\x1e\xda" + // 0x01A00301: 0x00001EDA + "\x01\xa1\x03\x01\x00\x00\x1e\xdb" + // 0x01A10301: 0x00001EDB + "\x01\xa0\x03\x00\x00\x00\x1e\xdc" + // 0x01A00300: 0x00001EDC + "\x01\xa1\x03\x00\x00\x00\x1e\xdd" + // 0x01A10300: 0x00001EDD + "\x01\xa0\x03\t\x00\x00\x1e\xde" + // 0x01A00309: 0x00001EDE + "\x01\xa1\x03\t\x00\x00\x1e\xdf" + // 0x01A10309: 0x00001EDF + "\x01\xa0\x03\x03\x00\x00\x1e\xe0" + // 0x01A00303: 0x00001EE0 + "\x01\xa1\x03\x03\x00\x00\x1e\xe1" + // 0x01A10303: 0x00001EE1 + "\x01\xa0\x03#\x00\x00\x1e\xe2" + // 0x01A00323: 0x00001EE2 + "\x01\xa1\x03#\x00\x00\x1e\xe3" + // 0x01A10323: 0x00001EE3 + "\x00U\x03#\x00\x00\x1e\xe4" + // 0x00550323: 0x00001EE4 + "\x00u\x03#\x00\x00\x1e\xe5" + // 0x00750323: 0x00001EE5 + "\x00U\x03\t\x00\x00\x1e\xe6" + // 0x00550309: 0x00001EE6 + "\x00u\x03\t\x00\x00\x1e\xe7" + // 0x00750309: 0x00001EE7 + "\x01\xaf\x03\x01\x00\x00\x1e\xe8" + // 0x01AF0301: 0x00001EE8 + "\x01\xb0\x03\x01\x00\x00\x1e\xe9" + // 0x01B00301: 0x00001EE9 + "\x01\xaf\x03\x00\x00\x00\x1e\xea" + // 0x01AF0300: 0x00001EEA + "\x01\xb0\x03\x00\x00\x00\x1e\xeb" + // 0x01B00300: 0x00001EEB + "\x01\xaf\x03\t\x00\x00\x1e\xec" + // 0x01AF0309: 0x00001EEC + "\x01\xb0\x03\t\x00\x00\x1e\xed" + // 0x01B00309: 0x00001EED + "\x01\xaf\x03\x03\x00\x00\x1e\xee" + // 0x01AF0303: 0x00001EEE + "\x01\xb0\x03\x03\x00\x00\x1e\xef" + // 0x01B00303: 0x00001EEF + "\x01\xaf\x03#\x00\x00\x1e\xf0" + // 0x01AF0323: 0x00001EF0 + "\x01\xb0\x03#\x00\x00\x1e\xf1" + // 0x01B00323: 0x00001EF1 + "\x00Y\x03\x00\x00\x00\x1e\xf2" + // 0x00590300: 0x00001EF2 + "\x00y\x03\x00\x00\x00\x1e\xf3" + // 0x00790300: 0x00001EF3 + "\x00Y\x03#\x00\x00\x1e\xf4" + // 0x00590323: 0x00001EF4 + "\x00y\x03#\x00\x00\x1e\xf5" + // 0x00790323: 0x00001EF5 + "\x00Y\x03\t\x00\x00\x1e\xf6" + // 0x00590309: 0x00001EF6 + "\x00y\x03\t\x00\x00\x1e\xf7" + // 0x00790309: 0x00001EF7 + "\x00Y\x03\x03\x00\x00\x1e\xf8" + // 0x00590303: 0x00001EF8 + "\x00y\x03\x03\x00\x00\x1e\xf9" + // 0x00790303: 0x00001EF9 + "\x03\xb1\x03\x13\x00\x00\x1f\x00" + // 0x03B10313: 0x00001F00 + "\x03\xb1\x03\x14\x00\x00\x1f\x01" + // 0x03B10314: 0x00001F01 + "\x1f\x00\x03\x00\x00\x00\x1f\x02" + // 0x1F000300: 0x00001F02 + "\x1f\x01\x03\x00\x00\x00\x1f\x03" + // 0x1F010300: 0x00001F03 + "\x1f\x00\x03\x01\x00\x00\x1f\x04" + // 0x1F000301: 0x00001F04 + "\x1f\x01\x03\x01\x00\x00\x1f\x05" + // 0x1F010301: 0x00001F05 + "\x1f\x00\x03B\x00\x00\x1f\x06" + // 0x1F000342: 0x00001F06 + "\x1f\x01\x03B\x00\x00\x1f\a" + // 0x1F010342: 0x00001F07 + "\x03\x91\x03\x13\x00\x00\x1f\b" + // 0x03910313: 0x00001F08 + "\x03\x91\x03\x14\x00\x00\x1f\t" + // 0x03910314: 0x00001F09 + "\x1f\b\x03\x00\x00\x00\x1f\n" + // 0x1F080300: 0x00001F0A + "\x1f\t\x03\x00\x00\x00\x1f\v" + // 0x1F090300: 0x00001F0B + "\x1f\b\x03\x01\x00\x00\x1f\f" + // 0x1F080301: 0x00001F0C + "\x1f\t\x03\x01\x00\x00\x1f\r" + // 0x1F090301: 0x00001F0D + "\x1f\b\x03B\x00\x00\x1f\x0e" + // 0x1F080342: 0x00001F0E + "\x1f\t\x03B\x00\x00\x1f\x0f" + // 0x1F090342: 0x00001F0F + "\x03\xb5\x03\x13\x00\x00\x1f\x10" + // 0x03B50313: 0x00001F10 + "\x03\xb5\x03\x14\x00\x00\x1f\x11" + // 0x03B50314: 0x00001F11 + "\x1f\x10\x03\x00\x00\x00\x1f\x12" + // 0x1F100300: 0x00001F12 + "\x1f\x11\x03\x00\x00\x00\x1f\x13" + // 0x1F110300: 0x00001F13 + "\x1f\x10\x03\x01\x00\x00\x1f\x14" + // 0x1F100301: 0x00001F14 + "\x1f\x11\x03\x01\x00\x00\x1f\x15" + // 0x1F110301: 0x00001F15 + "\x03\x95\x03\x13\x00\x00\x1f\x18" + // 0x03950313: 0x00001F18 + "\x03\x95\x03\x14\x00\x00\x1f\x19" + // 0x03950314: 0x00001F19 + "\x1f\x18\x03\x00\x00\x00\x1f\x1a" + // 0x1F180300: 0x00001F1A + "\x1f\x19\x03\x00\x00\x00\x1f\x1b" + // 0x1F190300: 0x00001F1B + "\x1f\x18\x03\x01\x00\x00\x1f\x1c" + // 0x1F180301: 0x00001F1C + "\x1f\x19\x03\x01\x00\x00\x1f\x1d" + // 0x1F190301: 0x00001F1D + "\x03\xb7\x03\x13\x00\x00\x1f " + // 0x03B70313: 0x00001F20 + "\x03\xb7\x03\x14\x00\x00\x1f!" + // 0x03B70314: 0x00001F21 + "\x1f \x03\x00\x00\x00\x1f\"" + // 0x1F200300: 0x00001F22 + "\x1f!\x03\x00\x00\x00\x1f#" + // 0x1F210300: 0x00001F23 + "\x1f \x03\x01\x00\x00\x1f$" + // 0x1F200301: 0x00001F24 + "\x1f!\x03\x01\x00\x00\x1f%" + // 0x1F210301: 0x00001F25 + "\x1f \x03B\x00\x00\x1f&" + // 0x1F200342: 0x00001F26 + "\x1f!\x03B\x00\x00\x1f'" + // 0x1F210342: 0x00001F27 + "\x03\x97\x03\x13\x00\x00\x1f(" + // 0x03970313: 0x00001F28 + "\x03\x97\x03\x14\x00\x00\x1f)" + // 0x03970314: 0x00001F29 + "\x1f(\x03\x00\x00\x00\x1f*" + // 0x1F280300: 0x00001F2A + "\x1f)\x03\x00\x00\x00\x1f+" + // 0x1F290300: 0x00001F2B + "\x1f(\x03\x01\x00\x00\x1f," + // 0x1F280301: 0x00001F2C + "\x1f)\x03\x01\x00\x00\x1f-" + // 0x1F290301: 0x00001F2D + "\x1f(\x03B\x00\x00\x1f." + // 0x1F280342: 0x00001F2E + "\x1f)\x03B\x00\x00\x1f/" + // 0x1F290342: 0x00001F2F + "\x03\xb9\x03\x13\x00\x00\x1f0" + // 0x03B90313: 0x00001F30 + "\x03\xb9\x03\x14\x00\x00\x1f1" + // 0x03B90314: 0x00001F31 + "\x1f0\x03\x00\x00\x00\x1f2" + // 0x1F300300: 0x00001F32 + "\x1f1\x03\x00\x00\x00\x1f3" + // 0x1F310300: 0x00001F33 + "\x1f0\x03\x01\x00\x00\x1f4" + // 0x1F300301: 0x00001F34 + "\x1f1\x03\x01\x00\x00\x1f5" + // 0x1F310301: 0x00001F35 + "\x1f0\x03B\x00\x00\x1f6" + // 0x1F300342: 0x00001F36 + "\x1f1\x03B\x00\x00\x1f7" + // 0x1F310342: 0x00001F37 + "\x03\x99\x03\x13\x00\x00\x1f8" + // 0x03990313: 0x00001F38 + "\x03\x99\x03\x14\x00\x00\x1f9" + // 0x03990314: 0x00001F39 + "\x1f8\x03\x00\x00\x00\x1f:" + // 0x1F380300: 0x00001F3A + "\x1f9\x03\x00\x00\x00\x1f;" + // 0x1F390300: 0x00001F3B + "\x1f8\x03\x01\x00\x00\x1f<" + // 0x1F380301: 0x00001F3C + "\x1f9\x03\x01\x00\x00\x1f=" + // 0x1F390301: 0x00001F3D + "\x1f8\x03B\x00\x00\x1f>" + // 0x1F380342: 0x00001F3E + "\x1f9\x03B\x00\x00\x1f?" + // 0x1F390342: 0x00001F3F + "\x03\xbf\x03\x13\x00\x00\x1f@" + // 0x03BF0313: 0x00001F40 + "\x03\xbf\x03\x14\x00\x00\x1fA" + // 0x03BF0314: 0x00001F41 + "\x1f@\x03\x00\x00\x00\x1fB" + // 0x1F400300: 0x00001F42 + "\x1fA\x03\x00\x00\x00\x1fC" + // 0x1F410300: 0x00001F43 + "\x1f@\x03\x01\x00\x00\x1fD" + // 0x1F400301: 0x00001F44 + "\x1fA\x03\x01\x00\x00\x1fE" + // 0x1F410301: 0x00001F45 + "\x03\x9f\x03\x13\x00\x00\x1fH" + // 0x039F0313: 0x00001F48 + "\x03\x9f\x03\x14\x00\x00\x1fI" + // 0x039F0314: 0x00001F49 + "\x1fH\x03\x00\x00\x00\x1fJ" + // 0x1F480300: 0x00001F4A + "\x1fI\x03\x00\x00\x00\x1fK" + // 0x1F490300: 0x00001F4B + "\x1fH\x03\x01\x00\x00\x1fL" + // 0x1F480301: 0x00001F4C + "\x1fI\x03\x01\x00\x00\x1fM" + // 0x1F490301: 0x00001F4D + "\x03\xc5\x03\x13\x00\x00\x1fP" + // 0x03C50313: 0x00001F50 + "\x03\xc5\x03\x14\x00\x00\x1fQ" + // 0x03C50314: 0x00001F51 + "\x1fP\x03\x00\x00\x00\x1fR" + // 0x1F500300: 0x00001F52 + "\x1fQ\x03\x00\x00\x00\x1fS" + // 0x1F510300: 0x00001F53 + "\x1fP\x03\x01\x00\x00\x1fT" + // 0x1F500301: 0x00001F54 + "\x1fQ\x03\x01\x00\x00\x1fU" + // 0x1F510301: 0x00001F55 + "\x1fP\x03B\x00\x00\x1fV" + // 0x1F500342: 0x00001F56 + "\x1fQ\x03B\x00\x00\x1fW" + // 0x1F510342: 0x00001F57 + "\x03\xa5\x03\x14\x00\x00\x1fY" + // 0x03A50314: 0x00001F59 + "\x1fY\x03\x00\x00\x00\x1f[" + // 0x1F590300: 0x00001F5B + "\x1fY\x03\x01\x00\x00\x1f]" + // 0x1F590301: 0x00001F5D + "\x1fY\x03B\x00\x00\x1f_" + // 0x1F590342: 0x00001F5F + "\x03\xc9\x03\x13\x00\x00\x1f`" + // 0x03C90313: 0x00001F60 + "\x03\xc9\x03\x14\x00\x00\x1fa" + // 0x03C90314: 0x00001F61 + "\x1f`\x03\x00\x00\x00\x1fb" + // 0x1F600300: 0x00001F62 + "\x1fa\x03\x00\x00\x00\x1fc" + // 0x1F610300: 0x00001F63 + "\x1f`\x03\x01\x00\x00\x1fd" + // 0x1F600301: 0x00001F64 + "\x1fa\x03\x01\x00\x00\x1fe" + // 0x1F610301: 0x00001F65 + "\x1f`\x03B\x00\x00\x1ff" + // 0x1F600342: 0x00001F66 + "\x1fa\x03B\x00\x00\x1fg" + // 0x1F610342: 0x00001F67 + "\x03\xa9\x03\x13\x00\x00\x1fh" + // 0x03A90313: 0x00001F68 + "\x03\xa9\x03\x14\x00\x00\x1fi" + // 0x03A90314: 0x00001F69 + "\x1fh\x03\x00\x00\x00\x1fj" + // 0x1F680300: 0x00001F6A + "\x1fi\x03\x00\x00\x00\x1fk" + // 0x1F690300: 0x00001F6B + "\x1fh\x03\x01\x00\x00\x1fl" + // 0x1F680301: 0x00001F6C + "\x1fi\x03\x01\x00\x00\x1fm" + // 0x1F690301: 0x00001F6D + "\x1fh\x03B\x00\x00\x1fn" + // 0x1F680342: 0x00001F6E + "\x1fi\x03B\x00\x00\x1fo" + // 0x1F690342: 0x00001F6F + "\x03\xb1\x03\x00\x00\x00\x1fp" + // 0x03B10300: 0x00001F70 + "\x03\xb5\x03\x00\x00\x00\x1fr" + // 0x03B50300: 0x00001F72 + "\x03\xb7\x03\x00\x00\x00\x1ft" + // 0x03B70300: 0x00001F74 + "\x03\xb9\x03\x00\x00\x00\x1fv" + // 0x03B90300: 0x00001F76 + "\x03\xbf\x03\x00\x00\x00\x1fx" + // 0x03BF0300: 0x00001F78 + "\x03\xc5\x03\x00\x00\x00\x1fz" + // 0x03C50300: 0x00001F7A + "\x03\xc9\x03\x00\x00\x00\x1f|" + // 0x03C90300: 0x00001F7C + "\x1f\x00\x03E\x00\x00\x1f\x80" + // 0x1F000345: 0x00001F80 + "\x1f\x01\x03E\x00\x00\x1f\x81" + // 0x1F010345: 0x00001F81 + "\x1f\x02\x03E\x00\x00\x1f\x82" + // 0x1F020345: 0x00001F82 + "\x1f\x03\x03E\x00\x00\x1f\x83" + // 0x1F030345: 0x00001F83 + "\x1f\x04\x03E\x00\x00\x1f\x84" + // 0x1F040345: 0x00001F84 + "\x1f\x05\x03E\x00\x00\x1f\x85" + // 0x1F050345: 0x00001F85 + "\x1f\x06\x03E\x00\x00\x1f\x86" + // 0x1F060345: 0x00001F86 + "\x1f\a\x03E\x00\x00\x1f\x87" + // 0x1F070345: 0x00001F87 + "\x1f\b\x03E\x00\x00\x1f\x88" + // 0x1F080345: 0x00001F88 + "\x1f\t\x03E\x00\x00\x1f\x89" + // 0x1F090345: 0x00001F89 + "\x1f\n\x03E\x00\x00\x1f\x8a" + // 0x1F0A0345: 0x00001F8A + "\x1f\v\x03E\x00\x00\x1f\x8b" + // 0x1F0B0345: 0x00001F8B + "\x1f\f\x03E\x00\x00\x1f\x8c" + // 0x1F0C0345: 0x00001F8C + "\x1f\r\x03E\x00\x00\x1f\x8d" + // 0x1F0D0345: 0x00001F8D + "\x1f\x0e\x03E\x00\x00\x1f\x8e" + // 0x1F0E0345: 0x00001F8E + "\x1f\x0f\x03E\x00\x00\x1f\x8f" + // 0x1F0F0345: 0x00001F8F + "\x1f \x03E\x00\x00\x1f\x90" + // 0x1F200345: 0x00001F90 + "\x1f!\x03E\x00\x00\x1f\x91" + // 0x1F210345: 0x00001F91 + "\x1f\"\x03E\x00\x00\x1f\x92" + // 0x1F220345: 0x00001F92 + "\x1f#\x03E\x00\x00\x1f\x93" + // 0x1F230345: 0x00001F93 + "\x1f$\x03E\x00\x00\x1f\x94" + // 0x1F240345: 0x00001F94 + "\x1f%\x03E\x00\x00\x1f\x95" + // 0x1F250345: 0x00001F95 + "\x1f&\x03E\x00\x00\x1f\x96" + // 0x1F260345: 0x00001F96 + "\x1f'\x03E\x00\x00\x1f\x97" + // 0x1F270345: 0x00001F97 + "\x1f(\x03E\x00\x00\x1f\x98" + // 0x1F280345: 0x00001F98 + "\x1f)\x03E\x00\x00\x1f\x99" + // 0x1F290345: 0x00001F99 + "\x1f*\x03E\x00\x00\x1f\x9a" + // 0x1F2A0345: 0x00001F9A + "\x1f+\x03E\x00\x00\x1f\x9b" + // 0x1F2B0345: 0x00001F9B + "\x1f,\x03E\x00\x00\x1f\x9c" + // 0x1F2C0345: 0x00001F9C + "\x1f-\x03E\x00\x00\x1f\x9d" + // 0x1F2D0345: 0x00001F9D + "\x1f.\x03E\x00\x00\x1f\x9e" + // 0x1F2E0345: 0x00001F9E + "\x1f/\x03E\x00\x00\x1f\x9f" + // 0x1F2F0345: 0x00001F9F + "\x1f`\x03E\x00\x00\x1f\xa0" + // 0x1F600345: 0x00001FA0 + "\x1fa\x03E\x00\x00\x1f\xa1" + // 0x1F610345: 0x00001FA1 + "\x1fb\x03E\x00\x00\x1f\xa2" + // 0x1F620345: 0x00001FA2 + "\x1fc\x03E\x00\x00\x1f\xa3" + // 0x1F630345: 0x00001FA3 + "\x1fd\x03E\x00\x00\x1f\xa4" + // 0x1F640345: 0x00001FA4 + "\x1fe\x03E\x00\x00\x1f\xa5" + // 0x1F650345: 0x00001FA5 + "\x1ff\x03E\x00\x00\x1f\xa6" + // 0x1F660345: 0x00001FA6 + "\x1fg\x03E\x00\x00\x1f\xa7" + // 0x1F670345: 0x00001FA7 + "\x1fh\x03E\x00\x00\x1f\xa8" + // 0x1F680345: 0x00001FA8 + "\x1fi\x03E\x00\x00\x1f\xa9" + // 0x1F690345: 0x00001FA9 + "\x1fj\x03E\x00\x00\x1f\xaa" + // 0x1F6A0345: 0x00001FAA + "\x1fk\x03E\x00\x00\x1f\xab" + // 0x1F6B0345: 0x00001FAB + "\x1fl\x03E\x00\x00\x1f\xac" + // 0x1F6C0345: 0x00001FAC + "\x1fm\x03E\x00\x00\x1f\xad" + // 0x1F6D0345: 0x00001FAD + "\x1fn\x03E\x00\x00\x1f\xae" + // 0x1F6E0345: 0x00001FAE + "\x1fo\x03E\x00\x00\x1f\xaf" + // 0x1F6F0345: 0x00001FAF + "\x03\xb1\x03\x06\x00\x00\x1f\xb0" + // 0x03B10306: 0x00001FB0 + "\x03\xb1\x03\x04\x00\x00\x1f\xb1" + // 0x03B10304: 0x00001FB1 + "\x1fp\x03E\x00\x00\x1f\xb2" + // 0x1F700345: 0x00001FB2 + "\x03\xb1\x03E\x00\x00\x1f\xb3" + // 0x03B10345: 0x00001FB3 + "\x03\xac\x03E\x00\x00\x1f\xb4" + // 0x03AC0345: 0x00001FB4 + "\x03\xb1\x03B\x00\x00\x1f\xb6" + // 0x03B10342: 0x00001FB6 + "\x1f\xb6\x03E\x00\x00\x1f\xb7" + // 0x1FB60345: 0x00001FB7 + "\x03\x91\x03\x06\x00\x00\x1f\xb8" + // 0x03910306: 0x00001FB8 + "\x03\x91\x03\x04\x00\x00\x1f\xb9" + // 0x03910304: 0x00001FB9 + "\x03\x91\x03\x00\x00\x00\x1f\xba" + // 0x03910300: 0x00001FBA + "\x03\x91\x03E\x00\x00\x1f\xbc" + // 0x03910345: 0x00001FBC + "\x00\xa8\x03B\x00\x00\x1f\xc1" + // 0x00A80342: 0x00001FC1 + "\x1ft\x03E\x00\x00\x1f\xc2" + // 0x1F740345: 0x00001FC2 + "\x03\xb7\x03E\x00\x00\x1f\xc3" + // 0x03B70345: 0x00001FC3 + "\x03\xae\x03E\x00\x00\x1f\xc4" + // 0x03AE0345: 0x00001FC4 + "\x03\xb7\x03B\x00\x00\x1f\xc6" + // 0x03B70342: 0x00001FC6 + "\x1f\xc6\x03E\x00\x00\x1f\xc7" + // 0x1FC60345: 0x00001FC7 + "\x03\x95\x03\x00\x00\x00\x1f\xc8" + // 0x03950300: 0x00001FC8 + "\x03\x97\x03\x00\x00\x00\x1f\xca" + // 0x03970300: 0x00001FCA + "\x03\x97\x03E\x00\x00\x1f\xcc" + // 0x03970345: 0x00001FCC + "\x1f\xbf\x03\x00\x00\x00\x1f\xcd" + // 0x1FBF0300: 0x00001FCD + "\x1f\xbf\x03\x01\x00\x00\x1f\xce" + // 0x1FBF0301: 0x00001FCE + "\x1f\xbf\x03B\x00\x00\x1f\xcf" + // 0x1FBF0342: 0x00001FCF + "\x03\xb9\x03\x06\x00\x00\x1f\xd0" + // 0x03B90306: 0x00001FD0 + "\x03\xb9\x03\x04\x00\x00\x1f\xd1" + // 0x03B90304: 0x00001FD1 + "\x03\xca\x03\x00\x00\x00\x1f\xd2" + // 0x03CA0300: 0x00001FD2 + "\x03\xb9\x03B\x00\x00\x1f\xd6" + // 0x03B90342: 0x00001FD6 + "\x03\xca\x03B\x00\x00\x1f\xd7" + // 0x03CA0342: 0x00001FD7 + "\x03\x99\x03\x06\x00\x00\x1f\xd8" + // 0x03990306: 0x00001FD8 + "\x03\x99\x03\x04\x00\x00\x1f\xd9" + // 0x03990304: 0x00001FD9 + "\x03\x99\x03\x00\x00\x00\x1f\xda" + // 0x03990300: 0x00001FDA + "\x1f\xfe\x03\x00\x00\x00\x1f\xdd" + // 0x1FFE0300: 0x00001FDD + "\x1f\xfe\x03\x01\x00\x00\x1f\xde" + // 0x1FFE0301: 0x00001FDE + "\x1f\xfe\x03B\x00\x00\x1f\xdf" + // 0x1FFE0342: 0x00001FDF + "\x03\xc5\x03\x06\x00\x00\x1f\xe0" + // 0x03C50306: 0x00001FE0 + "\x03\xc5\x03\x04\x00\x00\x1f\xe1" + // 0x03C50304: 0x00001FE1 + "\x03\xcb\x03\x00\x00\x00\x1f\xe2" + // 0x03CB0300: 0x00001FE2 + "\x03\xc1\x03\x13\x00\x00\x1f\xe4" + // 0x03C10313: 0x00001FE4 + "\x03\xc1\x03\x14\x00\x00\x1f\xe5" + // 0x03C10314: 0x00001FE5 + "\x03\xc5\x03B\x00\x00\x1f\xe6" + // 0x03C50342: 0x00001FE6 + "\x03\xcb\x03B\x00\x00\x1f\xe7" + // 0x03CB0342: 0x00001FE7 + "\x03\xa5\x03\x06\x00\x00\x1f\xe8" + // 0x03A50306: 0x00001FE8 + "\x03\xa5\x03\x04\x00\x00\x1f\xe9" + // 0x03A50304: 0x00001FE9 + "\x03\xa5\x03\x00\x00\x00\x1f\xea" + // 0x03A50300: 0x00001FEA + "\x03\xa1\x03\x14\x00\x00\x1f\xec" + // 0x03A10314: 0x00001FEC + "\x00\xa8\x03\x00\x00\x00\x1f\xed" + // 0x00A80300: 0x00001FED + "\x1f|\x03E\x00\x00\x1f\xf2" + // 0x1F7C0345: 0x00001FF2 + "\x03\xc9\x03E\x00\x00\x1f\xf3" + // 0x03C90345: 0x00001FF3 + "\x03\xce\x03E\x00\x00\x1f\xf4" + // 0x03CE0345: 0x00001FF4 + "\x03\xc9\x03B\x00\x00\x1f\xf6" + // 0x03C90342: 0x00001FF6 + "\x1f\xf6\x03E\x00\x00\x1f\xf7" + // 0x1FF60345: 0x00001FF7 + "\x03\x9f\x03\x00\x00\x00\x1f\xf8" + // 0x039F0300: 0x00001FF8 + "\x03\xa9\x03\x00\x00\x00\x1f\xfa" + // 0x03A90300: 0x00001FFA + "\x03\xa9\x03E\x00\x00\x1f\xfc" + // 0x03A90345: 0x00001FFC + "!\x90\x038\x00\x00!\x9a" + // 0x21900338: 0x0000219A + "!\x92\x038\x00\x00!\x9b" + // 0x21920338: 0x0000219B + "!\x94\x038\x00\x00!\xae" + // 0x21940338: 0x000021AE + "!\xd0\x038\x00\x00!\xcd" + // 0x21D00338: 0x000021CD + "!\xd4\x038\x00\x00!\xce" + // 0x21D40338: 0x000021CE + "!\xd2\x038\x00\x00!\xcf" + // 0x21D20338: 0x000021CF + "\"\x03\x038\x00\x00\"\x04" + // 0x22030338: 0x00002204 + "\"\b\x038\x00\x00\"\t" + // 0x22080338: 0x00002209 + "\"\v\x038\x00\x00\"\f" + // 0x220B0338: 0x0000220C + "\"#\x038\x00\x00\"$" + // 0x22230338: 0x00002224 + "\"%\x038\x00\x00\"&" + // 0x22250338: 0x00002226 + "\"<\x038\x00\x00\"A" + // 0x223C0338: 0x00002241 + "\"C\x038\x00\x00\"D" + // 0x22430338: 0x00002244 + "\"E\x038\x00\x00\"G" + // 0x22450338: 0x00002247 + "\"H\x038\x00\x00\"I" + // 0x22480338: 0x00002249 + "\x00=\x038\x00\x00\"`" + // 0x003D0338: 0x00002260 + "\"a\x038\x00\x00\"b" + // 0x22610338: 0x00002262 + "\"M\x038\x00\x00\"m" + // 0x224D0338: 0x0000226D + "\x00<\x038\x00\x00\"n" + // 0x003C0338: 0x0000226E + "\x00>\x038\x00\x00\"o" + // 0x003E0338: 0x0000226F + "\"d\x038\x00\x00\"p" + // 0x22640338: 0x00002270 + "\"e\x038\x00\x00\"q" + // 0x22650338: 0x00002271 + "\"r\x038\x00\x00\"t" + // 0x22720338: 0x00002274 + "\"s\x038\x00\x00\"u" + // 0x22730338: 0x00002275 + "\"v\x038\x00\x00\"x" + // 0x22760338: 0x00002278 + "\"w\x038\x00\x00\"y" + // 0x22770338: 0x00002279 + "\"z\x038\x00\x00\"\x80" + // 0x227A0338: 0x00002280 + "\"{\x038\x00\x00\"\x81" + // 0x227B0338: 0x00002281 + "\"\x82\x038\x00\x00\"\x84" + // 0x22820338: 0x00002284 + "\"\x83\x038\x00\x00\"\x85" + // 0x22830338: 0x00002285 + "\"\x86\x038\x00\x00\"\x88" + // 0x22860338: 0x00002288 + "\"\x87\x038\x00\x00\"\x89" + // 0x22870338: 0x00002289 + "\"\xa2\x038\x00\x00\"\xac" + // 0x22A20338: 0x000022AC + "\"\xa8\x038\x00\x00\"\xad" + // 0x22A80338: 0x000022AD + "\"\xa9\x038\x00\x00\"\xae" + // 0x22A90338: 0x000022AE + "\"\xab\x038\x00\x00\"\xaf" + // 0x22AB0338: 0x000022AF + "\"|\x038\x00\x00\"\xe0" + // 0x227C0338: 0x000022E0 + "\"}\x038\x00\x00\"\xe1" + // 0x227D0338: 0x000022E1 + "\"\x91\x038\x00\x00\"\xe2" + // 0x22910338: 0x000022E2 + "\"\x92\x038\x00\x00\"\xe3" + // 0x22920338: 0x000022E3 + "\"\xb2\x038\x00\x00\"\xea" + // 0x22B20338: 0x000022EA + "\"\xb3\x038\x00\x00\"\xeb" + // 0x22B30338: 0x000022EB + "\"\xb4\x038\x00\x00\"\xec" + // 0x22B40338: 0x000022EC + "\"\xb5\x038\x00\x00\"\xed" + // 0x22B50338: 0x000022ED + "0K0\x99\x00\x000L" + // 0x304B3099: 0x0000304C + "0M0\x99\x00\x000N" + // 0x304D3099: 0x0000304E + "0O0\x99\x00\x000P" + // 0x304F3099: 0x00003050 + "0Q0\x99\x00\x000R" + // 0x30513099: 0x00003052 + "0S0\x99\x00\x000T" + // 0x30533099: 0x00003054 + "0U0\x99\x00\x000V" + // 0x30553099: 0x00003056 + "0W0\x99\x00\x000X" + // 0x30573099: 0x00003058 + "0Y0\x99\x00\x000Z" + // 0x30593099: 0x0000305A + "0[0\x99\x00\x000\\" + // 0x305B3099: 0x0000305C + "0]0\x99\x00\x000^" + // 0x305D3099: 0x0000305E + "0_0\x99\x00\x000`" + // 0x305F3099: 0x00003060 + "0a0\x99\x00\x000b" + // 0x30613099: 0x00003062 + "0d0\x99\x00\x000e" + // 0x30643099: 0x00003065 + "0f0\x99\x00\x000g" + // 0x30663099: 0x00003067 + "0h0\x99\x00\x000i" + // 0x30683099: 0x00003069 + "0o0\x99\x00\x000p" + // 0x306F3099: 0x00003070 + "0o0\x9a\x00\x000q" + // 0x306F309A: 0x00003071 + "0r0\x99\x00\x000s" + // 0x30723099: 0x00003073 + "0r0\x9a\x00\x000t" + // 0x3072309A: 0x00003074 + "0u0\x99\x00\x000v" + // 0x30753099: 0x00003076 + "0u0\x9a\x00\x000w" + // 0x3075309A: 0x00003077 + "0x0\x99\x00\x000y" + // 0x30783099: 0x00003079 + "0x0\x9a\x00\x000z" + // 0x3078309A: 0x0000307A + "0{0\x99\x00\x000|" + // 0x307B3099: 0x0000307C + "0{0\x9a\x00\x000}" + // 0x307B309A: 0x0000307D + "0F0\x99\x00\x000\x94" + // 0x30463099: 0x00003094 + "0\x9d0\x99\x00\x000\x9e" + // 0x309D3099: 0x0000309E + "0\xab0\x99\x00\x000\xac" + // 0x30AB3099: 0x000030AC + "0\xad0\x99\x00\x000\xae" + // 0x30AD3099: 0x000030AE + "0\xaf0\x99\x00\x000\xb0" + // 0x30AF3099: 0x000030B0 + "0\xb10\x99\x00\x000\xb2" + // 0x30B13099: 0x000030B2 + "0\xb30\x99\x00\x000\xb4" + // 0x30B33099: 0x000030B4 + "0\xb50\x99\x00\x000\xb6" + // 0x30B53099: 0x000030B6 + "0\xb70\x99\x00\x000\xb8" + // 0x30B73099: 0x000030B8 + "0\xb90\x99\x00\x000\xba" + // 0x30B93099: 0x000030BA + "0\xbb0\x99\x00\x000\xbc" + // 0x30BB3099: 0x000030BC + "0\xbd0\x99\x00\x000\xbe" + // 0x30BD3099: 0x000030BE + "0\xbf0\x99\x00\x000\xc0" + // 0x30BF3099: 0x000030C0 + "0\xc10\x99\x00\x000\xc2" + // 0x30C13099: 0x000030C2 + "0\xc40\x99\x00\x000\xc5" + // 0x30C43099: 0x000030C5 + "0\xc60\x99\x00\x000\xc7" + // 0x30C63099: 0x000030C7 + "0\xc80\x99\x00\x000\xc9" + // 0x30C83099: 0x000030C9 + "0\xcf0\x99\x00\x000\xd0" + // 0x30CF3099: 0x000030D0 + "0\xcf0\x9a\x00\x000\xd1" + // 0x30CF309A: 0x000030D1 + "0\xd20\x99\x00\x000\xd3" + // 0x30D23099: 0x000030D3 + "0\xd20\x9a\x00\x000\xd4" + // 0x30D2309A: 0x000030D4 + "0\xd50\x99\x00\x000\xd6" + // 0x30D53099: 0x000030D6 + "0\xd50\x9a\x00\x000\xd7" + // 0x30D5309A: 0x000030D7 + "0\xd80\x99\x00\x000\xd9" + // 0x30D83099: 0x000030D9 + "0\xd80\x9a\x00\x000\xda" + // 0x30D8309A: 0x000030DA + "0\xdb0\x99\x00\x000\xdc" + // 0x30DB3099: 0x000030DC + "0\xdb0\x9a\x00\x000\xdd" + // 0x30DB309A: 0x000030DD + "0\xa60\x99\x00\x000\xf4" + // 0x30A63099: 0x000030F4 + "0\xef0\x99\x00\x000\xf7" + // 0x30EF3099: 0x000030F7 + "0\xf00\x99\x00\x000\xf8" + // 0x30F03099: 0x000030F8 + "0\xf10\x99\x00\x000\xf9" + // 0x30F13099: 0x000030F9 + "0\xf20\x99\x00\x000\xfa" + // 0x30F23099: 0x000030FA + "0\xfd0\x99\x00\x000\xfe" + // 0x30FD3099: 0x000030FE + "\x10\x99\x10\xba\x00\x01\x10\x9a" + // 0x109910BA: 0x0001109A + "\x10\x9b\x10\xba\x00\x01\x10\x9c" + // 0x109B10BA: 0x0001109C + "\x10\xa5\x10\xba\x00\x01\x10\xab" + // 0x10A510BA: 0x000110AB + "\x111\x11'\x00\x01\x11." + // 0x11311127: 0x0001112E + "\x112\x11'\x00\x01\x11/" + // 0x11321127: 0x0001112F + "\x13G\x13>\x00\x01\x13K" + // 0x1347133E: 0x0001134B + "\x13G\x13W\x00\x01\x13L" + // 0x13471357: 0x0001134C + "\x14\xb9\x14\xba\x00\x01\x14\xbb" + // 0x14B914BA: 0x000114BB + "\x14\xb9\x14\xb0\x00\x01\x14\xbc" + // 0x14B914B0: 0x000114BC + "\x14\xb9\x14\xbd\x00\x01\x14\xbe" + // 0x14B914BD: 0x000114BE + "\x15\xb8\x15\xaf\x00\x01\x15\xba" + // 0x15B815AF: 0x000115BA + "\x15\xb9\x15\xaf\x00\x01\x15\xbb" + // 0x15B915AF: 0x000115BB + "" + // Total size of tables: 53KB (54006 bytes) diff --git a/vendor/gopkg.in/src-d/go-billy.v4/.gitignore b/vendor/gopkg.in/src-d/go-billy.v4/.gitignore index 3f2bc47..62cdb53 100644 --- a/vendor/gopkg.in/src-d/go-billy.v4/.gitignore +++ b/vendor/gopkg.in/src-d/go-billy.v4/.gitignore @@ -1 +1,5 @@ /coverage.txt +/vendor +Gopkg.lock +Gopkg.toml +go.sum diff --git a/vendor/gopkg.in/src-d/go-billy.v4/util/util.go b/vendor/gopkg.in/src-d/go-billy.v4/util/util.go index 2876375..cf7fb57 100644 --- a/vendor/gopkg.in/src-d/go-billy.v4/util/util.go +++ b/vendor/gopkg.in/src-d/go-billy.v4/util/util.go @@ -168,6 +168,45 @@ func TempFile(fs billy.Basic, dir, prefix string) (f billy.File, err error) { return } +// TempDir creates a new temporary directory in the directory dir +// with a name beginning with prefix and returns the path of the +// new directory. If dir is the empty string, TempDir uses the +// default directory for temporary files (see os.TempDir). +// Multiple programs calling TempDir simultaneously +// will not choose the same directory. It is the caller's responsibility +// to remove the directory when no longer needed. +func TempDir(fs billy.Dir, dir, prefix string) (name string, err error) { + // This implementation is based on stdlib ioutil.TempDir + + if dir == "" { + dir = os.TempDir() + } + + nconflict := 0 + for i := 0; i < 10000; i++ { + try := filepath.Join(dir, prefix+nextSuffix()) + err = fs.MkdirAll(try, 0700) + if os.IsExist(err) { + if nconflict++; nconflict > 10 { + randmu.Lock() + rand = reseed() + randmu.Unlock() + } + continue + } + if os.IsNotExist(err) { + if _, err := os.Stat(dir); os.IsNotExist(err) { + return "", err + } + } + if err == nil { + name = try + } + break + } + return +} + type underlying interface { Underlying() billy.Basic } diff --git a/vendor/gopkg.in/src-d/go-git.v4/options.go b/vendor/gopkg.in/src-d/go-git.v4/options.go index 5d10a88..ed7689a 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/options.go +++ b/vendor/gopkg.in/src-d/go-git.v4/options.go @@ -335,6 +335,11 @@ type LogOptions struct { // Show only those commits in which the specified file was inserted/updated. // It is equivalent to running `git log -- `. FileName *string + + // Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as . + // It is equivalent to running `git log --all`. + // If set on true, the From option will be ignored. + All bool } var ( diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go index 2b4aceb..0d9ed54 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go @@ -51,7 +51,13 @@ func WritePackfileToObjectStorage( } defer ioutil.CheckClose(w, &err) - _, err = io.Copy(w, packfile) + + var n int64 + n, err = io.Copy(w, packfile) + if err == nil && n == 0 { + return ErrEmptyPackfile + } + return err } diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go index 330cb73..a268bce 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go @@ -48,7 +48,7 @@ func NewFSObject( // Reader implements the plumbing.EncodedObject interface. func (o *FSObject) Reader() (io.ReadCloser, error) { obj, ok := o.cache.Get(o.hash) - if ok { + if ok && obj != o { reader, err := obj.Reader() if err != nil { return nil, err diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go index 2166e0a..1e7ef26 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go @@ -21,6 +21,16 @@ var ( ErrZLib = NewError("zlib reading error") ) +// When reading small objects from packfile it is beneficial to do so at +// once to exploit the buffered I/O. In many cases the objects are so small +// that they were already loaded to memory when the object header was +// loaded from the packfile. Wrapping in FSObject would cause this buffered +// data to be thrown away and then re-read later, with the additional +// seeking causing reloads from disk. Objects smaller than this threshold +// are now always read into memory and stored in cache instead of being +// wrapped in FSObject. +const smallObjectThreshold = 16 * 1024 + // Packfile allows retrieving information from inside a packfile. type Packfile struct { idxfile.Index @@ -79,15 +89,7 @@ func (p *Packfile) GetByOffset(o int64) (plumbing.EncodedObject, error) { } } - if _, err := p.s.SeekFromStart(o); err != nil { - if err == io.EOF || isInvalid(err) { - return nil, plumbing.ErrObjectNotFound - } - - return nil, err - } - - return p.nextObject() + return p.objectAtOffset(o) } // GetSizeByOffset retrieves the size of the encoded object from the @@ -108,6 +110,12 @@ func (p *Packfile) GetSizeByOffset(o int64) (size int64, err error) { return h.Length, nil } +func (p *Packfile) objectHeaderAtOffset(offset int64) (*ObjectHeader, error) { + h, err := p.s.SeekObjectHeader(offset) + p.s.pendingObject = nil + return h, err +} + func (p *Packfile) nextObjectHeader() (*ObjectHeader, error) { h, err := p.s.NextObjectHeader() p.s.pendingObject = nil @@ -154,11 +162,7 @@ func (p *Packfile) getObjectType(h *ObjectHeader) (typ plumbing.ObjectType, err if baseType, ok := p.offsetToType[offset]; ok { typ = baseType } else { - if _, err = p.s.SeekFromStart(offset); err != nil { - return - } - - h, err = p.nextObjectHeader() + h, err = p.objectHeaderAtOffset(offset) if err != nil { return } @@ -175,8 +179,8 @@ func (p *Packfile) getObjectType(h *ObjectHeader) (typ plumbing.ObjectType, err return } -func (p *Packfile) nextObject() (plumbing.EncodedObject, error) { - h, err := p.nextObjectHeader() +func (p *Packfile) objectAtOffset(offset int64) (plumbing.EncodedObject, error) { + h, err := p.objectHeaderAtOffset(offset) if err != nil { if err == io.EOF || isInvalid(err) { return nil, plumbing.ErrObjectNotFound @@ -190,6 +194,13 @@ func (p *Packfile) nextObject() (plumbing.EncodedObject, error) { return p.getNextObject(h) } + // If the object is not a delta and it's small enough then read it + // completely into memory now since it is already read from disk + // into buffer anyway. + if h.Length <= smallObjectThreshold && h.Type != plumbing.OFSDeltaObject && h.Type != plumbing.REFDeltaObject { + return p.getNextObject(h) + } + hash, err := p.FindHash(h.Offset) if err != nil { return nil, err @@ -233,11 +244,7 @@ func (p *Packfile) getObjectContent(offset int64) (io.ReadCloser, error) { } } - if _, err := p.s.SeekFromStart(offset); err != nil { - return nil, err - } - - h, err := p.nextObjectHeader() + h, err := p.objectHeaderAtOffset(offset) if err != nil { return nil, err } @@ -329,8 +336,6 @@ func (p *Packfile) fillOFSDeltaObjectContent(obj plumbing.EncodedObject, offset if err != nil { return err } - - p.cachePut(base) } obj.SetType(base.Type()) diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go index 5a62d63..71cbba9 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go @@ -398,11 +398,7 @@ func (p *Parser) readData(o *objectInfo) ([]byte, error) { return data, nil } - if _, err := p.scanner.SeekFromStart(o.Offset); err != nil { - return nil, err - } - - if _, err := p.scanner.NextObjectHeader(); err != nil { + if _, err := p.scanner.SeekObjectHeader(o.Offset); err != nil { return nil, err } diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go index 6fc183b..614b0d1 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go @@ -138,14 +138,52 @@ func (s *Scanner) readCount() (uint32, error) { return binary.ReadUint32(s.r) } +// SeekObjectHeader seeks to specified offset and returns the ObjectHeader +// for the next object in the reader +func (s *Scanner) SeekObjectHeader(offset int64) (*ObjectHeader, error) { + // if seeking we assume that you are not interested in the header + if s.version == 0 { + s.version = VersionSupported + } + + if _, err := s.r.Seek(offset, io.SeekStart); err != nil { + return nil, err + } + + h, err := s.nextObjectHeader() + if err != nil { + return nil, err + } + + h.Offset = offset + return h, nil +} + // NextObjectHeader returns the ObjectHeader for the next object in the reader func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) { - defer s.Flush() - if err := s.doPending(); err != nil { return nil, err } + offset, err := s.r.Seek(0, io.SeekCurrent) + if err != nil { + return nil, err + } + + h, err := s.nextObjectHeader() + if err != nil { + return nil, err + } + + h.Offset = offset + return h, nil +} + +// nextObjectHeader returns the ObjectHeader for the next object in the reader +// without the Offset field +func (s *Scanner) nextObjectHeader() (*ObjectHeader, error) { + defer s.Flush() + s.crc.Reset() h := &ObjectHeader{} @@ -308,7 +346,7 @@ var byteSlicePool = sync.Pool{ // SeekFromStart sets a new offset from start, returns the old position before // the change. func (s *Scanner) SeekFromStart(offset int64) (previous int64, err error) { - // if seeking we assume that you are not interested on the header + // if seeking we assume that you are not interested in the header if s.version == 0 { s.version = VersionSupported } @@ -385,7 +423,7 @@ type bufferedSeeker struct { } func (r *bufferedSeeker) Seek(offset int64, whence int) (int64, error) { - if whence == io.SeekCurrent { + if whence == io.SeekCurrent && offset == 0 { current, err := r.r.Seek(offset, whence) if err != nil { return current, err diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go index 40ad258..8c76557 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go @@ -1,10 +1,12 @@ package object import ( + "container/list" "io" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/storage" ) type commitPreIterator struct { @@ -181,3 +183,133 @@ func (w *commitPostIterator) ForEach(cb func(*Commit) error) error { } func (w *commitPostIterator) Close() {} + +// commitAllIterator stands for commit iterator for all refs. +type commitAllIterator struct { + // currCommit points to the current commit. + currCommit *list.Element +} + +// NewCommitAllIter returns a new commit iterator for all refs. +// repoStorer is a repo Storer used to get commits and references. +// commitIterFunc is a commit iterator function, used to iterate through ref commits in chosen order +func NewCommitAllIter(repoStorer storage.Storer, commitIterFunc func(*Commit) CommitIter) (CommitIter, error) { + commitsPath := list.New() + commitsLookup := make(map[plumbing.Hash]*list.Element) + head, err := storer.ResolveReference(repoStorer, plumbing.HEAD) + if err != nil { + return nil, err + } + + // add all references along with the HEAD + if err = addReference(repoStorer, commitIterFunc, head, commitsPath, commitsLookup); err != nil { + return nil, err + } + refIter, err := repoStorer.IterReferences() + if err != nil { + return nil, err + } + defer refIter.Close() + err = refIter.ForEach( + func(ref *plumbing.Reference) error { + return addReference(repoStorer, commitIterFunc, ref, commitsPath, commitsLookup) + }, + ) + if err != nil { + return nil, err + } + + return &commitAllIterator{commitsPath.Front()}, nil +} + +func addReference( + repoStorer storage.Storer, + commitIterFunc func(*Commit) CommitIter, + ref *plumbing.Reference, + commitsPath *list.List, + commitsLookup map[plumbing.Hash]*list.Element) error { + + _, exists := commitsLookup[ref.Hash()] + if exists { + // we already have it - skip the reference. + return nil + } + + refCommit, _ := GetCommit(repoStorer, ref.Hash()) + if refCommit == nil { + // if it's not a commit - skip it. + return nil + } + + var ( + refCommits []*Commit + parent *list.Element + ) + // collect all ref commits to add + commitIter := commitIterFunc(refCommit) + for c, e := commitIter.Next(); e == nil; { + parent, exists = commitsLookup[c.Hash] + if exists { + break + } + refCommits = append(refCommits, c) + c, e = commitIter.Next() + } + commitIter.Close() + + if parent == nil { + // common parent - not found + // add all commits to the path from this ref (maybe it's a HEAD and we don't have anything, yet) + for _, c := range refCommits { + parent = commitsPath.PushBack(c) + commitsLookup[c.Hash] = parent + } + } else { + // add ref's commits to the path in reverse order (from the latest) + for i := len(refCommits) - 1; i >= 0; i-- { + c := refCommits[i] + // insert before found common parent + parent = commitsPath.InsertBefore(c, parent) + commitsLookup[c.Hash] = parent + } + } + + return nil +} + +func (it *commitAllIterator) Next() (*Commit, error) { + if it.currCommit == nil { + return nil, io.EOF + } + + c := it.currCommit.Value.(*Commit) + it.currCommit = it.currCommit.Next() + + return c, nil +} + +func (it *commitAllIterator) ForEach(cb func(*Commit) error) error { + for { + c, err := it.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + err = cb(c) + if err == storer.ErrStop { + break + } + if err != nil { + return err + } + } + + return nil +} + +func (it *commitAllIterator) Close() { + it.currCommit = nil +} diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go index 84e738a..6f16e61 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go @@ -1,23 +1,30 @@ package object import ( - "gopkg.in/src-d/go-git.v4/plumbing/storer" "io" + + "gopkg.in/src-d/go-git.v4/plumbing" + + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) type commitFileIter struct { fileName string sourceIter CommitIter currentCommit *Commit + checkParent bool } // NewCommitFileIterFromIter returns a commit iterator which performs diffTree between // successive trees returned from the commit iterator from the argument. The purpose of this is // to find the commits that explain how the files that match the path came to be. -func NewCommitFileIterFromIter(fileName string, commitIter CommitIter) CommitIter { +// If checkParent is true then the function double checks if potential parent (next commit in a path) +// is one of the parents in the tree (it's used by `git log --all`). +func NewCommitFileIterFromIter(fileName string, commitIter CommitIter, checkParent bool) CommitIter { iterator := new(commitFileIter) iterator.sourceIter = commitIter iterator.fileName = fileName + iterator.checkParent = checkParent return iterator } @@ -71,20 +78,14 @@ func (c *commitFileIter) getNextFileCommit() (*Commit, error) { return nil, diffErr } - foundChangeForFile := false - for _, change := range changes { - if change.name() == c.fileName { - foundChangeForFile = true - break - } - } + found := c.hasFileChange(changes, parentCommit) // Storing the current-commit in-case a change is found, and // Updating the current-commit for the next-iteration prevCommit := c.currentCommit c.currentCommit = parentCommit - if foundChangeForFile == true { + if found { return prevCommit, nil } @@ -95,6 +96,35 @@ func (c *commitFileIter) getNextFileCommit() (*Commit, error) { } } +func (c *commitFileIter) hasFileChange(changes Changes, parent *Commit) bool { + for _, change := range changes { + if change.name() != c.fileName { + continue + } + + // filename matches, now check if source iterator contains all commits (from all refs) + if c.checkParent { + if parent != nil && isParentHash(parent.Hash, c.currentCommit) { + return true + } + continue + } + + return true + } + + return false +} + +func isParentHash(hash plumbing.Hash, commit *Commit) bool { + for _, h := range commit.ParentHashes { + if h == hash { + return true + } + } + return false +} + func (c *commitFileIter) ForEach(cb func(*Commit) error) error { for { commit, nextErr := c.Next() diff --git a/vendor/gopkg.in/src-d/go-git.v4/repository.go b/vendor/gopkg.in/src-d/go-git.v4/repository.go index 97134ec..de92d64 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/repository.go +++ b/vendor/gopkg.in/src-d/go-git.v4/repository.go @@ -41,6 +41,8 @@ var ( ErrTagExists = errors.New("tag already exists") // ErrTagNotFound an error stating the specified tag does not exist ErrTagNotFound = errors.New("tag not found") + // ErrFetching is returned when the packfile could not be downloaded + ErrFetching = errors.New("unable to fetch packfile") ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch") ErrRepositoryNotExists = errors.New("repository does not exist") @@ -858,6 +860,8 @@ func (r *Repository) fetchAndUpdateReferences( remoteRefs, err := remote.fetch(ctx, o) if err == NoErrAlreadyUpToDate { objsUpdated = false + } else if err == packfile.ErrEmptyPackfile { + return nil, ErrFetching } else if err != nil { return nil, err } @@ -1023,8 +1027,36 @@ func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error { // Log returns the commit history from the given LogOptions. func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) { - h := o.From - if o.From == plumbing.ZeroHash { + fn := commitIterFunc(o.Order) + if fn == nil { + return nil, fmt.Errorf("invalid Order=%v", o.Order) + } + + var ( + it object.CommitIter + err error + ) + if o.All { + it, err = r.logAll(fn) + } else { + it, err = r.log(o.From, fn) + } + + if err != nil { + return nil, err + } + + if o.FileName != nil { + // for `git log --all` also check parent (if the next commit comes from the real parent) + it = r.logWithFile(*o.FileName, it, o.All) + } + + return it, nil +} + +func (r *Repository) log(from plumbing.Hash, commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) { + h := from + if from == plumbing.ZeroHash { head, err := r.Head() if err != nil { return nil, err @@ -1037,27 +1069,41 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) { if err != nil { return nil, err } + return commitIterFunc(commit), nil +} - var commitIter object.CommitIter - switch o.Order { +func (r *Repository) logAll(commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) { + return object.NewCommitAllIter(r.Storer, commitIterFunc) +} + +func (*Repository) logWithFile(fileName string, commitIter object.CommitIter, checkParent bool) object.CommitIter { + return object.NewCommitFileIterFromIter(fileName, commitIter, checkParent) +} + +func commitIterFunc(order LogOrder) func(c *object.Commit) object.CommitIter { + switch order { case LogOrderDefault: - commitIter = object.NewCommitPreorderIter(commit, nil, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitPreorderIter(c, nil, nil) + } case LogOrderDFS: - commitIter = object.NewCommitPreorderIter(commit, nil, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitPreorderIter(c, nil, nil) + } case LogOrderDFSPost: - commitIter = object.NewCommitPostorderIter(commit, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitPostorderIter(c, nil) + } case LogOrderBSF: - commitIter = object.NewCommitIterBSF(commit, nil, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitIterBSF(c, nil, nil) + } case LogOrderCommitterTime: - commitIter = object.NewCommitIterCTime(commit, nil, nil) - default: - return nil, fmt.Errorf("invalid Order=%v", o.Order) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitIterCTime(c, nil, nil) + } } - - if o.FileName == nil { - return commitIter, nil - } - return object.NewCommitFileIterFromIter(*o.FileName, commitIter), nil + return nil } // Tags returns all the tag References in a repository. diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go index d27c1a3..9da2f31 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go @@ -1,15 +1,24 @@ -// +build !norwfs - package dotgit import ( + "fmt" "os" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/utils/ioutil" + + "gopkg.in/src-d/go-billy.v4" ) func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err error) { + if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) { + return d.setRefRwfs(fileName, content, old) + } + + return d.setRefNorwfs(fileName, content, old) +} + +func (d *DotGit) setRefRwfs(fileName, content string, old *plumbing.Reference) (err error) { // If we are not checking an old ref, just truncate the file. mode := os.O_RDWR | os.O_CREATE if old == nil { @@ -41,3 +50,41 @@ func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err _, err = f.Write([]byte(content)) return err } + +// There are some filesystems that don't support opening files in RDWD mode. +// In these filesystems the standard SetRef function can not be used as it +// reads the reference file to check that it's not modified before updating it. +// +// This version of the function writes the reference without extra checks +// making it compatible with these simple filesystems. This is usually not +// a problem as they should be accessed by only one process at a time. +func (d *DotGit) setRefNorwfs(fileName, content string, old *plumbing.Reference) error { + _, err := d.fs.Stat(fileName) + if err == nil && old != nil { + fRead, err := d.fs.Open(fileName) + if err != nil { + return err + } + + ref, err := d.readReferenceFrom(fRead, old.Name().String()) + fRead.Close() + + if err != nil { + return err + } + + if ref.Hash() != old.Hash() { + return fmt.Errorf("reference has changed concurrently") + } + } + + f, err := d.fs.Create(fileName) + if err != nil { + return err + } + + defer f.Close() + + _, err = f.Write([]byte(content)) + return err +} diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go deleted file mode 100644 index 5695bd3..0000000 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build norwfs - -package dotgit - -import ( - "fmt" - - "gopkg.in/src-d/go-git.v4/plumbing" -) - -// There are some filesystems that don't support opening files in RDWD mode. -// In these filesystems the standard SetRef function can not be used as i -// reads the reference file to check that it's not modified before updating it. -// -// This version of the function writes the reference without extra checks -// making it compatible with these simple filesystems. This is usually not -// a problem as they should be accessed by only one process at a time. -func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) error { - _, err := d.fs.Stat(fileName) - if err == nil && old != nil { - fRead, err := d.fs.Open(fileName) - if err != nil { - return err - } - - ref, err := d.readReferenceFrom(fRead, old.Name().String()) - fRead.Close() - - if err != nil { - return err - } - - if ref.Hash() != old.Hash() { - return fmt.Errorf("reference has changed concurrently") - } - } - - f, err := d.fs.Create(fileName) - if err != nil { - return err - } - - defer f.Close() - - _, err = f.Write([]byte(content)) - return err -} diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go index 57dcbb4..3eb62a2 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go @@ -20,24 +20,25 @@ import ( type ObjectStorage struct { options Options - // deltaBaseCache is an object cache uses to cache delta's bases when - deltaBaseCache cache.Object + // objectCache is an object cache uses to cache delta's bases and also recently + // loaded loose objects + objectCache cache.Object dir *dotgit.DotGit index map[plumbing.Hash]idxfile.Index } // NewObjectStorage creates a new ObjectStorage with the given .git directory and cache. -func NewObjectStorage(dir *dotgit.DotGit, cache cache.Object) *ObjectStorage { - return NewObjectStorageWithOptions(dir, cache, Options{}) +func NewObjectStorage(dir *dotgit.DotGit, objectCache cache.Object) *ObjectStorage { + return NewObjectStorageWithOptions(dir, objectCache, Options{}) } // NewObjectStorageWithOptions creates a new ObjectStorage with the given .git directory, cache and extra options -func NewObjectStorageWithOptions(dir *dotgit.DotGit, cache cache.Object, ops Options) *ObjectStorage { +func NewObjectStorageWithOptions(dir *dotgit.DotGit, objectCache cache.Object, ops Options) *ObjectStorage { return &ObjectStorage{ - options: ops, - deltaBaseCache: cache, - dir: dir, + options: ops, + objectCache: objectCache, + dir: dir, } } @@ -206,7 +207,7 @@ func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( idx := s.index[pack] hash, err := idx.FindHash(offset) if err == nil { - obj, ok := s.deltaBaseCache.Get(hash) + obj, ok := s.objectCache.Get(hash) if ok { return obj.Size(), nil } @@ -215,8 +216,8 @@ func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( } var p *packfile.Packfile - if s.deltaBaseCache != nil { - p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.deltaBaseCache) + if s.objectCache != nil { + p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache) } else { p = packfile.NewPackfile(idx, s.dir.Fs(), f) } @@ -241,9 +242,19 @@ func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) ( // EncodedObject returns the object with the given hash, by searching for it in // the packfile and the git object directories. func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { - obj, err := s.getFromUnpacked(h) - if err == plumbing.ErrObjectNotFound { + var obj plumbing.EncodedObject + var err error + + if s.index != nil { obj, err = s.getFromPackfile(h, false) + if err == plumbing.ErrObjectNotFound { + obj, err = s.getFromUnpacked(h) + } + } else { + obj, err = s.getFromUnpacked(h) + if err == plumbing.ErrObjectNotFound { + obj, err = s.getFromPackfile(h, false) + } } // If the error is still object not found, check if it's a shared object @@ -254,7 +265,7 @@ func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (p // Create a new object storage with the DotGit(s) and check for the // required hash object. Skip when not found. for _, dg := range dotgits { - o := NewObjectStorage(dg, s.deltaBaseCache) + o := NewObjectStorage(dg, s.objectCache) enobj, enerr := o.EncodedObject(t, h) if enerr != nil { continue @@ -304,9 +315,12 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb return nil, err } - defer ioutil.CheckClose(f, &err) + if cacheObj, found := s.objectCache.Get(h); found { + return cacheObj, nil + } + obj = s.NewEncodedObject() r, err := objfile.NewReader(f) if err != nil { @@ -327,6 +341,8 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb return nil, err } + s.objectCache.Put(obj) + _, err = io.Copy(w, r) return obj, err } @@ -369,7 +385,7 @@ func (s *ObjectStorage) decodeObjectAt( ) (plumbing.EncodedObject, error) { hash, err := idx.FindHash(offset) if err == nil { - obj, ok := s.deltaBaseCache.Get(hash) + obj, ok := s.objectCache.Get(hash) if ok { return obj, nil } @@ -380,8 +396,8 @@ func (s *ObjectStorage) decodeObjectAt( } var p *packfile.Packfile - if s.deltaBaseCache != nil { - p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.deltaBaseCache) + if s.objectCache != nil { + p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache) } else { p = packfile.NewPackfile(idx, s.dir.Fs(), f) } @@ -400,11 +416,7 @@ func (s *ObjectStorage) decodeDeltaObjectAt( } p := packfile.NewScanner(f) - if _, err := p.SeekFromStart(offset); err != nil { - return nil, err - } - - header, err := p.NextObjectHeader() + header, err := p.SeekObjectHeader(offset) if err != nil { return nil, err } @@ -495,7 +507,7 @@ func (s *ObjectStorage) buildPackfileIters( } return newPackfileIter( s.dir.Fs(), pack, t, seen, s.index[h], - s.deltaBaseCache, s.options.KeepDescriptors, + s.objectCache, s.options.KeepDescriptors, ) }, }, nil diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go index 14a772a..370f7bd 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go @@ -51,11 +51,7 @@ func NewStorageWithOptions(fs billy.Filesystem, cache cache.Object, ops Options) fs: fs, dir: dir, - ObjectStorage: ObjectStorage{ - options: ops, - deltaBaseCache: cache, - dir: dir, - }, + ObjectStorage: *NewObjectStorageWithOptions(dir, cache, ops), ReferenceStorage: ReferenceStorage{dir: dir}, IndexStorage: IndexStorage{dir: dir}, ShallowStorage: ShallowStorage{dir: dir}, diff --git a/vendor/gotest.tools/LICENSE b/vendor/gotest.tools/LICENSE new file mode 100644 index 0000000..aeaa2fa --- /dev/null +++ b/vendor/gotest.tools/LICENSE @@ -0,0 +1,13 @@ +Copyright 2018 gotest.tools authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/gotest.tools/assert/assert.go b/vendor/gotest.tools/assert/assert.go new file mode 100644 index 0000000..05d6635 --- /dev/null +++ b/vendor/gotest.tools/assert/assert.go @@ -0,0 +1,311 @@ +/*Package assert provides assertions for comparing expected values to actual +values. When an assertion fails a helpful error message is printed. + +Assert and Check + +Assert() and Check() both accept a Comparison, and fail the test when the +comparison fails. The one difference is that Assert() will end the test execution +immediately (using t.FailNow()) whereas Check() will fail the test (using t.Fail()), +return the value of the comparison, then proceed with the rest of the test case. + +Example usage + +The example below shows assert used with some common types. + + + import ( + "testing" + + "gotest.tools/assert" + is "gotest.tools/assert/cmp" + ) + + func TestEverything(t *testing.T) { + // booleans + assert.Assert(t, ok) + assert.Assert(t, !missing) + + // primitives + assert.Equal(t, count, 1) + assert.Equal(t, msg, "the message") + assert.Assert(t, total != 10) // NotEqual + + // errors + assert.NilError(t, closer.Close()) + assert.Error(t, err, "the exact error message") + assert.ErrorContains(t, err, "includes this") + assert.ErrorType(t, err, os.IsNotExist) + + // complex types + assert.DeepEqual(t, result, myStruct{Name: "title"}) + assert.Assert(t, is.Len(items, 3)) + assert.Assert(t, len(sequence) != 0) // NotEmpty + assert.Assert(t, is.Contains(mapping, "key")) + + // pointers and interface + assert.Assert(t, is.Nil(ref)) + assert.Assert(t, ref != nil) // NotNil + } + +Comparisons + +Package https://godoc.org/gotest.tools/assert/cmp provides +many common comparisons. Additional comparisons can be written to compare +values in other ways. See the example Assert (CustomComparison). + +Automated migration from testify + +gty-migrate-from-testify is a binary which can update source code which uses +testify assertions to use the assertions provided by this package. + +See http://bit.do/cmd-gty-migrate-from-testify. + + +*/ +package assert // import "gotest.tools/assert" + +import ( + "fmt" + "go/ast" + "go/token" + + gocmp "github.com/google/go-cmp/cmp" + "gotest.tools/assert/cmp" + "gotest.tools/internal/format" + "gotest.tools/internal/source" +) + +// BoolOrComparison can be a bool, or cmp.Comparison. See Assert() for usage. +type BoolOrComparison interface{} + +// TestingT is the subset of testing.T used by the assert package. +type TestingT interface { + FailNow() + Fail() + Log(args ...interface{}) +} + +type helperT interface { + Helper() +} + +const failureMessage = "assertion failed: " + +// nolint: gocyclo +func assert( + t TestingT, + failer func(), + argSelector argSelector, + comparison BoolOrComparison, + msgAndArgs ...interface{}, +) bool { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + var success bool + switch check := comparison.(type) { + case bool: + if check { + return true + } + logFailureFromBool(t, msgAndArgs...) + + // Undocumented legacy comparison without Result type + case func() (success bool, message string): + success = runCompareFunc(t, check, msgAndArgs...) + + case nil: + return true + + case error: + msg := "error is not nil: " + t.Log(format.WithCustomMessage(failureMessage+msg+check.Error(), msgAndArgs...)) + + case cmp.Comparison: + success = runComparison(t, argSelector, check, msgAndArgs...) + + case func() cmp.Result: + success = runComparison(t, argSelector, check, msgAndArgs...) + + default: + t.Log(fmt.Sprintf("invalid Comparison: %v (%T)", check, check)) + } + + if success { + return true + } + failer() + return false +} + +func runCompareFunc( + t TestingT, + f func() (success bool, message string), + msgAndArgs ...interface{}, +) bool { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + if success, message := f(); !success { + t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) + return false + } + return true +} + +func logFailureFromBool(t TestingT, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + const stackIndex = 3 // Assert()/Check(), assert(), formatFailureFromBool() + const comparisonArgPos = 1 + args, err := source.CallExprArgs(stackIndex) + if err != nil { + t.Log(err.Error()) + return + } + + msg, err := boolFailureMessage(args[comparisonArgPos]) + if err != nil { + t.Log(err.Error()) + msg = "expression is false" + } + + t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...)) +} + +func boolFailureMessage(expr ast.Expr) (string, error) { + if binaryExpr, ok := expr.(*ast.BinaryExpr); ok && binaryExpr.Op == token.NEQ { + x, err := source.FormatNode(binaryExpr.X) + if err != nil { + return "", err + } + y, err := source.FormatNode(binaryExpr.Y) + if err != nil { + return "", err + } + return x + " is " + y, nil + } + + if unaryExpr, ok := expr.(*ast.UnaryExpr); ok && unaryExpr.Op == token.NOT { + x, err := source.FormatNode(unaryExpr.X) + if err != nil { + return "", err + } + return x + " is true", nil + } + + formatted, err := source.FormatNode(expr) + if err != nil { + return "", err + } + return "expression is false: " + formatted, nil +} + +// Assert performs a comparison. If the comparison fails the test is marked as +// failed, a failure message is logged, and execution is stopped immediately. +// +// The comparison argument may be one of three types: bool, cmp.Comparison or +// error. +// When called with a bool the failure message will contain the literal source +// code of the expression. +// When called with a cmp.Comparison the comparison is responsible for producing +// a helpful failure message. +// When called with an error a nil value is considered success. A non-nil error +// is a failure, and Error() is used as the failure message. +func Assert(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsFromComparisonCall, comparison, msgAndArgs...) +} + +// Check performs a comparison. If the comparison fails the test is marked as +// failed, a failure message is logged, and Check returns false. Otherwise returns +// true. +// +// See Assert for details about the comparison arg and failure messages. +func Check(t TestingT, comparison BoolOrComparison, msgAndArgs ...interface{}) bool { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + return assert(t, t.Fail, argsFromComparisonCall, comparison, msgAndArgs...) +} + +// NilError fails the test immediately if err is not nil. +// This is equivalent to Assert(t, err) +func NilError(t TestingT, err error, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsAfterT, err, msgAndArgs...) +} + +// Equal uses the == operator to assert two values are equal and fails the test +// if they are not equal. +// +// If the comparison fails Equal will use the variable names for x and y as part +// of the failure message to identify the actual and expected values. +// +// If either x or y are a multi-line string the failure message will include a +// unified diff of the two values. If the values only differ by whitespace +// the unified diff will be augmented by replacing whitespace characters with +// visible characters to identify the whitespace difference. +// +// This is equivalent to Assert(t, cmp.Equal(x, y)). +func Equal(t TestingT, x, y interface{}, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsAfterT, cmp.Equal(x, y), msgAndArgs...) +} + +// DeepEqual uses google/go-cmp (http://bit.do/go-cmp) to assert two values are +// equal and fails the test if they are not equal. +// +// Package https://godoc.org/gotest.tools/assert/opt provides some additional +// commonly used Options. +// +// This is equivalent to Assert(t, cmp.DeepEqual(x, y)). +func DeepEqual(t TestingT, x, y interface{}, opts ...gocmp.Option) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsAfterT, cmp.DeepEqual(x, y, opts...)) +} + +// Error fails the test if err is nil, or the error message is not the expected +// message. +// Equivalent to Assert(t, cmp.Error(err, message)). +func Error(t TestingT, err error, message string, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsAfterT, cmp.Error(err, message), msgAndArgs...) +} + +// ErrorContains fails the test if err is nil, or the error message does not +// contain the expected substring. +// Equivalent to Assert(t, cmp.ErrorContains(err, substring)). +func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsAfterT, cmp.ErrorContains(err, substring), msgAndArgs...) +} + +// ErrorType fails the test if err is nil, or err is not the expected type. +// +// Expected can be one of: +// a func(error) bool which returns true if the error is the expected type, +// an instance of (or a pointer to) a struct of the expected type, +// a pointer to an interface the error is expected to implement, +// a reflect.Type of the expected struct or interface. +// +// Equivalent to Assert(t, cmp.ErrorType(err, expected)). +func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert(t, t.FailNow, argsAfterT, cmp.ErrorType(err, expected), msgAndArgs...) +} diff --git a/vendor/gotest.tools/assert/cmp/compare.go b/vendor/gotest.tools/assert/cmp/compare.go new file mode 100644 index 0000000..cf48d88 --- /dev/null +++ b/vendor/gotest.tools/assert/cmp/compare.go @@ -0,0 +1,356 @@ +/*Package cmp provides Comparisons for Assert and Check*/ +package cmp // import "gotest.tools/assert/cmp" + +import ( + "fmt" + "reflect" + "regexp" + "strings" + + "github.com/google/go-cmp/cmp" + "gotest.tools/internal/format" +) + +// Comparison is a function which compares values and returns ResultSuccess if +// the actual value matches the expected value. If the values do not match the +// Result will contain a message about why it failed. +type Comparison func() Result + +// DeepEqual compares two values using google/go-cmp (http://bit.do/go-cmp) +// and succeeds if the values are equal. +// +// The comparison can be customized using comparison Options. +// Package https://godoc.org/gotest.tools/assert/opt provides some additional +// commonly used Options. +func DeepEqual(x, y interface{}, opts ...cmp.Option) Comparison { + return func() (result Result) { + defer func() { + if panicmsg, handled := handleCmpPanic(recover()); handled { + result = ResultFailure(panicmsg) + } + }() + diff := cmp.Diff(x, y, opts...) + if diff == "" { + return ResultSuccess + } + return multiLineDiffResult(diff) + } +} + +func handleCmpPanic(r interface{}) (string, bool) { + if r == nil { + return "", false + } + panicmsg, ok := r.(string) + if !ok { + panic(r) + } + switch { + case strings.HasPrefix(panicmsg, "cannot handle unexported field"): + return panicmsg, true + } + panic(r) +} + +func toResult(success bool, msg string) Result { + if success { + return ResultSuccess + } + return ResultFailure(msg) +} + +// RegexOrPattern may be either a *regexp.Regexp or a string that is a valid +// regexp pattern. +type RegexOrPattern interface{} + +// Regexp succeeds if value v matches regular expression re. +// +// Example: +// assert.Assert(t, cmp.Regexp("^[0-9a-f]{32}$", str)) +// r := regexp.MustCompile("^[0-9a-f]{32}$") +// assert.Assert(t, cmp.Regexp(r, str)) +func Regexp(re RegexOrPattern, v string) Comparison { + match := func(re *regexp.Regexp) Result { + return toResult( + re.MatchString(v), + fmt.Sprintf("value %q does not match regexp %q", v, re.String())) + } + + return func() Result { + switch regex := re.(type) { + case *regexp.Regexp: + return match(regex) + case string: + re, err := regexp.Compile(regex) + if err != nil { + return ResultFailure(err.Error()) + } + return match(re) + default: + return ResultFailure(fmt.Sprintf("invalid type %T for regex pattern", regex)) + } + } +} + +// Equal succeeds if x == y. See assert.Equal for full documentation. +func Equal(x, y interface{}) Comparison { + return func() Result { + switch { + case x == y: + return ResultSuccess + case isMultiLineStringCompare(x, y): + diff := format.UnifiedDiff(format.DiffConfig{A: x.(string), B: y.(string)}) + return multiLineDiffResult(diff) + } + return ResultFailureTemplate(` + {{- .Data.x}} ( + {{- with callArg 0 }}{{ formatNode . }} {{end -}} + {{- printf "%T" .Data.x -}} + ) != {{ .Data.y}} ( + {{- with callArg 1 }}{{ formatNode . }} {{end -}} + {{- printf "%T" .Data.y -}} + )`, + map[string]interface{}{"x": x, "y": y}) + } +} + +func isMultiLineStringCompare(x, y interface{}) bool { + strX, ok := x.(string) + if !ok { + return false + } + strY, ok := y.(string) + if !ok { + return false + } + return strings.Contains(strX, "\n") || strings.Contains(strY, "\n") +} + +func multiLineDiffResult(diff string) Result { + return ResultFailureTemplate(` +--- {{ with callArg 0 }}{{ formatNode . }}{{else}}←{{end}} ++++ {{ with callArg 1 }}{{ formatNode . }}{{else}}→{{end}} +{{ .Data.diff }}`, + map[string]interface{}{"diff": diff}) +} + +// Len succeeds if the sequence has the expected length. +func Len(seq interface{}, expected int) Comparison { + return func() (result Result) { + defer func() { + if e := recover(); e != nil { + result = ResultFailure(fmt.Sprintf("type %T does not have a length", seq)) + } + }() + value := reflect.ValueOf(seq) + length := value.Len() + if length == expected { + return ResultSuccess + } + msg := fmt.Sprintf("expected %s (length %d) to have length %d", seq, length, expected) + return ResultFailure(msg) + } +} + +// Contains succeeds if item is in collection. Collection may be a string, map, +// slice, or array. +// +// If collection is a string, item must also be a string, and is compared using +// strings.Contains(). +// If collection is a Map, contains will succeed if item is a key in the map. +// If collection is a slice or array, item is compared to each item in the +// sequence using reflect.DeepEqual(). +func Contains(collection interface{}, item interface{}) Comparison { + return func() Result { + colValue := reflect.ValueOf(collection) + if !colValue.IsValid() { + return ResultFailure(fmt.Sprintf("nil does not contain items")) + } + msg := fmt.Sprintf("%v does not contain %v", collection, item) + + itemValue := reflect.ValueOf(item) + switch colValue.Type().Kind() { + case reflect.String: + if itemValue.Type().Kind() != reflect.String { + return ResultFailure("string may only contain strings") + } + return toResult( + strings.Contains(colValue.String(), itemValue.String()), + fmt.Sprintf("string %q does not contain %q", collection, item)) + + case reflect.Map: + if itemValue.Type() != colValue.Type().Key() { + return ResultFailure(fmt.Sprintf( + "%v can not contain a %v key", colValue.Type(), itemValue.Type())) + } + return toResult(colValue.MapIndex(itemValue).IsValid(), msg) + + case reflect.Slice, reflect.Array: + for i := 0; i < colValue.Len(); i++ { + if reflect.DeepEqual(colValue.Index(i).Interface(), item) { + return ResultSuccess + } + } + return ResultFailure(msg) + default: + return ResultFailure(fmt.Sprintf("type %T does not contain items", collection)) + } + } +} + +// Panics succeeds if f() panics. +func Panics(f func()) Comparison { + return func() (result Result) { + defer func() { + if err := recover(); err != nil { + result = ResultSuccess + } + }() + f() + return ResultFailure("did not panic") + } +} + +// Error succeeds if err is a non-nil error, and the error message equals the +// expected message. +func Error(err error, message string) Comparison { + return func() Result { + switch { + case err == nil: + return ResultFailure("expected an error, got nil") + case err.Error() != message: + return ResultFailure(fmt.Sprintf( + "expected error %q, got %s", message, formatErrorMessage(err))) + } + return ResultSuccess + } +} + +// ErrorContains succeeds if err is a non-nil error, and the error message contains +// the expected substring. +func ErrorContains(err error, substring string) Comparison { + return func() Result { + switch { + case err == nil: + return ResultFailure("expected an error, got nil") + case !strings.Contains(err.Error(), substring): + return ResultFailure(fmt.Sprintf( + "expected error to contain %q, got %s", substring, formatErrorMessage(err))) + } + return ResultSuccess + } +} + +func formatErrorMessage(err error) string { + if _, ok := err.(interface { + Cause() error + }); ok { + return fmt.Sprintf("%q\n%+v", err, err) + } + // This error was not wrapped with github.com/pkg/errors + return fmt.Sprintf("%q", err) +} + +// Nil succeeds if obj is a nil interface, pointer, or function. +// +// Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices, +// maps, and channels. +func Nil(obj interface{}) Comparison { + msgFunc := func(value reflect.Value) string { + return fmt.Sprintf("%v (type %s) is not nil", reflect.Indirect(value), value.Type()) + } + return isNil(obj, msgFunc) +} + +func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison { + return func() Result { + if obj == nil { + return ResultSuccess + } + value := reflect.ValueOf(obj) + kind := value.Type().Kind() + if kind >= reflect.Chan && kind <= reflect.Slice { + if value.IsNil() { + return ResultSuccess + } + return ResultFailure(msgFunc(value)) + } + + return ResultFailure(fmt.Sprintf("%v (type %s) can not be nil", value, value.Type())) + } +} + +// ErrorType succeeds if err is not nil and is of the expected type. +// +// Expected can be one of: +// a func(error) bool which returns true if the error is the expected type, +// an instance of (or a pointer to) a struct of the expected type, +// a pointer to an interface the error is expected to implement, +// a reflect.Type of the expected struct or interface. +func ErrorType(err error, expected interface{}) Comparison { + return func() Result { + switch expectedType := expected.(type) { + case func(error) bool: + return cmpErrorTypeFunc(err, expectedType) + case reflect.Type: + if expectedType.Kind() == reflect.Interface { + return cmpErrorTypeImplementsType(err, expectedType) + } + return cmpErrorTypeEqualType(err, expectedType) + case nil: + return ResultFailure(fmt.Sprintf("invalid type for expected: nil")) + } + + expectedType := reflect.TypeOf(expected) + switch { + case expectedType.Kind() == reflect.Struct, isPtrToStruct(expectedType): + return cmpErrorTypeEqualType(err, expectedType) + case isPtrToInterface(expectedType): + return cmpErrorTypeImplementsType(err, expectedType.Elem()) + } + return ResultFailure(fmt.Sprintf("invalid type for expected: %T", expected)) + } +} + +func cmpErrorTypeFunc(err error, f func(error) bool) Result { + if f(err) { + return ResultSuccess + } + actual := "nil" + if err != nil { + actual = fmt.Sprintf("%s (%T)", err, err) + } + return ResultFailureTemplate(`error is {{ .Data.actual }} + {{- with callArg 1 }}, not {{ formatNode . }}{{end -}}`, + map[string]interface{}{"actual": actual}) +} + +func cmpErrorTypeEqualType(err error, expectedType reflect.Type) Result { + if err == nil { + return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType)) + } + errValue := reflect.ValueOf(err) + if errValue.Type() == expectedType { + return ResultSuccess + } + return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType)) +} + +func cmpErrorTypeImplementsType(err error, expectedType reflect.Type) Result { + if err == nil { + return ResultFailure(fmt.Sprintf("error is nil, not %s", expectedType)) + } + errValue := reflect.ValueOf(err) + if errValue.Type().Implements(expectedType) { + return ResultSuccess + } + return ResultFailure(fmt.Sprintf("error is %s (%T), not %s", err, err, expectedType)) +} + +func isPtrToInterface(typ reflect.Type) bool { + return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Interface +} + +func isPtrToStruct(typ reflect.Type) bool { + return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct +} diff --git a/vendor/gotest.tools/assert/cmp/result.go b/vendor/gotest.tools/assert/cmp/result.go new file mode 100644 index 0000000..7c3c37d --- /dev/null +++ b/vendor/gotest.tools/assert/cmp/result.go @@ -0,0 +1,94 @@ +package cmp + +import ( + "bytes" + "fmt" + "go/ast" + "text/template" + + "gotest.tools/internal/source" +) + +// Result of a Comparison. +type Result interface { + Success() bool +} + +type result struct { + success bool + message string +} + +func (r result) Success() bool { + return r.success +} + +func (r result) FailureMessage() string { + return r.message +} + +// ResultSuccess is a constant which is returned by a ComparisonWithResult to +// indicate success. +var ResultSuccess = result{success: true} + +// ResultFailure returns a failed Result with a failure message. +func ResultFailure(message string) Result { + return result{message: message} +} + +// ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure +// is returned with the error message as the failure message. +func ResultFromError(err error) Result { + if err == nil { + return ResultSuccess + } + return ResultFailure(err.Error()) +} + +type templatedResult struct { + success bool + template string + data map[string]interface{} +} + +func (r templatedResult) Success() bool { + return r.success +} + +func (r templatedResult) FailureMessage(args []ast.Expr) string { + msg, err := renderMessage(r, args) + if err != nil { + return fmt.Sprintf("failed to render failure message: %s", err) + } + return msg +} + +// ResultFailureTemplate returns a Result with a template string and data which +// can be used to format a failure message. The template may access data from .Data, +// the comparison args with the callArg function, and the formatNode function may +// be used to format the call args. +func ResultFailureTemplate(template string, data map[string]interface{}) Result { + return templatedResult{template: template, data: data} +} + +func renderMessage(result templatedResult, args []ast.Expr) (string, error) { + tmpl := template.New("failure").Funcs(template.FuncMap{ + "formatNode": source.FormatNode, + "callArg": func(index int) ast.Expr { + if index >= len(args) { + return nil + } + return args[index] + }, + }) + var err error + tmpl, err = tmpl.Parse(result.template) + if err != nil { + return "", err + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, map[string]interface{}{ + "Data": result.data, + }) + return buf.String(), err +} diff --git a/vendor/gotest.tools/assert/result.go b/vendor/gotest.tools/assert/result.go new file mode 100644 index 0000000..949d939 --- /dev/null +++ b/vendor/gotest.tools/assert/result.go @@ -0,0 +1,106 @@ +package assert + +import ( + "fmt" + "go/ast" + + "gotest.tools/assert/cmp" + "gotest.tools/internal/format" + "gotest.tools/internal/source" +) + +func runComparison( + t TestingT, + argSelector argSelector, + f cmp.Comparison, + msgAndArgs ...interface{}, +) bool { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + result := f() + if result.Success() { + return true + } + + var message string + switch typed := result.(type) { + case resultWithComparisonArgs: + const stackIndex = 3 // Assert/Check, assert, runComparison + args, err := source.CallExprArgs(stackIndex) + if err != nil { + t.Log(err.Error()) + } + message = typed.FailureMessage(filterPrintableExpr(argSelector(args))) + case resultBasic: + message = typed.FailureMessage() + default: + message = fmt.Sprintf("comparison returned invalid Result type: %T", result) + } + + t.Log(format.WithCustomMessage(failureMessage+message, msgAndArgs...)) + return false +} + +type resultWithComparisonArgs interface { + FailureMessage(args []ast.Expr) string +} + +type resultBasic interface { + FailureMessage() string +} + +// filterPrintableExpr filters the ast.Expr slice to only include Expr that are +// easy to read when printed and contain relevant information to an assertion. +// +// Ident and SelectorExpr are included because they print nicely and the variable +// names may provide additional context to their values. +// BasicLit and CompositeLit are excluded because their source is equivalent to +// their value, which is already available. +// Other types are ignored for now, but could be added if they are relevant. +func filterPrintableExpr(args []ast.Expr) []ast.Expr { + result := make([]ast.Expr, len(args)) + for i, arg := range args { + if isShortPrintableExpr(arg) { + result[i] = arg + continue + } + + if starExpr, ok := arg.(*ast.StarExpr); ok { + result[i] = starExpr.X + continue + } + } + return result +} + +func isShortPrintableExpr(expr ast.Expr) bool { + switch expr.(type) { + case *ast.Ident, *ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr: + return true + case *ast.BinaryExpr, *ast.UnaryExpr: + return true + default: + // CallExpr, ParenExpr, TypeAssertExpr, KeyValueExpr, StarExpr + return false + } +} + +type argSelector func([]ast.Expr) []ast.Expr + +func argsAfterT(args []ast.Expr) []ast.Expr { + if len(args) < 1 { + return nil + } + return args[1:] +} + +func argsFromComparisonCall(args []ast.Expr) []ast.Expr { + if len(args) < 1 { + return nil + } + if callExpr, ok := args[1].(*ast.CallExpr); ok { + return callExpr.Args + } + return nil +} diff --git a/vendor/gotest.tools/internal/difflib/LICENSE b/vendor/gotest.tools/internal/difflib/LICENSE new file mode 100644 index 0000000..c67dad6 --- /dev/null +++ b/vendor/gotest.tools/internal/difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/gotest.tools/internal/difflib/difflib.go b/vendor/gotest.tools/internal/difflib/difflib.go new file mode 100644 index 0000000..b6f486b --- /dev/null +++ b/vendor/gotest.tools/internal/difflib/difflib.go @@ -0,0 +1,423 @@ +/*Package difflib is a partial port of Python difflib module. + +Original source: https://github.com/pmezard/go-difflib + +This file is trimmed to only the parts used by this repository. +*/ +package difflib // import "gotest.tools/internal/difflib" + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// Match stores line numbers of size of match +type Match struct { + A int + B int + Size int +} + +// OpCode identifies the type of diff +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +// NewMatcher returns a new SequenceMatcher +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +// SetSeqs sets two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// SetSeq1 sets the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// SetSeq2 sets the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// GetMatchingBlocks returns a list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// GetOpCodes returns a list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// GetGroupedOpCodes isolates change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} diff --git a/vendor/gotest.tools/internal/format/diff.go b/vendor/gotest.tools/internal/format/diff.go new file mode 100644 index 0000000..c938c97 --- /dev/null +++ b/vendor/gotest.tools/internal/format/diff.go @@ -0,0 +1,161 @@ +package format + +import ( + "bytes" + "fmt" + "strings" + "unicode" + + "gotest.tools/internal/difflib" +) + +const ( + contextLines = 2 +) + +// DiffConfig for a unified diff +type DiffConfig struct { + A string + B string + From string + To string +} + +// UnifiedDiff is a modified version of difflib.WriteUnifiedDiff with better +// support for showing the whitespace differences. +func UnifiedDiff(conf DiffConfig) string { + a := strings.SplitAfter(conf.A, "\n") + b := strings.SplitAfter(conf.B, "\n") + groups := difflib.NewMatcher(a, b).GetGroupedOpCodes(contextLines) + if len(groups) == 0 { + return "" + } + + buf := new(bytes.Buffer) + writeFormat := func(format string, args ...interface{}) { + buf.WriteString(fmt.Sprintf(format, args...)) + } + writeLine := func(prefix string, s string) { + buf.WriteString(prefix + s) + } + if hasWhitespaceDiffLines(groups, a, b) { + writeLine = visibleWhitespaceLine(writeLine) + } + formatHeader(writeFormat, conf) + for _, group := range groups { + formatRangeLine(writeFormat, group) + for _, opCode := range group { + in, out := a[opCode.I1:opCode.I2], b[opCode.J1:opCode.J2] + switch opCode.Tag { + case 'e': + formatLines(writeLine, " ", in) + case 'r': + formatLines(writeLine, "-", in) + formatLines(writeLine, "+", out) + case 'd': + formatLines(writeLine, "-", in) + case 'i': + formatLines(writeLine, "+", out) + } + } + } + return buf.String() +} + +// hasWhitespaceDiffLines returns true if any diff groups is only different +// because of whitespace characters. +func hasWhitespaceDiffLines(groups [][]difflib.OpCode, a, b []string) bool { + for _, group := range groups { + in, out := new(bytes.Buffer), new(bytes.Buffer) + for _, opCode := range group { + if opCode.Tag == 'e' { + continue + } + for _, line := range a[opCode.I1:opCode.I2] { + in.WriteString(line) + } + for _, line := range b[opCode.J1:opCode.J2] { + out.WriteString(line) + } + } + if removeWhitespace(in.String()) == removeWhitespace(out.String()) { + return true + } + } + return false +} + +func removeWhitespace(s string) string { + var result []rune + for _, r := range s { + if !unicode.IsSpace(r) { + result = append(result, r) + } + } + return string(result) +} + +func visibleWhitespaceLine(ws func(string, string)) func(string, string) { + mapToVisibleSpace := func(r rune) rune { + switch r { + case '\n': + case ' ': + return '·' + case '\t': + return '▷' + case '\v': + return '▽' + case '\r': + return '↵' + case '\f': + return '↓' + default: + if unicode.IsSpace(r) { + return '�' + } + } + return r + } + return func(prefix, s string) { + ws(prefix, strings.Map(mapToVisibleSpace, s)) + } +} + +func formatHeader(wf func(string, ...interface{}), conf DiffConfig) { + if conf.From != "" || conf.To != "" { + wf("--- %s\n", conf.From) + wf("+++ %s\n", conf.To) + } +} + +func formatRangeLine(wf func(string, ...interface{}), group []difflib.OpCode) { + first, last := group[0], group[len(group)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + wf("@@ -%s +%s @@\n", range1, range2) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning-- // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +func formatLines(writeLine func(string, string), prefix string, lines []string) { + for _, line := range lines { + writeLine(prefix, line) + } + // Add a newline if the last line is missing one so that the diff displays + // properly. + if !strings.HasSuffix(lines[len(lines)-1], "\n") { + writeLine("", "\n") + } +} diff --git a/vendor/gotest.tools/internal/format/format.go b/vendor/gotest.tools/internal/format/format.go new file mode 100644 index 0000000..8f6494f --- /dev/null +++ b/vendor/gotest.tools/internal/format/format.go @@ -0,0 +1,27 @@ +package format // import "gotest.tools/internal/format" + +import "fmt" + +// Message accepts a msgAndArgs varargs and formats it using fmt.Sprintf +func Message(msgAndArgs ...interface{}) string { + switch len(msgAndArgs) { + case 0: + return "" + case 1: + return fmt.Sprintf("%v", msgAndArgs[0]) + default: + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } +} + +// WithCustomMessage accepts one or two messages and formats them appropriately +func WithCustomMessage(source string, msgAndArgs ...interface{}) string { + custom := Message(msgAndArgs...) + switch { + case custom == "": + return source + case source == "": + return custom + } + return fmt.Sprintf("%s: %s", source, custom) +} diff --git a/vendor/gotest.tools/internal/source/defers.go b/vendor/gotest.tools/internal/source/defers.go new file mode 100644 index 0000000..66cfafb --- /dev/null +++ b/vendor/gotest.tools/internal/source/defers.go @@ -0,0 +1,53 @@ +package source + +import ( + "go/ast" + "go/token" + + "github.com/pkg/errors" +) + +func scanToDeferLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { + var matchedNode ast.Node + ast.Inspect(node, func(node ast.Node) bool { + switch { + case node == nil || matchedNode != nil: + return false + case fileset.Position(node.End()).Line == lineNum: + if funcLit, ok := node.(*ast.FuncLit); ok { + matchedNode = funcLit + return false + } + } + return true + }) + debug("defer line node: %s", debugFormatNode{matchedNode}) + return matchedNode +} + +func guessDefer(node ast.Node) (ast.Node, error) { + defers := collectDefers(node) + switch len(defers) { + case 0: + return nil, errors.New("failed to expression in defer") + case 1: + return defers[0].Call, nil + default: + return nil, errors.Errorf( + "ambiguous call expression: multiple (%d) defers in call block", + len(defers)) + } +} + +func collectDefers(node ast.Node) []*ast.DeferStmt { + var defers []*ast.DeferStmt + ast.Inspect(node, func(node ast.Node) bool { + if d, ok := node.(*ast.DeferStmt); ok { + defers = append(defers, d) + debug("defer: %s", debugFormatNode{d}) + return false + } + return true + }) + return defers +} diff --git a/vendor/gotest.tools/internal/source/source.go b/vendor/gotest.tools/internal/source/source.go new file mode 100644 index 0000000..8a5d0e8 --- /dev/null +++ b/vendor/gotest.tools/internal/source/source.go @@ -0,0 +1,166 @@ +package source // import "gotest.tools/internal/source" + +import ( + "bytes" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "os" + "runtime" + "strconv" + "strings" + + "github.com/pkg/errors" +) + +const baseStackIndex = 1 + +// FormattedCallExprArg returns the argument from an ast.CallExpr at the +// index in the call stack. The argument is formatted using FormatNode. +func FormattedCallExprArg(stackIndex int, argPos int) (string, error) { + args, err := CallExprArgs(stackIndex + 1) + if err != nil { + return "", err + } + if argPos >= len(args) { + return "", errors.New("failed to find expression") + } + return FormatNode(args[argPos]) +} + +// CallExprArgs returns the ast.Expr slice for the args of an ast.CallExpr at +// the index in the call stack. +func CallExprArgs(stackIndex int) ([]ast.Expr, error) { + _, filename, lineNum, ok := runtime.Caller(baseStackIndex + stackIndex) + if !ok { + return nil, errors.New("failed to get call stack") + } + debug("call stack position: %s:%d", filename, lineNum) + + node, err := getNodeAtLine(filename, lineNum) + if err != nil { + return nil, err + } + debug("found node: %s", debugFormatNode{node}) + + return getCallExprArgs(node) +} + +func getNodeAtLine(filename string, lineNum int) (ast.Node, error) { + fileset := token.NewFileSet() + astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse source file: %s", filename) + } + + if node := scanToLine(fileset, astFile, lineNum); node != nil { + return node, nil + } + if node := scanToDeferLine(fileset, astFile, lineNum); node != nil { + node, err := guessDefer(node) + if err != nil || node != nil { + return node, err + } + } + return nil, errors.Errorf( + "failed to find an expression on line %d in %s", lineNum, filename) +} + +func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { + var matchedNode ast.Node + ast.Inspect(node, func(node ast.Node) bool { + switch { + case node == nil || matchedNode != nil: + return false + case nodePosition(fileset, node).Line == lineNum: + matchedNode = node + return false + } + return true + }) + return matchedNode +} + +// In golang 1.9 the line number changed from being the line where the statement +// ended to the line where the statement began. +func nodePosition(fileset *token.FileSet, node ast.Node) token.Position { + if goVersionBefore19 { + return fileset.Position(node.End()) + } + return fileset.Position(node.Pos()) +} + +var goVersionBefore19 = func() bool { + version := runtime.Version() + // not a release version + if !strings.HasPrefix(version, "go") { + return false + } + version = strings.TrimPrefix(version, "go") + parts := strings.Split(version, ".") + if len(parts) < 2 { + return false + } + minor, err := strconv.ParseInt(parts[1], 10, 32) + return err == nil && parts[0] == "1" && minor < 9 +}() + +func getCallExprArgs(node ast.Node) ([]ast.Expr, error) { + visitor := &callExprVisitor{} + ast.Walk(visitor, node) + if visitor.expr == nil { + return nil, errors.New("failed to find call expression") + } + debug("callExpr: %s", debugFormatNode{visitor.expr}) + return visitor.expr.Args, nil +} + +type callExprVisitor struct { + expr *ast.CallExpr +} + +func (v *callExprVisitor) Visit(node ast.Node) ast.Visitor { + if v.expr != nil || node == nil { + return nil + } + debug("visit: %s", debugFormatNode{node}) + + switch typed := node.(type) { + case *ast.CallExpr: + v.expr = typed + return nil + case *ast.DeferStmt: + ast.Walk(v, typed.Call.Fun) + return nil + } + return v +} + +// FormatNode using go/format.Node and return the result as a string +func FormatNode(node ast.Node) (string, error) { + buf := new(bytes.Buffer) + err := format.Node(buf, token.NewFileSet(), node) + return buf.String(), err +} + +var debugEnabled = os.Getenv("GOTESTTOOLS_DEBUG") != "" + +func debug(format string, args ...interface{}) { + if debugEnabled { + fmt.Fprintf(os.Stderr, "DEBUG: "+format+"\n", args...) + } +} + +type debugFormatNode struct { + ast.Node +} + +func (n debugFormatNode) String() string { + out, err := FormatNode(n.Node) + if err != nil { + return fmt.Sprintf("failed to format %s: %s", n.Node, err) + } + return fmt.Sprintf("(%T) %s", n.Node, out) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 325975b..35b057b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,10 +1,13 @@ # github.com/Microsoft/go-winio v0.4.11 github.com/Microsoft/go-winio +# github.com/actions/workflow-parser v1.0.0 +github.com/actions/workflow-parser/model +github.com/actions/workflow-parser/parser # github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 github.com/containerd/continuity/pathdriver # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew -# github.com/docker/distribution v2.7.0+incompatible +# github.com/docker/distribution v2.7.1+incompatible github.com/docker/distribution/reference github.com/docker/distribution/digestset # github.com/docker/docker v1.13.1 => github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb @@ -41,7 +44,7 @@ github.com/docker/go-connections/sockets github.com/docker/go-connections/tlsconfig # github.com/docker/go-units v0.3.3 github.com/docker/go-units -# github.com/emirpasic/gods v1.9.0 +# github.com/emirpasic/gods v1.12.0 github.com/emirpasic/gods/trees/binaryheap github.com/emirpasic/gods/containers github.com/emirpasic/gods/lists/arraylist @@ -52,14 +55,19 @@ github.com/emirpasic/gods/lists github.com/go-ini/ini # github.com/gogo/protobuf v1.2.0 github.com/gogo/protobuf/proto +# github.com/google/go-cmp v0.2.0 +github.com/google/go-cmp/cmp +github.com/google/go-cmp/cmp/internal/diff +github.com/google/go-cmp/cmp/internal/function +github.com/google/go-cmp/cmp/internal/value # github.com/hashicorp/hcl v1.0.0 github.com/hashicorp/hcl github.com/hashicorp/hcl/hcl/ast -github.com/hashicorp/hcl/hcl/token github.com/hashicorp/hcl/hcl/parser +github.com/hashicorp/hcl/hcl/token github.com/hashicorp/hcl/json/parser -github.com/hashicorp/hcl/hcl/strconv github.com/hashicorp/hcl/hcl/scanner +github.com/hashicorp/hcl/hcl/strconv github.com/hashicorp/hcl/json/scanner github.com/hashicorp/hcl/json/token # github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c @@ -72,7 +80,7 @@ github.com/jbenet/go-context/io github.com/kevinburke/ssh_config # github.com/konsorten/go-windows-terminal-sequences v1.0.1 github.com/konsorten/go-windows-terminal-sequences -# github.com/mitchellh/go-homedir v1.0.0 +# github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir # github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/go-digest @@ -92,6 +100,10 @@ github.com/pmezard/go-difflib/difflib github.com/sergi/go-diff/diffmatchpatch # github.com/sirupsen/logrus v1.3.0 github.com/sirupsen/logrus +# github.com/soniakeys/bits v1.0.0 +github.com/soniakeys/bits +# github.com/soniakeys/graph v0.0.0 +github.com/soniakeys/graph # github.com/spf13/cobra v0.0.3 github.com/spf13/cobra # github.com/spf13/pflag v1.0.3 @@ -105,7 +117,7 @@ github.com/src-d/gcfg/types github.com/stretchr/testify/assert # github.com/xanzy/ssh-agent v0.2.0 github.com/xanzy/ssh-agent -# golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc +# golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613 golang.org/x/crypto/ssh/terminal golang.org/x/crypto/openpgp golang.org/x/crypto/openpgp/armor @@ -123,24 +135,24 @@ golang.org/x/crypto/internal/chacha20 golang.org/x/crypto/poly1305 golang.org/x/crypto/ed25519/internal/edwards25519 golang.org/x/crypto/internal/subtle -# golang.org/x/net v0.0.0-20181220203305-927f97764cc3 +# golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 golang.org/x/net/context/ctxhttp golang.org/x/net/proxy golang.org/x/net/context golang.org/x/net/internal/socks -# golang.org/x/sys v0.0.0-20190102155601-82a175fd1598 +# golang.org/x/sys v0.0.0-20190201152629-afcc84fd7533 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/text v0.3.0 +# golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 golang.org/x/text/unicode/norm golang.org/x/text/transform -# gopkg.in/src-d/go-billy.v4 v4.2.1 +# gopkg.in/src-d/go-billy.v4 v4.3.0 gopkg.in/src-d/go-billy.v4 gopkg.in/src-d/go-billy.v4/osfs gopkg.in/src-d/go-billy.v4/util gopkg.in/src-d/go-billy.v4/helper/chroot gopkg.in/src-d/go-billy.v4/helper/polyfill -# gopkg.in/src-d/go-git.v4 v4.8.1 +# gopkg.in/src-d/go-git.v4 v4.9.1 gopkg.in/src-d/go-git.v4 gopkg.in/src-d/go-git.v4/plumbing gopkg.in/src-d/go-git.v4/config @@ -185,3 +197,9 @@ gopkg.in/src-d/go-git.v4/plumbing/transport/server gopkg.in/warnings.v0 # gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 +# gotest.tools v2.2.0+incompatible +gotest.tools/assert +gotest.tools/assert/cmp +gotest.tools/internal/format +gotest.tools/internal/source +gotest.tools/internal/difflib