diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md new file mode 100644 index 00000000000..c7b0ce5c86c --- /dev/null +++ b/DEPENDENCIES.md @@ -0,0 +1,66 @@ +# Dependency Management +[`dep`](https://github.com/golang/dep) is a tool of choice when it comes to dependency management. + +## How we use `dep`. + +1. Transitive dependencies of `go-ethereum`. The most important thing for us is + to be in-sync there. We want to reduce the regression scope. + Hence, we pin down all the dependencies of `go-ethereum` with SHAs in `Gopkg.toml` when + importing a new version of upstream. (This is considered a bad practice for + `dep` but we are willing to take the risk to keep consitency with the upstream). + +2. Exclusive `status-go` dependencies. The policy there is to keep them as + fresh as possible. Hence, no constraints for them in the `toml` file. + +## Installing `dep` + +`go get -u github.com/golang/dep/cmd/dep` + + +## Docs (worth reading) +1. [README](https://github.com/golang/dep/blob/master/README.md) +2. [F.A.Q.](https://github.com/golang/dep/blob/master/docs/FAQ.md) + + +## Checking-out all dependencies + +`dep ensure` - download all the dependencies based on `Gopkg.lock`. + +`Gopkg.lock` is kept inact if it is in-sync with `Gopkg.toml`. If the `toml` +file is changed, `dep ensure` will re-generate `Gopkg.lock` as well. + + +## Adding a new Dependency +(see [Adding a new dependency](https://github.com/golang/dep#adding-a-dependency)) +1. `$ dep ensure -add github.com/foo/bar` +2. Commit changes. + + +## Updating a dependency +(see: [Changing a Dependency](https://github.com/golang/dep#changing-dependencies)) +1. Update constraint in the `Gopkg.toml` file if needed. +2. Run `dep ensure -update github.com/foo/bar` +3. Commit changes. + +## Updating all dependencies + +`dep ensure -update` + +## Updating `Geth` + +1. Update `develop` branch in [`status-im/go-ethereum`](https://github.com/status-im/go-ethereum/tree/develop). +2. Update the `go-ethereum` dependency: `dep ensure -v -update github.com/ethereum/go-ethereum`. +3. Make sure that `[[constraint]]` statements in `status-go/Gopkg.toml` contains the same SHAs as `go-ethereum/vendor/vendor.json`. +4. Update vendor files in `status-go`, running `dep ensure`. +5. Commit `Gopkg.lock`, `Gopkg.toml` and `vendor` directories. + + +## Commiting changes + +Make sure that you don't commit unnecessary changes to `Gopkg.toml` and +`Gopkg.lock`. + + +## Common issues + +1. Relative imports and "Could not introduce package, as its subpackage does not contain usable Go code". See [this comment](https://github.com/golang/dep/issues/899#issuecomment-317904001) for more information. diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 00000000000..75826a01749 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,372 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/NaySoftware/go-fcm" + packages = ["."] + revision = "2a6c4f48b49f0d5dbfe621589da4c5405157d7c9" + +[[projects]] + name = "github.com/aristanetworks/goarista" + packages = ["monotime"] + revision = "ea17b1a17847fb6e4c0a91de0b674704693469b0" + +[[projects]] + name = "github.com/btcsuite/btcd" + packages = [ + "btcec", + "chaincfg", + "chaincfg/chainhash", + "wire" + ] + revision = "d06c0bb181529331be8f8d9350288c420d9e60e4" + +[[projects]] + name = "github.com/btcsuite/btcutil" + packages = [ + ".", + "base58" + ] + revision = "dcd4997b0664bcfd6ef48e4ae9da8396e08b1cd9" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + +[[projects]] + name = "github.com/edsrzf/mmap-go" + packages = ["."] + revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8" + +[[projects]] + branch = "develop" + name = "github.com/ethereum/go-ethereum" + packages = [ + ".", + "accounts", + "accounts/keystore", + "accounts/usbwallet", + "accounts/usbwallet/internal/trezor", + "cmd/utils", + "common", + "common/bitutil", + "common/hexutil", + "common/math", + "common/mclock", + "consensus", + "consensus/clique", + "consensus/ethash", + "consensus/misc", + "core", + "core/bloombits", + "core/state", + "core/types", + "core/vm", + "crypto", + "crypto/bn256", + "crypto/ecies", + "crypto/randentropy", + "crypto/secp256k1", + "crypto/sha3", + "dashboard", + "eth", + "eth/downloader", + "eth/fetcher", + "eth/filters", + "eth/gasprice", + "ethdb", + "ethstats", + "event", + "internal/debug", + "internal/ethapi", + "les", + "les/flowcontrol", + "les/status", + "light", + "log", + "log/term", + "metrics", + "miner", + "node", + "p2p", + "p2p/discover", + "p2p/discv5", + "p2p/nat", + "p2p/netutil", + "params", + "rlp", + "rpc", + "trie", + "whisper/mailserver", + "whisper/notifications", + "whisper/whisperv5" + ] + revision = "0e836de922116088b7621b86adf630a86d944c07" + source = "https://github.com/status-im/go-ethereum.git" + +[[projects]] + name = "github.com/go-playground/locales" + packages = [ + ".", + "currency" + ] + revision = "e4cbcb5d0652150d40ad0646651076b6bd2be4f6" + version = "v0.11.2" + +[[projects]] + name = "github.com/go-playground/universal-translator" + packages = ["."] + revision = "b32fa301c9fe55953584134cb6853a13c87ec0a1" + version = "v0.16.0" + +[[projects]] + name = "github.com/go-stack/stack" + packages = ["."] + revision = "54be5f394ed2c3e19dac9134a40a95ba5a017f7b" + +[[projects]] + name = "github.com/golang/mock" + packages = ["gomock"] + revision = "13f360950a79f5864a972c786a10a50e44b69541" + version = "v1.0.0" + +[[projects]] + name = "github.com/golang/protobuf" + packages = [ + "proto", + "protoc-gen-go/descriptor" + ] + revision = "748d386b5c1ea99658fd69fe9f03991ce86a90c1" + +[[projects]] + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru" + ] + revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6" + +[[projects]] + name = "github.com/huin/goupnp" + packages = [ + ".", + "dcps/internetgateway1", + "dcps/internetgateway2", + "httpu", + "scpd", + "soap", + "ssdp" + ] + revision = "679507af18f3c7ba2bcc7905392ce23e148661c3" + +[[projects]] + name = "github.com/jackpal/go-nat-pmp" + packages = ["."] + revision = "1fa385a6f45828c83361136b45b1a21a12139493" + +[[projects]] + name = "github.com/karalabe/hid" + packages = ["."] + revision = "f00545f9f3748e591590be3732d913c77525b10f" + +[[projects]] + name = "github.com/mattn/go-colorable" + packages = ["."] + revision = "5411d3eea5978e6cdc258b30de592b60df6aba96" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "281032e84ae07510239465db46bf442aa44b953a" + +[[projects]] + name = "github.com/pborman/uuid" + packages = ["."] + revision = "1b00554d822231195d1babd97ff4a781231955c9" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + +[[projects]] + name = "github.com/prometheus/prometheus" + packages = ["util/flock"] + revision = "3101606756c53221ed58ba94ecba6b26adf89dcc" + +[[projects]] + name = "github.com/rcrowley/go-metrics" + packages = [ + ".", + "exp" + ] + revision = "1f30fe9094a513ce4c700b9a54458bbb0c96996c" + +[[projects]] + name = "github.com/rjeczalik/notify" + packages = ["."] + revision = "9d5aa0c3b735c3340018a4627446c3ea5a04a097" + +[[projects]] + name = "github.com/robertkrimen/otto" + packages = [ + ".", + "ast", + "dbg", + "file", + "parser", + "registry", + "token" + ] + revision = "9c716adcc8cedb0c0e3c02be549f4ad20e0b216c" + +[[projects]] + name = "github.com/rs/cors" + packages = ["."] + revision = "a62a804a8a009876ca59105f7899938a1349f4b3" + +[[projects]] + name = "github.com/rs/xhandler" + packages = ["."] + revision = "ed27b6fd65218132ee50cd95f38474a3d8a2cd12" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + "suite" + ] + revision = "890a5c3458b43e6104ff5da8dfa139d013d77544" + +[[projects]] + name = "github.com/syndtr/goleveldb" + packages = [ + "leveldb", + "leveldb/cache", + "leveldb/comparer", + "leveldb/errors", + "leveldb/filter", + "leveldb/iterator", + "leveldb/journal", + "leveldb/memdb", + "leveldb/opt", + "leveldb/storage", + "leveldb/table", + "leveldb/util" + ] + revision = "b89cc31ef7977104127d34c1bd31ebd1a9db2199" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "pbkdf2", + "ripemd160", + "scrypt" + ] + revision = "13931e22f9e72ea58bb73048bc752b48c6d4d4ac" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "html", + "html/atom", + "html/charset", + "websocket" + ] + revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec" + +[[projects]] + branch = "master" + name = "golang.org/x/sync" + packages = ["syncmap"] + revision = "fd80eb99c8f653c847d294a001bdf2a3a6f768f5" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "2c42eef0765b9837fbdab12011af7830f55f88f0" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = [ + "encoding", + "encoding/charmap", + "encoding/htmlindex", + "encoding/internal", + "encoding/internal/identifier", + "encoding/japanese", + "encoding/korean", + "encoding/simplifiedchinese", + "encoding/traditionalchinese", + "encoding/unicode", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "internal/utf8internal", + "language", + "runes", + "transform", + "unicode/cldr", + "unicode/norm" + ] + revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" + +[[projects]] + branch = "v0.1.1" + name = "gopkg.in/fatih/set.v0" + packages = ["."] + revision = "27c40922c40b43fe04554d8223a402af3ea333f3" + +[[projects]] + name = "gopkg.in/go-playground/validator.v9" + packages = ["."] + revision = "48a433ba4bcadc5be9aa16d4bdcb383d3f57a741" + version = "v9.9.3" + +[[projects]] + branch = "v2" + name = "gopkg.in/karalabe/cookiejar.v2" + packages = ["collections/prque"] + revision = "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57" + +[[projects]] + branch = "v2" + name = "gopkg.in/natefinch/npipe.v2" + packages = ["."] + revision = "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6" + +[[projects]] + name = "gopkg.in/sourcemap.v1" + packages = [ + ".", + "base64vlq" + ] + revision = "6e83acea0053641eff084973fee085f0c193c61a" + version = "v1.0.5" + +[[projects]] + name = "gopkg.in/urfave/cli.v1" + packages = ["."] + revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1" + version = "v1.20.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "88da891a2f95812ac0244320ac9816905986a3f72870f14da7e63eb7c6feb8eb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 00000000000..3d789aee0b6 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,129 @@ +[prune] + unused-packages = true + go-tests = true + + [[prune.project]] + name = "github.com/karalabe/hid" + non-go = false + unused-packages = false + + [[prune.project]] + name = "github.com/ethereum/go-ethereum" + non-go = false + unused-packages = false + +# * * * * * constrained `status-go` dependencies * * * * * +# (for the full dependency list see `Gopkg.lock`) + +[[constraint]] + # `btcutil` is required to be compatible with `btcd` + name = "github.com/btcsuite/btcutil" + revision = "dcd4997b0664bcfd6ef48e4ae9da8396e08b1cd9" + +[[constraint]] + # fork of `go-ethereum` with Status patches + name = "github.com/ethereum/go-ethereum" + branch = "develop" + source = "https://github.com/status-im/go-ethereum.git" + +# * * * * * `go-ethereum` dependencies * * * * * +# Pinned down SHAs from `go-ethereum/vendor/vendor.json` +# When upgrading upstream, upgrade these values too. +[[override]] + name = "github.com/aristanetworks/goarista" + revision = "ea17b1a17847fb6e4c0a91de0b674704693469b0" + +[[override]] + name = "github.com/btcsuite/btcd" + revision = "d06c0bb181529331be8f8d9350288c420d9e60e4" + +[[override]] + name = "github.com/davecgh/go-spew" + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + +[[override]] + name = "github.com/edsrzf/mmap-go" + revision = "935e0e8a636ca4ba70b713f3e38a19e1b77739e8" + +[[override]] + name = "github.com/go-stack/stack" + revision = "54be5f394ed2c3e19dac9134a40a95ba5a017f7b" + +[[override]] + name = "github.com/golang/protobuf" + revision = "748d386b5c1ea99658fd69fe9f03991ce86a90c1" + +[[override]] + name = "github.com/golang/snappy" + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[override]] + name = "github.com/hashicorp/golang-lru" + revision = "0a025b7e63adc15a622f29b0b2c4c3848243bbf6" + +[[override]] + name = "github.com/huin/goupnp" + revision = "679507af18f3c7ba2bcc7905392ce23e148661c3" + +[[override]] + name = "github.com/jackpal/go-nat-pmp" + revision = "1fa385a6f45828c83361136b45b1a21a12139493" + +[[override]] + name = "github.com/karalabe/hid" + revision = "f00545f9f3748e591590be3732d913c77525b10f" + +[[override]] + name = "github.com/mattn/go-colorable" + revision = "5411d3eea5978e6cdc258b30de592b60df6aba96" + +[[override]] + name = "github.com/mattn/go-isatty" + revision = "281032e84ae07510239465db46bf442aa44b953a" + +[[override]] + name = "github.com/pborman/uuid" + revision = "1b00554d822231195d1babd97ff4a781231955c9" + +[[override]] + name = "github.com/pmezard/go-difflib" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + +[[override]] + name = "github.com/prometheus/prometheus" + revision = "3101606756c53221ed58ba94ecba6b26adf89dcc" + +[[override]] + name = "github.com/rcrowley/go-metrics" + revision = "1f30fe9094a513ce4c700b9a54458bbb0c96996c" + +[[override]] + name = "github.com/rjeczalik/notify" + revision = "9d5aa0c3b735c3340018a4627446c3ea5a04a097" + +[[override]] + name = "github.com/robertkrimen/otto" + # (@mandrigin): This supposed to be contrained as: + # + # revision = "6a77b7cbc37d0c39f7d5fa5766826e541df31fd5" + # + # but it has relative imports that break everything. + # The following revision only differs from the source + # with fixing relative imports. + revision = "9c716adcc8cedb0c0e3c02be549f4ad20e0b216c" + +[[override]] + name = "github.com/rs/cors" + revision = "a62a804a8a009876ca59105f7899938a1349f4b3" + +[[override]] + name = "github.com/rs/xhandler" + revision = "ed27b6fd65218132ee50cd95f38474a3d8a2cd12" + +[[override]] + name = "github.com/stretchr/testify" + revision = "890a5c3458b43e6104ff5da8dfa139d013d77544" + +[[override]] + name = "github.com/syndtr/goleveldb" + revision = "b89cc31ef7977104127d34c1bd31ebd1a9db2199" diff --git a/vendor/github.com/NaySoftware/go-fcm/fcm.go b/vendor/github.com/NaySoftware/go-fcm/fcm.go index a12ad612d67..97140a0bf5f 100644 --- a/vendor/github.com/NaySoftware/go-fcm/fcm.go +++ b/vendor/github.com/NaySoftware/go-fcm/fcm.go @@ -73,18 +73,19 @@ type FcmResponseStatus struct { // NotificationPayload notification message payload type NotificationPayload struct { - Title string `json:"title,omitempty"` - Body string `json:"body,omitempty"` - Icon string `json:"icon,omitempty"` - Sound string `json:"sound,omitempty"` - Badge string `json:"badge,omitempty"` - Tag string `json:"tag,omitempty"` - Color string `json:"color,omitempty"` - ClickAction string `json:"click_action,omitempty"` - BodyLocKey string `json:"body_loc_key,omitempty"` - BodyLocArgs string `json:"body_loc_args,omitempty"` - TitleLocKey string `json:"title_loc_key,omitempty"` - TitleLocArgs string `json:"title_loc_args,omitempty"` + Title string `json:"title,omitempty"` + Body string `json:"body,omitempty"` + Icon string `json:"icon,omitempty"` + Sound string `json:"sound,omitempty"` + Badge string `json:"badge,omitempty"` + Tag string `json:"tag,omitempty"` + Color string `json:"color,omitempty"` + ClickAction string `json:"click_action,omitempty"` + BodyLocKey string `json:"body_loc_key,omitempty"` + BodyLocArgs string `json:"body_loc_args,omitempty"` + TitleLocKey string `json:"title_loc_key,omitempty"` + TitleLocArgs string `json:"title_loc_args,omitempty"` + AndroidChannelID string `json:"android_channel_id,omitempty"` } // NewFcmClient init and create fcm client diff --git a/vendor/github.com/aristanetworks/goarista/AUTHORS b/vendor/github.com/aristanetworks/goarista/AUTHORS new file mode 100644 index 00000000000..5bb93cb3fa6 --- /dev/null +++ b/vendor/github.com/aristanetworks/goarista/AUTHORS @@ -0,0 +1,25 @@ +All contributors are required to sign a "Contributor License Agreement" at + + +The following organizations and people have contributed code to this library. +(Please keep both lists sorted alphabetically.) + + +Arista Networks, Inc. + + +Benoit Sigoure +Fabrice Rabaute + + + +The list of individual contributors for code currently in HEAD can be obtained +at any time with the following script: + +find . -type f \ +| while read i; do \ + git blame -t $i 2>/dev/null; \ + done \ +| sed 's/^[0-9a-f]\{8\} [^(]*(\([^)]*\) [-+0-9 ]\{14,\}).*/\1/;s/ *$//' \ +| awk '{a[$0]++; t++} END{for(n in a) print n}' \ +| sort diff --git a/vendor/github.com/aristanetworks/goarista/atime/issue15006.s b/vendor/github.com/aristanetworks/goarista/atime/issue15006.s deleted file mode 100644 index 66109f4f317..00000000000 --- a/vendor/github.com/aristanetworks/goarista/atime/issue15006.s +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (C) 2016 Arista Networks, Inc. -// Use of this source code is governed by the Apache License 2.0 -// that can be found in the COPYING file. - -// This file is intentionally empty. -// It's a workaround for https://github.com/golang/go/issues/15006 diff --git a/vendor/github.com/aristanetworks/goarista/atime/nanotime.go b/vendor/github.com/aristanetworks/goarista/atime/nanotime.go deleted file mode 100644 index 8877cdca1f9..00000000000 --- a/vendor/github.com/aristanetworks/goarista/atime/nanotime.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2016 Arista Networks, Inc. -// Use of this source code is governed by the Apache License 2.0 -// that can be found in the COPYING file. - -// Package atime provides a fast monotonic clock source. -package atime - -import ( - _ "unsafe" // required to use //go:linkname -) - -//go:noescape -//go:linkname nanotime runtime.nanotime -func nanotime() int64 - -// NanoTime returns the current time in nanoseconds from a monotonic clock. -// The time returned is based on some arbitrary platform-specific point in the -// past. The time returned is guaranteed to increase monotonically at a -// constant rate, unlike time.Now() from the Go standard library, which may -// slow down, speed up, jump forward or backward, due to NTP activity or leap -// seconds. -func NanoTime() uint64 { - return uint64(nanotime()) -} diff --git a/vendor/github.com/aristanetworks/goarista/monitor/stats/LICENSE b/vendor/github.com/aristanetworks/goarista/monitor/stats/LICENSE new file mode 100644 index 00000000000..f4988b45079 --- /dev/null +++ b/vendor/github.com/aristanetworks/goarista/monitor/stats/LICENSE @@ -0,0 +1,28 @@ +Copyright 2014, Google Inc. +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/aristanetworks/goarista/monotime/nanotime.go b/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go index efc1b92a606..5f5fbc7ae56 100644 --- a/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go +++ b/vendor/github.com/aristanetworks/goarista/monotime/nanotime.go @@ -6,6 +6,7 @@ package monotime import ( + "time" _ "unsafe" // required to use //go:linkname ) @@ -22,3 +23,9 @@ func nanotime() int64 func Now() uint64 { return uint64(nanotime()) } + +// Since returns the amount of time that has elapsed since t. t should be +// the result of a call to Now() on the same machine. +func Since(t uint64) time.Duration { + return time.Duration(Now() - t) +} diff --git a/vendor/github.com/btcsuite/btcd/LICENSE b/vendor/github.com/btcsuite/btcd/LICENSE index 49de919577d..53ba0c5608d 100644 --- a/vendor/github.com/btcsuite/btcd/LICENSE +++ b/vendor/github.com/btcsuite/btcd/LICENSE @@ -1,6 +1,7 @@ ISC License -Copyright (c) 2013-2016 The btcsuite developers +Copyright (c) 2013-2017 The btcsuite developers +Copyright (c) 2015-2016 The Decred developers Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/btcsuite/btcd/btcec/field.go b/vendor/github.com/btcsuite/btcd/btcec/field.go index 2a74878ba53..c2c6a645d44 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/field.go +++ b/vendor/github.com/btcsuite/btcd/btcec/field.go @@ -1,5 +1,5 @@ -// Copyright (c) 2013-2014 The btcsuite developers -// Copyright (c) 2013-2014 Dave Collins +// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2013-2016 Dave Collins // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -94,14 +94,16 @@ const ( fieldMSBMask = (1 << fieldMSBBits) - 1 // fieldPrimeWordZero is word zero of the secp256k1 prime in the - // internal field representation. It is used during modular reduction - // and negation. + // internal field representation. It is used during negation. fieldPrimeWordZero = 0x3fffc2f // fieldPrimeWordOne is word one of the secp256k1 prime in the - // internal field representation. It is used during modular reduction - // and negation. + // internal field representation. It is used during negation. fieldPrimeWordOne = 0x3ffffbf + + // primeLowBits is the lower 2*fieldBase bits of the secp256k1 prime in + // its standard normalized form. It is used during modular reduction. + primeLowBits = 0xffffefffffc2f ) // fieldVal implements optimized fixed-precision arithmetic over the @@ -331,12 +333,8 @@ func (f *fieldVal) Normalize() *fieldVal { // zero even though it won't change the value to ensure constant time // between the branches. var mask int32 - if t0 < fieldPrimeWordZero { - mask |= -1 - } else { - mask |= 0 - } - if t1 < fieldPrimeWordOne { + lowBits := uint64(t1)<> fieldBase) & fieldBaseMask) t2 = t2 & uint32(mask) t3 = t3 & uint32(mask) t4 = t4 & uint32(mask) diff --git a/vendor/github.com/btcsuite/btcd/btcec/pubkey.go b/vendor/github.com/btcsuite/btcd/btcec/pubkey.go index be6f8509787..f145414eccb 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/pubkey.go +++ b/vendor/github.com/btcsuite/btcd/btcec/pubkey.go @@ -25,7 +25,7 @@ func isOdd(a *big.Int) bool { // decompressPoint decompresses a point on the given curve given the X point and // the solution to use. func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, error) { - // TODO(oga) This will probably only work for secp256k1 due to + // TODO: This will probably only work for secp256k1 due to // optimizations. // Y = +-sqrt(x^3 + B) diff --git a/vendor/github.com/btcsuite/btcd/btcec/signature.go b/vendor/github.com/btcsuite/btcd/btcec/signature.go index ab5a345c4cd..9b27652079f 100644 --- a/vendor/github.com/btcsuite/btcd/btcec/signature.go +++ b/vendor/github.com/btcsuite/btcd/btcec/signature.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2014 The btcsuite developers +// Copyright (c) 2013-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -9,12 +9,11 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/hmac" + "crypto/sha256" "errors" "fmt" "hash" "math/big" - - "github.com/btcsuite/fastsha256" ) // Errors returned by canonicalPadding. @@ -329,7 +328,7 @@ func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, e.Mod(e, curve.Params().N) minuseGx, minuseGy := curve.ScalarBaseMult(e.Bytes()) - // TODO(oga) this would be faster if we did a mult and add in one + // TODO: this would be faster if we did a mult and add in one // step to prevent the jacobian conversion back and forth. Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy) @@ -455,7 +454,7 @@ func nonceRFC6979(privkey *big.Int, hash []byte) *big.Int { curve := S256() q := curve.Params().N x := privkey - alg := fastsha256.New + alg := sha256.New qlen := q.BitLen() holen := alg().Size() diff --git a/vendor/github.com/btcsuite/btcd/btcjson/CONTRIBUTORS b/vendor/github.com/btcsuite/btcd/btcjson/CONTRIBUTORS new file mode 100644 index 00000000000..b8d98b32f34 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcjson/CONTRIBUTORS @@ -0,0 +1,16 @@ +# This is the list of people who have contributed code to the repository. +# +# Names should be added to this file only after verifying that the individual +# or the individual's organization has agreed to the LICENSE. +# +# Names should be added to this file like so: +# Name + +John C. Vernaleo +Dave Collins +Owain G. Ainsworth +David Hill +Josh Rickmar +Andreas Metsälä +Francis Lam +Geert-Johan Riemer diff --git a/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hash.go b/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hash.go index 83004d50e8a..2b1cec022be 100644 --- a/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hash.go +++ b/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hash.go @@ -84,35 +84,45 @@ func NewHash(newHash []byte) (*Hash, error) { // the hexadecimal string of a byte-reversed hash, but any missing characters // result in zero padding at the end of the Hash. func NewHashFromStr(hash string) (*Hash, error) { + ret := new(Hash) + err := Decode(ret, hash) + if err != nil { + return nil, err + } + return ret, nil +} + +// Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a +// destination. +func Decode(dst *Hash, src string) error { // Return error if hash string is too long. - if len(hash) > MaxHashStringSize { - return nil, ErrHashStrSize + if len(src) > MaxHashStringSize { + return ErrHashStrSize } - // Hex decoder expects the hash to be a multiple of two. - if len(hash)%2 != 0 { - hash = "0" + hash + // Hex decoder expects the hash to be a multiple of two. When not, pad + // with a leading zero. + var srcBytes []byte + if len(src)%2 == 0 { + srcBytes = []byte(src) + } else { + srcBytes = make([]byte, 1+len(src)) + srcBytes[0] = '0' + copy(srcBytes[1:], src) } - // Convert string hash to bytes. - buf, err := hex.DecodeString(hash) + // Hex decode the source bytes to a temporary destination. + var reversedHash Hash + _, err := hex.Decode(reversedHash[HashSize-hex.DecodedLen(len(srcBytes)):], srcBytes) if err != nil { - return nil, err + return err } - // Un-reverse the decoded bytes, copying into in leading bytes of a - // Hash. There is no need to explicitly pad the result as any - // missing (when len(buf) < HashSize) bytes from the decoded hex string - // will remain zeros at the end of the Hash. - var ret Hash - blen := len(buf) - mid := blen / 2 - if blen%2 != 0 { - mid++ - } - blen-- - for i, b := range buf[:mid] { - ret[i], ret[blen-i] = buf[blen-i], b + // Reverse copy from the temporary hash to destination. Because the + // temporary was zeroed, the written result will be correctly padded. + for i, b := range reversedHash[:HashSize/2] { + dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b } - return &ret, nil + + return nil } diff --git a/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hashfuncs.go b/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hashfuncs.go index ae7a380ae1e..bf74f73c397 100644 --- a/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hashfuncs.go +++ b/vendor/github.com/btcsuite/btcd/chaincfg/chainhash/hashfuncs.go @@ -1,33 +1,33 @@ // Copyright (c) 2015 The Decred developers -// Copyright (c) 2016 The btcsuite developers +// Copyright (c) 2016-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package chainhash -import "github.com/btcsuite/fastsha256" +import "crypto/sha256" // HashB calculates hash(b) and returns the resulting bytes. func HashB(b []byte) []byte { - hash := fastsha256.Sum256(b) + hash := sha256.Sum256(b) return hash[:] } // HashH calculates hash(b) and returns the resulting bytes as a Hash. func HashH(b []byte) Hash { - return Hash(fastsha256.Sum256(b)) + return Hash(sha256.Sum256(b)) } // DoubleHashB calculates hash(hash(b)) and returns the resulting bytes. func DoubleHashB(b []byte) []byte { - first := fastsha256.Sum256(b) - second := fastsha256.Sum256(first[:]) + first := sha256.Sum256(b) + second := sha256.Sum256(first[:]) return second[:] } // DoubleHashH calculates hash(hash(b)) and returns the resulting bytes as a // Hash. func DoubleHashH(b []byte) Hash { - first := fastsha256.Sum256(b) - return Hash(fastsha256.Sum256(first[:])) + first := sha256.Sum256(b) + return Hash(sha256.Sum256(first[:])) } diff --git a/vendor/github.com/btcsuite/btcd/chaincfg/params.go b/vendor/github.com/btcsuite/btcd/chaincfg/params.go index 120fe0c4c88..451683de06d 100644 --- a/vendor/github.com/btcsuite/btcd/chaincfg/params.go +++ b/vendor/github.com/btcsuite/btcd/chaincfg/params.go @@ -6,6 +6,7 @@ package chaincfg import ( "errors" + "math" "math/big" "time" @@ -50,6 +51,47 @@ type Checkpoint struct { Hash *chainhash.Hash } +// DNSSeed identifies a DNS seed. +type DNSSeed struct { + // Host defines the hostname of the seed. + Host string + + // HasFiltering defines whether the seed supports filtering + // by service flags (wire.ServiceFlag). + HasFiltering bool +} + +// ConsensusDeployment defines details related to a specific consensus rule +// change that is voted in. This is part of BIP0009. +type ConsensusDeployment struct { + // BitNumber defines the specific bit number within the block version + // this particular soft-fork deployment refers to. + BitNumber uint8 + + // StartTime is the median block time after which voting on the + // deployment starts. + StartTime uint64 + + // ExpireTime is the median block time after which the attempted + // deployment expires. + ExpireTime uint64 +} + +// Constants that define the deployment offset in the deployments field of the +// parameters for each deployment. This is useful to be able to get the details +// of a specific deployment by name. +const ( + // DeploymentTestDummy defines the rule change deployment ID for testing + // purposes. + DeploymentTestDummy = iota + + // NOTE: DefinedDeployments must always come last since it is used to + // determine how many defined deployments there currently are. + + // DefinedDeployments is the number of currently defined deployments. + DefinedDeployments +) + // Params defines a Bitcoin network by its parameters. These parameters may be // used by Bitcoin applications to differentiate networks as well as addresses // and keys for one network from those intended for use on another network. @@ -65,7 +107,7 @@ type Params struct { // DNSSeeds defines a list of DNS seeds for the network that are used // as one method to discover peers. - DNSSeeds []string + DNSSeeds []DNSSeed // GenesisBlock defines the first block of the chain. GenesisBlock *wire.MsgBlock @@ -81,6 +123,12 @@ type Params struct { // block in compact form. PowLimitBits uint32 + // These fields define the block heights at which the specified softfork + // BIP became active. + BIP0034Height int32 + BIP0065Height int32 + BIP0066Height int32 + // CoinbaseMaturity is the number of blocks required before newly mined // coins (coinbase transactions) can be spent. CoinbaseMaturity uint16 @@ -122,16 +170,22 @@ type Params struct { // Checkpoints ordered from oldest to newest. Checkpoints []Checkpoint - // Enforce current block version once network has - // upgraded. This is part of BIP0034. - BlockEnforceNumRequired uint64 - - // Reject previous block versions once network has - // upgraded. This is part of BIP0034. - BlockRejectNumRequired uint64 - - // The number of nodes to check. This is part of BIP0034. - BlockUpgradeNumToCheck uint64 + // These fields are related to voting on consensus rule changes as + // defined by BIP0009. + // + // RuleChangeActivationThreshold is the number of blocks in a threshold + // state retarget window for which a positive vote for a rule change + // must be cast in order to lock in a rule change. It should typically + // be 95% for the main network and 75% for test networks. + // + // MinerConfirmationWindow is the number of blocks in each threshold + // state retarget window. + // + // Deployments define the specific consensus rule changes to be voted + // on. + RuleChangeActivationThreshold uint32 + MinerConfirmationWindow uint32 + Deployments [DefinedDeployments]ConsensusDeployment // Mempool parameters RelayNonStdTxs bool @@ -155,14 +209,14 @@ var MainNetParams = Params{ Name: "mainnet", Net: wire.MainNet, DefaultPort: "8333", - DNSSeeds: []string{ - "seed.bitcoin.sipa.be", - "dnsseed.bluematt.me", - "dnsseed.bitcoin.dashjr.org", - "seed.bitcoinstats.com", - "seed.bitnodes.io", - "bitseed.xf2.org", - "seed.bitcoin.jonasschnelli.ch", + DNSSeeds: []DNSSeed{ + {"seed.bitcoin.sipa.be", true}, + {"dnsseed.bluematt.me", true}, + {"dnsseed.bitcoin.dashjr.org", false}, + {"seed.bitcoinstats.com", true}, + {"seed.bitnodes.io", false}, + {"bitseed.xf2.org", false}, + {"seed.bitcoin.jonasschnelli.ch", true}, }, // Chain parameters @@ -170,6 +224,9 @@ var MainNetParams = Params{ GenesisHash: &genesisHash, PowLimit: mainPowLimit, PowLimitBits: 0x1d00ffff, + BIP0034Height: 227931, // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8 + BIP0065Height: 388381, // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 + BIP0066Height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -201,15 +258,19 @@ var MainNetParams = Params{ {382320, newHashFromStr("00000000000000000a8dc6ed5b133d0eb2fd6af56203e4159789b092defd8ab2")}, }, - // Enforce current block version once majority of the network has - // upgraded. - // 75% (750 / 1000) - // Reject previous block versions once a majority of the network has - // upgraded. - // 95% (950 / 1000) - BlockEnforceNumRequired: 750, - BlockRejectNumRequired: 950, - BlockUpgradeNumToCheck: 1000, + // Consensus rule change deployments. + // + // The miner confirmation window is defined as: + // target proof of work timespan / target proof of work spacing + RuleChangeActivationThreshold: 1916, // 95% of MinerConfirmationWindow + MinerConfirmationWindow: 2016, // + Deployments: [DefinedDeployments]ConsensusDeployment{ + DeploymentTestDummy: { + BitNumber: 28, + StartTime: 1199145601, // January 1, 2008 UTC + ExpireTime: 1230767999, // December 31, 2008 UTC + }, + }, // Mempool parameters RelayNonStdTxs: false, @@ -235,7 +296,7 @@ var RegressionNetParams = Params{ Name: "regtest", Net: wire.TestNet, DefaultPort: "18444", - DNSSeeds: []string{}, + DNSSeeds: []DNSSeed{}, // Chain parameters GenesisBlock: ®TestGenesisBlock, @@ -243,6 +304,9 @@ var RegressionNetParams = Params{ PowLimit: regressionPowLimit, PowLimitBits: 0x207fffff, CoinbaseMaturity: 100, + BIP0034Height: 100000000, // Not active - Permit ver 1 blocks + BIP0065Height: 1351, // Used by regression tests + BIP0066Height: 1251, // Used by regression tests SubsidyReductionInterval: 150, TargetTimespan: time.Hour * 24 * 14, // 14 days TargetTimePerBlock: time.Minute * 10, // 10 minutes @@ -254,15 +318,19 @@ var RegressionNetParams = Params{ // Checkpoints ordered from oldest to newest. Checkpoints: nil, - // Enforce current block version once majority of the network has - // upgraded. - // 75% (750 / 1000) - // Reject previous block versions once a majority of the network has - // upgraded. - // 95% (950 / 1000) - BlockEnforceNumRequired: 750, - BlockRejectNumRequired: 950, - BlockUpgradeNumToCheck: 1000, + // Consensus rule change deployments. + // + // The miner confirmation window is defined as: + // target proof of work timespan / target proof of work spacing + RuleChangeActivationThreshold: 108, // 75% of MinerConfirmationWindow + MinerConfirmationWindow: 144, + Deployments: [DefinedDeployments]ConsensusDeployment{ + DeploymentTestDummy: { + BitNumber: 28, + StartTime: 0, // Always available for vote + ExpireTime: math.MaxInt64, // Never expires + }, + }, // Mempool parameters RelayNonStdTxs: true, @@ -288,10 +356,11 @@ var TestNet3Params = Params{ Name: "testnet3", Net: wire.TestNet3, DefaultPort: "18333", - DNSSeeds: []string{ - "testnet-seed.bitcoin.schildbach.de", - "testnet-seed.bitcoin.petertodd.org", - "testnet-seed.bluematt.me", + DNSSeeds: []DNSSeed{ + {"testnet-seed.bitcoin.jonasschnelli.ch", true}, + {"testnet-seed.bitcoin.schildbach.de", false}, + {"seed.tbtc.petertodd.org", true}, + {"testnet-seed.bluematt.me", false}, }, // Chain parameters @@ -299,6 +368,9 @@ var TestNet3Params = Params{ GenesisHash: &testNet3GenesisHash, PowLimit: testNet3PowLimit, PowLimitBits: 0x1d00ffff, + BIP0034Height: 21111, // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8 + BIP0065Height: 581885, // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 + BIP0066Height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -311,17 +383,31 @@ var TestNet3Params = Params{ // Checkpoints ordered from oldest to newest. Checkpoints: []Checkpoint{ {546, newHashFromStr("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, + {100000, newHashFromStr("00000000009e2958c15ff9290d571bf9459e93b19765c6801ddeccadbb160a1e")}, + {200000, newHashFromStr("0000000000287bffd321963ef05feab753ebe274e1d78b2fd4e2bfe9ad3aa6f2")}, + {300001, newHashFromStr("0000000000004829474748f3d1bc8fcf893c88be255e6d7f571c548aff57abf4")}, + {400002, newHashFromStr("0000000005e2c73b8ecb82ae2dbc2e8274614ebad7172b53528aba7501f5a089")}, + {500011, newHashFromStr("00000000000929f63977fbac92ff570a9bd9e7715401ee96f2848f7b07750b02")}, + {600002, newHashFromStr("000000000001f471389afd6ee94dcace5ccc44adc18e8bff402443f034b07240")}, + {700000, newHashFromStr("000000000000406178b12a4dea3b27e13b3c4fe4510994fd667d7c1e6a3f4dc1")}, + {800010, newHashFromStr("000000000017ed35296433190b6829db01e657d80631d43f5983fa403bfdb4c1")}, + {900000, newHashFromStr("0000000000356f8d8924556e765b7a94aaebc6b5c8685dcfa2b1ee8b41acd89b")}, + {1000007, newHashFromStr("00000000001ccb893d8a1f25b70ad173ce955e5f50124261bbbc50379a612ddf")}, }, - // Enforce current block version once majority of the network has - // upgraded. - // 51% (51 / 100) - // Reject previous block versions once a majority of the network has - // upgraded. - // 75% (75 / 100) - BlockEnforceNumRequired: 51, - BlockRejectNumRequired: 75, - BlockUpgradeNumToCheck: 100, + // Consensus rule change deployments. + // + // The miner confirmation window is defined as: + // target proof of work timespan / target proof of work spacing + RuleChangeActivationThreshold: 1512, // 75% of MinerConfirmationWindow + MinerConfirmationWindow: 2016, + Deployments: [DefinedDeployments]ConsensusDeployment{ + DeploymentTestDummy: { + BitNumber: 28, + StartTime: 1199145601, // January 1, 2008 UTC + ExpireTime: 1230767999, // December 31, 2008 UTC + }, + }, // Mempool parameters RelayNonStdTxs: true, @@ -351,13 +437,16 @@ var SimNetParams = Params{ Name: "simnet", Net: wire.SimNet, DefaultPort: "18555", - DNSSeeds: []string{}, // NOTE: There must NOT be any seeds. + DNSSeeds: []DNSSeed{}, // NOTE: There must NOT be any seeds. // Chain parameters GenesisBlock: &simNetGenesisBlock, GenesisHash: &simNetGenesisHash, PowLimit: simNetPowLimit, PowLimitBits: 0x207fffff, + BIP0034Height: 0, // Always active on simnet + BIP0065Height: 0, // Always active on simnet + BIP0066Height: 0, // Always active on simnet CoinbaseMaturity: 100, SubsidyReductionInterval: 210000, TargetTimespan: time.Hour * 24 * 14, // 14 days @@ -370,15 +459,19 @@ var SimNetParams = Params{ // Checkpoints ordered from oldest to newest. Checkpoints: nil, - // Enforce current block version once majority of the network has - // upgraded. - // 51% (51 / 100) - // Reject previous block versions once a majority of the network has - // upgraded. - // 75% (75 / 100) - BlockEnforceNumRequired: 51, - BlockRejectNumRequired: 75, - BlockUpgradeNumToCheck: 100, + // Consensus rule change deployments. + // + // The miner confirmation window is defined as: + // target proof of work timespan / target proof of work spacing + RuleChangeActivationThreshold: 75, // 75% of MinerConfirmationWindow + MinerConfirmationWindow: 100, + Deployments: [DefinedDeployments]ConsensusDeployment{ + DeploymentTestDummy: { + BitNumber: 28, + StartTime: 0, // Always available for vote + ExpireTime: math.MaxInt64, // Never expires + }, + }, // Mempool parameters RelayNonStdTxs: true, @@ -416,6 +509,11 @@ var ( hdPrivToPubKeyIDs = make(map[[4]byte][]byte) ) +// String returns the hostname of the DNS seed in human-readable form. +func (d DNSSeed) String() string { + return d.Host +} + // Register registers the network parameters for a Bitcoin network. This may // error with ErrDuplicateNet if the network is already registered (either // due to a previous Register call, or the network being one of the default diff --git a/vendor/github.com/btcsuite/btcd/txscript/data/LICENSE b/vendor/github.com/btcsuite/btcd/txscript/data/LICENSE new file mode 100644 index 00000000000..30d808c5884 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/txscript/data/LICENSE @@ -0,0 +1,8 @@ +The json files in this directory come from the bitcoind project +(https://github.com/bitcoin/bitcoin) and is released under the following +license: + + Copyright (c) 2012-2014 The Bitcoin Core developers + Distributed under the MIT/X11 software license, see the accompanying + file COPYING or http://www.opensource.org/licenses/mit-license.php. + diff --git a/vendor/github.com/btcsuite/btcd/wire/blockheader.go b/vendor/github.com/btcsuite/btcd/wire/blockheader.go index cc0e63c0f72..c2c0ae0333e 100644 --- a/vendor/github.com/btcsuite/btcd/wire/blockheader.go +++ b/vendor/github.com/btcsuite/btcd/wire/blockheader.go @@ -12,9 +12,6 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) -// BlockVersion is the current latest supported block version. -const BlockVersion = 4 - // MaxBlockHeaderPayload is the maximum number of bytes a block header can be. // Version 4 bytes + Timestamp 4 bytes + Bits 4 bytes + Nonce 4 bytes + // PrevBlock and MerkleRoot hashes. @@ -53,8 +50,8 @@ func (h *BlockHeader) BlockHash() chainhash.Hash { // transactions. Ignore the error returns since there is no way the // encode could fail except being out of memory which would cause a // run-time panic. - var buf bytes.Buffer - _ = writeBlockHeader(&buf, 0, h) + buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload)) + _ = writeBlockHeader(buf, 0, h) return chainhash.DoubleHashH(buf.Bytes()) } @@ -95,16 +92,16 @@ func (h *BlockHeader) Serialize(w io.Writer) error { return writeBlockHeader(w, 0, h) } -// NewBlockHeader returns a new BlockHeader using the provided previous block -// hash, merkle root hash, difficulty bits, and nonce used to generate the +// NewBlockHeader returns a new BlockHeader using the provided version, previous +// block hash, merkle root hash, difficulty bits, and nonce used to generate the // block with defaults for the remaining fields. -func NewBlockHeader(prevHash *chainhash.Hash, merkleRootHash *chainhash.Hash, +func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash, bits uint32, nonce uint32) *BlockHeader { // Limit the timestamp to one second precision since the protocol // doesn't support better. return &BlockHeader{ - Version: BlockVersion, + Version: version, PrevBlock: *prevHash, MerkleRoot: *merkleRootHash, Timestamp: time.Unix(time.Now().Unix(), 0), @@ -117,13 +114,8 @@ func NewBlockHeader(prevHash *chainhash.Hash, merkleRootHash *chainhash.Hash, // decoding block headers stored to disk, such as in a database, as opposed to // decoding from the wire. func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error { - err := readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, + return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce) - if err != nil { - return err - } - - return nil } // writeBlockHeader writes a bitcoin block header to w. See Serialize for @@ -131,11 +123,6 @@ func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error { // opposed to encoding for the wire. func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error { sec := uint32(bh.Timestamp.Unix()) - err := writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot, + return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot, sec, bh.Bits, bh.Nonce) - if err != nil { - return err - } - - return nil } diff --git a/vendor/github.com/btcsuite/btcd/wire/common.go b/vendor/github.com/btcsuite/btcd/wire/common.go index 4b980a7f935..85c9df83c76 100644 --- a/vendor/github.com/btcsuite/btcd/wire/common.go +++ b/vendor/github.com/btcsuite/btcd/wire/common.go @@ -378,7 +378,7 @@ func writeElement(w io.Writer, element interface{}) error { case bool: var err error - if e == true { + if e { err = binarySerializer.PutUint8(w, 0x01) } else { err = binarySerializer.PutUint8(w, 0x00) @@ -624,10 +624,7 @@ func WriteVarString(w io.Writer, pver uint32, str string) error { return err } _, err = w.Write([]byte(str)) - if err != nil { - return err - } - return nil + return err } // ReadVarBytes reads a variable length byte array. A byte array is encoded @@ -672,10 +669,7 @@ func WriteVarBytes(w io.Writer, pver uint32, bytes []byte) error { } _, err = w.Write(bytes) - if err != nil { - return err - } - return nil + return err } // randomUint64 returns a cryptographically random uint64 value. This diff --git a/vendor/github.com/btcsuite/btcd/wire/doc.go b/vendor/github.com/btcsuite/btcd/wire/doc.go index c10373ee1ed..b8b8c56fff4 100644 --- a/vendor/github.com/btcsuite/btcd/wire/doc.go +++ b/vendor/github.com/btcsuite/btcd/wire/doc.go @@ -157,5 +157,6 @@ This package includes spec changes outlined by the following BIPs: BIP0037 (https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki) BIP0111 (https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki) BIP0130 (https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki) + BIP0133 (https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki) */ package wire diff --git a/vendor/github.com/btcsuite/btcd/wire/invvect.go b/vendor/github.com/btcsuite/btcd/wire/invvect.go index d6f04e26351..3feddcb1aca 100644 --- a/vendor/github.com/btcsuite/btcd/wire/invvect.go +++ b/vendor/github.com/btcsuite/btcd/wire/invvect.go @@ -67,18 +67,10 @@ func NewInvVect(typ InvType, hash *chainhash.Hash) *InvVect { // readInvVect reads an encoded InvVect from r depending on the protocol // version. func readInvVect(r io.Reader, pver uint32, iv *InvVect) error { - err := readElements(r, &iv.Type, &iv.Hash) - if err != nil { - return err - } - return nil + return readElements(r, &iv.Type, &iv.Hash) } // writeInvVect serializes an InvVect to w depending on the protocol version. func writeInvVect(w io.Writer, pver uint32, iv *InvVect) error { - err := writeElements(w, iv.Type, &iv.Hash) - if err != nil { - return err - } - return nil + return writeElements(w, iv.Type, &iv.Hash) } diff --git a/vendor/github.com/btcsuite/btcd/wire/message.go b/vendor/github.com/btcsuite/btcd/wire/message.go index 9cded98c5c2..c2edcdac4cf 100644 --- a/vendor/github.com/btcsuite/btcd/wire/message.go +++ b/vendor/github.com/btcsuite/btcd/wire/message.go @@ -50,6 +50,7 @@ const ( CmdMerkleBlock = "merkleblock" CmdReject = "reject" CmdSendHeaders = "sendheaders" + CmdFeeFilter = "feefilter" ) // Message is an interface that describes a bitcoin message. A type that @@ -134,6 +135,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdSendHeaders: msg = &MsgSendHeaders{} + case CmdFeeFilter: + msg = &MsgFeeFilter{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } @@ -257,11 +261,7 @@ func WriteMessageN(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) (in // Write payload. n, err = w.Write(payload) totalBytes += n - if err != nil { - return totalBytes, err - } - - return totalBytes, nil + return totalBytes, err } // WriteMessage writes a bitcoin Message to w including the necessary header diff --git a/vendor/github.com/btcsuite/btcd/wire/msgalert.go b/vendor/github.com/btcsuite/btcd/wire/msgalert.go index 23be105f6f6..8bddae19f73 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgalert.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgalert.go @@ -165,7 +165,7 @@ func (alert *Alert) Serialize(w io.Writer, pver uint32) error { if err != nil { return err } - for i := 0; i < int(count); i++ { + for i := 0; i < count; i++ { err = writeElement(w, alert.SetCancel[i]) if err != nil { return err @@ -187,7 +187,7 @@ func (alert *Alert) Serialize(w io.Writer, pver uint32) error { if err != nil { return err } - for i := 0; i < int(count); i++ { + for i := 0; i < count; i++ { err = WriteVarString(w, pver, alert.SetSubVer[i]) if err != nil { return err @@ -206,11 +206,7 @@ func (alert *Alert) Serialize(w io.Writer, pver uint32) error { if err != nil { return err } - err = WriteVarString(w, pver, alert.Reserved) - if err != nil { - return err - } - return nil + return WriteVarString(w, pver, alert.Reserved) } // Deserialize decodes from r into the receiver using the alert protocol @@ -279,10 +275,7 @@ func (alert *Alert) Deserialize(r io.Reader, pver uint32) error { return err } alert.Reserved, err = ReadVarString(r, pver) - if err != nil { - return err - } - return nil + return err } // NewAlert returns an new Alert with values provided. @@ -356,11 +349,7 @@ func (msg *MsgAlert) BtcDecode(r io.Reader, pver uint32) error { msg.Signature, err = ReadVarBytes(r, pver, MaxMessagePayload, "alert signature") - if err != nil { - return err - } - - return nil + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -390,11 +379,7 @@ func (msg *MsgAlert) BtcEncode(w io.Writer, pver uint32) error { if err != nil { return err } - err = WriteVarBytes(w, pver, msg.Signature) - if err != nil { - return err - } - return nil + return WriteVarBytes(w, pver, msg.Signature) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msgfeefilter.go b/vendor/github.com/btcsuite/btcd/wire/msgfeefilter.go new file mode 100644 index 00000000000..0162f8387e4 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/wire/msgfeefilter.go @@ -0,0 +1,64 @@ +// Copyright (c) 2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "io" +) + +// MsgFeeFilter implements the Message interface and represents a bitcoin +// feefilter message. It is used to request the receiving peer does not +// announce any transactions below the specified minimum fee rate. +// +// This message was not added until protocol versions starting with +// FeeFilterVersion. +type MsgFeeFilter struct { + MinFee int64 +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgFeeFilter) BtcDecode(r io.Reader, pver uint32) error { + if pver < FeeFilterVersion { + str := fmt.Sprintf("feefilter message invalid for protocol "+ + "version %d", pver) + return messageError("MsgFeeFilter.BtcDecode", str) + } + + return readElement(r, &msg.MinFee) +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgFeeFilter) BtcEncode(w io.Writer, pver uint32) error { + if pver < FeeFilterVersion { + str := fmt.Sprintf("feefilter message invalid for protocol "+ + "version %d", pver) + return messageError("MsgFeeFilter.BtcEncode", str) + } + + return writeElement(w, msg.MinFee) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgFeeFilter) Command() string { + return CmdFeeFilter +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgFeeFilter) MaxPayloadLength(pver uint32) uint32 { + return 8 +} + +// NewMsgFeeFilter returns a new bitcoin feefilter message that conforms to +// the Message interface. See MsgFeeFilter for details. +func NewMsgFeeFilter(minfee int64) *MsgFeeFilter { + return &MsgFeeFilter{ + MinFee: minfee, + } +} diff --git a/vendor/github.com/btcsuite/btcd/wire/msgfilteradd.go b/vendor/github.com/btcsuite/btcd/wire/msgfilteradd.go index 244ae4d09cf..b9e8a8697d5 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgfilteradd.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgfilteradd.go @@ -37,11 +37,7 @@ func (msg *MsgFilterAdd) BtcDecode(r io.Reader, pver uint32) error { var err error msg.Data, err = ReadVarBytes(r, pver, MaxFilterAddDataSize, "filteradd data") - if err != nil { - return err - } - - return nil + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -60,12 +56,7 @@ func (msg *MsgFilterAdd) BtcEncode(w io.Writer, pver uint32) error { return messageError("MsgFilterAdd.BtcEncode", str) } - err := WriteVarBytes(w, pver, msg.Data) - if err != nil { - return err - } - - return nil + return WriteVarBytes(w, pver, msg.Data) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msgfilterload.go b/vendor/github.com/btcsuite/btcd/wire/msgfilterload.go index b8bdd147c02..80374194ffe 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgfilterload.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgfilterload.go @@ -106,12 +106,7 @@ func (msg *MsgFilterLoad) BtcEncode(w io.Writer, pver uint32) error { return err } - err = writeElements(w, msg.HashFuncs, msg.Tweak, msg.Flags) - if err != nil { - return err - } - - return nil + return writeElements(w, msg.HashFuncs, msg.Tweak, msg.Flags) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msggetblocks.go b/vendor/github.com/btcsuite/btcd/wire/msggetblocks.go index ffc4c2e6b2d..8201ff41a65 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msggetblocks.go +++ b/vendor/github.com/btcsuite/btcd/wire/msggetblocks.go @@ -80,12 +80,7 @@ func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32) error { msg.AddBlockLocatorHash(hash) } - err = readElement(r, &msg.HashStop) - if err != nil { - return err - } - - return nil + return readElement(r, &msg.HashStop) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -115,12 +110,7 @@ func (msg *MsgGetBlocks) BtcEncode(w io.Writer, pver uint32) error { } } - err = writeElement(w, &msg.HashStop) - if err != nil { - return err - } - - return nil + return writeElement(w, &msg.HashStop) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msggetheaders.go b/vendor/github.com/btcsuite/btcd/wire/msggetheaders.go index 46932de5948..00755f3c81c 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msggetheaders.go +++ b/vendor/github.com/btcsuite/btcd/wire/msggetheaders.go @@ -77,12 +77,7 @@ func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32) error { msg.AddBlockLocatorHash(hash) } - err = readElement(r, &msg.HashStop) - if err != nil { - return err - } - - return nil + return readElement(r, &msg.HashStop) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -113,12 +108,7 @@ func (msg *MsgGetHeaders) BtcEncode(w io.Writer, pver uint32) error { } } - err = writeElement(w, &msg.HashStop) - if err != nil { - return err - } - - return nil + return writeElement(w, &msg.HashStop) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msgmerkleblock.go b/vendor/github.com/btcsuite/btcd/wire/msgmerkleblock.go index 3cec9935e1d..747070281c9 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgmerkleblock.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgmerkleblock.go @@ -85,11 +85,7 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32) error { msg.Flags, err = ReadVarBytes(r, pver, maxFlagsPerMerkleBlock, "merkle block flags size") - if err != nil { - return err - } - - return nil + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -136,12 +132,7 @@ func (msg *MsgMerkleBlock) BtcEncode(w io.Writer, pver uint32) error { } } - err = WriteVarBytes(w, pver, msg.Flags) - if err != nil { - return err - } - - return nil + return WriteVarBytes(w, pver, msg.Flags) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msgpong.go b/vendor/github.com/btcsuite/btcd/wire/msgpong.go index 4c89acc8335..9fd02721fa3 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgpong.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgpong.go @@ -31,12 +31,7 @@ func (msg *MsgPong) BtcDecode(r io.Reader, pver uint32) error { return messageError("MsgPong.BtcDecode", str) } - err := readElement(r, &msg.Nonce) - if err != nil { - return err - } - - return nil + return readElement(r, &msg.Nonce) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -50,12 +45,7 @@ func (msg *MsgPong) BtcEncode(w io.Writer, pver uint32) error { return messageError("MsgPong.BtcEncode", str) } - err := writeElement(w, msg.Nonce) - if err != nil { - return err - } - - return nil + return writeElement(w, msg.Nonce) } // Command returns the protocol command string for the message. This is part diff --git a/vendor/github.com/btcsuite/btcd/wire/msgtx.go b/vendor/github.com/btcsuite/btcd/wire/msgtx.go index 85d234ddb27..899cf6a5a93 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgtx.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgtx.go @@ -24,14 +24,33 @@ const ( // MaxPrevOutIndex is the maximum index the index field of a previous // outpoint can be. MaxPrevOutIndex uint32 = 0xffffffff -) -const ( - // defaultTxInOutAlloc is the default size used for the backing array - // for transaction inputs and outputs. The array will dynamically grow - // as needed, but this figure is intended to provide enough space for - // the number of inputs and outputs in a typical transaction without - // needing to grow the backing array multiple times. + // SequenceLockTimeDisabled is a flag that if set on a transaction + // input's sequence number, the sequence number will not be interpreted + // as a relative locktime. + SequenceLockTimeDisabled = 1 << 31 + + // SequenceLockTimeIsSeconds is a flag that if set on a transaction + // input's sequence number, the relative locktime has units of 512 + // seconds. + SequenceLockTimeIsSeconds = 1 << 22 + + // SequenceLockTimeMask is a mask that extracts the relative locktime + // when masked against the transaction input sequence number. + SequenceLockTimeMask = 0x0000ffff + + // SequenceLockTimeGranularity is the defined time based granularity + // for seconds-based relative time locks. When converting from seconds + // to a sequence number, the value is right shifted by this amount, + // therefore the granularity of relative time locks in 512 or 2^9 + // seconds. Enforced relative lock times are multiples of 512 seconds. + SequenceLockTimeGranularity = 9 + + // defaultTxInOutAlloc is the default size used for the backing array for + // transaction inputs and outputs. The array will dynamically grow as needed, + // but this figure is intended to provide enough space for the number of + // inputs and outputs in a typical transaction without needing to grow the + // backing array multiple times. defaultTxInOutAlloc = 15 // minTxInPayload is the minimum payload size for a transaction input. @@ -518,12 +537,7 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { } } - err = binarySerializer.PutUint32(w, littleEndian, msg.LockTime) - if err != nil { - return err - } - - return nil + return binarySerializer.PutUint32(w, littleEndian, msg.LockTime) } // Serialize encodes the transaction to w using a format that suitable for @@ -617,9 +631,9 @@ func (msg *MsgTx) PkScriptLocs() []int { // are no transaction inputs or outputs. Also, the lock time is set to zero // to indicate the transaction is valid immediately as opposed to some time in // future. -func NewMsgTx() *MsgTx { +func NewMsgTx(version int32) *MsgTx { return &MsgTx{ - Version: TxVersion, + Version: version, TxIn: make([]*TxIn, 0, defaultTxInOutAlloc), TxOut: make([]*TxOut, 0, defaultTxInOutAlloc), } @@ -633,11 +647,7 @@ func readOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { } op.Index, err = binarySerializer.Uint32(r, littleEndian) - if err != nil { - return err - } - - return nil + return err } // writeOutPoint encodes op to the bitcoin protocol encoding for an OutPoint @@ -648,11 +658,7 @@ func writeOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error return err } - err = binarySerializer.PutUint32(w, littleEndian, op.Index) - if err != nil { - return err - } - return nil + return binarySerializer.PutUint32(w, littleEndian, op.Index) } // readScript reads a variable length byte array that represents a transaction @@ -700,12 +706,7 @@ func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { return err } - err = readElement(r, &ti.Sequence) - if err != nil { - return err - } - - return nil + return readElement(r, &ti.Sequence) } // writeTxIn encodes ti to the bitcoin protocol encoding for a transaction @@ -721,12 +722,7 @@ func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { return err } - err = binarySerializer.PutUint32(w, littleEndian, ti.Sequence) - if err != nil { - return err - } - - return nil + return binarySerializer.PutUint32(w, littleEndian, ti.Sequence) } // readTxOut reads the next sequence of bytes from r as a transaction output @@ -739,11 +735,7 @@ func readTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { to.PkScript, err = readScript(r, pver, MaxMessagePayload, "transaction output public key script") - if err != nil { - return err - } - - return nil + return err } // writeTxOut encodes to into the bitcoin protocol encoding for a transaction @@ -754,9 +746,5 @@ func writeTxOut(w io.Writer, pver uint32, version int32, to *TxOut) error { return err } - err = WriteVarBytes(w, pver, to.PkScript) - if err != nil { - return err - } - return nil + return WriteVarBytes(w, pver, to.PkScript) } diff --git a/vendor/github.com/btcsuite/btcd/wire/msgversion.go b/vendor/github.com/btcsuite/btcd/wire/msgversion.go index b8e96d253d4..d6a3061f4f1 100644 --- a/vendor/github.com/btcsuite/btcd/wire/msgversion.go +++ b/vendor/github.com/btcsuite/btcd/wire/msgversion.go @@ -8,17 +8,16 @@ import ( "bytes" "fmt" "io" - "net" "strings" "time" ) // MaxUserAgentLen is the maximum allowed length for the user agent field in a // version message (MsgVersion). -const MaxUserAgentLen = 2000 +const MaxUserAgentLen = 256 // DefaultUserAgent for wire in the stack -const DefaultUserAgent = "/btcwire:0.4.0/" +const DefaultUserAgent = "/btcwire:0.5.0/" // MsgVersion implements the Message interface and represents a bitcoin version // message. It is used for a peer to advertise itself as soon as an outbound @@ -239,27 +238,6 @@ func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64, } } -// NewMsgVersionFromConn is a convenience function that extracts the remote -// and local address from conn and returns a new bitcoin version message that -// conforms to the Message interface. See NewMsgVersion. -func NewMsgVersionFromConn(conn net.Conn, nonce uint64, - lastBlock int32) (*MsgVersion, error) { - - // Don't assume any services until we know otherwise. - lna, err := NewNetAddress(conn.LocalAddr(), 0) - if err != nil { - return nil, err - } - - // Don't assume any services until we know otherwise. - rna, err := NewNetAddress(conn.RemoteAddr(), 0) - if err != nil { - return nil, err - } - - return NewMsgVersion(lna, rna, nonce, lastBlock), nil -} - // validateUserAgent checks userAgent length against MaxUserAgentLen func validateUserAgent(userAgent string) error { if len(userAgent) > MaxUserAgentLen { diff --git a/vendor/github.com/btcsuite/btcd/wire/netaddress.go b/vendor/github.com/btcsuite/btcd/wire/netaddress.go index 6c3e65a1abb..5a2610bccc4 100644 --- a/vendor/github.com/btcsuite/btcd/wire/netaddress.go +++ b/vendor/github.com/btcsuite/btcd/wire/netaddress.go @@ -6,16 +6,11 @@ package wire import ( "encoding/binary" - "errors" "io" "net" "time" ) -// ErrInvalidNetAddr describes an error that indicates the caller didn't specify -// a TCP address as required. -var ErrInvalidNetAddr = errors.New("provided net.Addr is not a net.TCPAddr") - // maxNetAddressPayload returns the max payload size for a bitcoin NetAddress // based on the protocol version. func maxNetAddressPayload(pver uint32) uint32 { @@ -53,10 +48,7 @@ type NetAddress struct { // HasService returns whether the specified service is supported by the address. func (na *NetAddress) HasService(service ServiceFlag) bool { - if na.Services&service == service { - return true - } - return false + return na.Services&service == service } // AddService adds service as a supported service by the peer generating the @@ -65,20 +57,21 @@ func (na *NetAddress) AddService(service ServiceFlag) { na.Services |= service } -// SetAddress is a convenience function to set the IP address and port in one -// call. -func (na *NetAddress) SetAddress(ip net.IP, port uint16) { - na.IP = ip - na.Port = port -} - // NewNetAddressIPPort returns a new NetAddress using the provided IP, port, and // supported services with defaults for the remaining fields. func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddress { + return NewNetAddressTimestamp(time.Now(), services, ip, port) +} + +// NewNetAddressTimestamp returns a new NetAddress using the provided +// timestamp, IP, port, and supported services. The timestamp is rounded to +// single second precision. +func NewNetAddressTimestamp( + timestamp time.Time, services ServiceFlag, ip net.IP, port uint16) *NetAddress { // Limit the timestamp to one second precision since the protocol // doesn't support better. na := NetAddress{ - Timestamp: time.Unix(time.Now().Unix(), 0), + Timestamp: time.Unix(timestamp.Unix(), 0), Services: services, IP: ip, Port: port, @@ -88,24 +81,14 @@ func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddre // NewNetAddress returns a new NetAddress using the provided TCP address and // supported services with defaults for the remaining fields. -// -// Note that addr must be a net.TCPAddr. An ErrInvalidNetAddr is returned -// if it is not. -func NewNetAddress(addr net.Addr, services ServiceFlag) (*NetAddress, error) { - tcpAddr, ok := addr.(*net.TCPAddr) - if !ok { - return nil, ErrInvalidNetAddr - } - - na := NewNetAddressIPPort(tcpAddr.IP, uint16(tcpAddr.Port), services) - return na, nil +func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress { + return NewNetAddressIPPort(addr.IP, uint16(addr.Port), services) } // readNetAddress reads an encoded NetAddress from r depending on the protocol // version and whether or not the timestamp is included per ts. Some messages // like version do not include the timestamp. func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { - var services ServiceFlag var ip [16]byte // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will @@ -118,7 +101,7 @@ func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { } } - err := readElements(r, &services, &ip) + err := readElements(r, &na.Services, &ip) if err != nil { return err } @@ -128,8 +111,12 @@ func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { return err } - na.Services = services - na.SetAddress(net.IP(ip[:]), port) + *na = NetAddress{ + Timestamp: na.Timestamp, + Services: na.Services, + IP: net.IP(ip[:]), + Port: port, + } return nil } @@ -158,10 +145,5 @@ func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error { } // Sigh. Bitcoin protocol mixes little and big endian. - err = binary.Write(w, bigEndian, na.Port) - if err != nil { - return err - } - - return nil + return binary.Write(w, bigEndian, na.Port) } diff --git a/vendor/github.com/btcsuite/btcd/wire/protocol.go b/vendor/github.com/btcsuite/btcd/wire/protocol.go index ba2c209fbe4..d73850dc1bd 100644 --- a/vendor/github.com/btcsuite/btcd/wire/protocol.go +++ b/vendor/github.com/btcsuite/btcd/wire/protocol.go @@ -12,7 +12,7 @@ import ( const ( // ProtocolVersion is the latest protocol version this package supports. - ProtocolVersion uint32 = 70012 + ProtocolVersion uint32 = 70013 // MultipleAddressVersion is the protocol version which added multiple // addresses per message (pver >= MultipleAddressVersion). @@ -35,6 +35,10 @@ const ( // with a relay flag (pver >= BIP0037Version). BIP0037Version uint32 = 70001 + // RejectVersion is the protocol version which added a new reject + // message. + RejectVersion uint32 = 70002 + // BIP0111Version is the protocol version which added the SFNodeBloom // service flag. BIP0111Version uint32 = 70011 @@ -43,9 +47,9 @@ const ( // sendheaders message. SendHeadersVersion uint32 = 70012 - // RejectVersion is the protocol version which added a new reject - // message. - RejectVersion uint32 = 70002 + // FeeFilterVersion is the protocol version which added a new + // feefilter message. + FeeFilterVersion uint32 = 70013 ) // ServiceFlag identifies services supported by a bitcoin peer. diff --git a/vendor/github.com/btcsuite/btcutil/.gitignore b/vendor/github.com/btcsuite/btcutil/.gitignore new file mode 100644 index 00000000000..5b97dbba798 --- /dev/null +++ b/vendor/github.com/btcsuite/btcutil/.gitignore @@ -0,0 +1,28 @@ +# Temp files +*~ + +# Log files +*.log + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/btcsuite/btcutil/.travis.yml b/vendor/github.com/btcsuite/btcutil/.travis.yml new file mode 100644 index 00000000000..3d5ab83d15e --- /dev/null +++ b/vendor/github.com/btcsuite/btcutil/.travis.yml @@ -0,0 +1,15 @@ +language: go +go: + - 1.7.x + - 1.8.x +sudo: false +install: + - go get -d -t -v ./... + - go get -v github.com/alecthomas/gometalinter + - gometalinter --install +script: + - export PATH=$PATH:$HOME/gopath/bin + - ./goclean.sh +after_success: + - go get -v github.com/mattn/goveralls + - goveralls -coverprofile=profile.cov -service=travis-ci diff --git a/vendor/github.com/btcsuite/btcutil/LICENSE b/vendor/github.com/btcsuite/btcutil/LICENSE index 16cf02558a4..49de919577d 100644 --- a/vendor/github.com/btcsuite/btcutil/LICENSE +++ b/vendor/github.com/btcsuite/btcutil/LICENSE @@ -1,6 +1,6 @@ ISC License -Copyright (c) 2013 Conformal Systems LLC. +Copyright (c) 2013-2016 The btcsuite developers Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/btcsuite/btcutil/address.go b/vendor/github.com/btcsuite/btcutil/address.go index ed6c724beb0..d0a2e3dd094 100644 --- a/vendor/github.com/btcsuite/btcutil/address.go +++ b/vendor/github.com/btcsuite/btcutil/address.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013, 2014 The btcsuite developers +// Copyright (c) 2013-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil/base58" - "github.com/btcsuite/golangcrypto/ripemd160" + "golang.org/x/crypto/ripemd160" ) var ( diff --git a/vendor/github.com/btcsuite/btcutil/appdata.go b/vendor/github.com/btcsuite/btcutil/appdata.go index 766fd10b492..e36cf7c4a45 100644 --- a/vendor/github.com/btcsuite/btcutil/appdata.go +++ b/vendor/github.com/btcsuite/btcutil/appdata.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2014 The btcsuite developers +// Copyright (c) 2013-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -24,10 +24,8 @@ func appDataDir(goos, appName string, roaming bool) string { } // The caller really shouldn't prepend the appName with a period, but - // if they do, handle it gracefully by stripping it. - if strings.HasPrefix(appName, ".") { - appName = appName[1:] - } + // if they do, handle it gracefully by trimming it. + appName = strings.TrimPrefix(appName, ".") appNameUpper := string(unicode.ToUpper(rune(appName[0]))) + appName[1:] appNameLower := string(unicode.ToLower(rune(appName[0]))) + appName[1:] diff --git a/vendor/github.com/btcsuite/btcutil/base58/base58.go b/vendor/github.com/btcsuite/btcutil/base58/base58.go index bb940e3823e..19a72de2c4f 100644 --- a/vendor/github.com/btcsuite/btcutil/base58/base58.go +++ b/vendor/github.com/btcsuite/btcutil/base58/base58.go @@ -39,7 +39,7 @@ func Decode(b string) []byte { } } flen := numZeros + len(tmpval) - val := make([]byte, flen, flen) + val := make([]byte, flen) copy(val[numZeros:], tmpval) return val diff --git a/vendor/github.com/btcsuite/btcutil/block.go b/vendor/github.com/btcsuite/btcutil/block.go index 0eb78ece5a8..5d06c4a4367 100644 --- a/vendor/github.com/btcsuite/btcutil/block.go +++ b/vendor/github.com/btcsuite/btcutil/block.go @@ -56,8 +56,8 @@ func (b *Block) Bytes() ([]byte, error) { } // Serialize the MsgBlock. - var w bytes.Buffer - err := b.msgBlock.Serialize(&w) + w := bytes.NewBuffer(make([]byte, 0, b.msgBlock.SerializeSize())) + err := b.msgBlock.Serialize(w) if err != nil { return nil, err } diff --git a/vendor/github.com/btcsuite/btcutil/goclean.sh b/vendor/github.com/btcsuite/btcutil/goclean.sh index 91833320ad1..41308485e57 100755 --- a/vendor/github.com/btcsuite/btcutil/goclean.sh +++ b/vendor/github.com/btcsuite/btcutil/goclean.sh @@ -4,16 +4,26 @@ # 2. goimports (https://github.com/bradfitz/goimports) # 3. golint (https://github.com/golang/lint) # 4. go vet (http://golang.org/cmd/vet) -# 5. test coverage (http://blog.golang.org/cover) +# 5. gosimple (https://github.com/dominikh/go-simple) +# 6. unconvert (https://github.com/mdempsky/unconvert) +# 7. race detector (http://blog.golang.org/race-detector) +# 8. test coverage (http://blog.golang.org/cover) +# +# gometalint (github.com/alecthomas/gometalinter) is used to run each each +# static checker. -set -e +set -ex # Automatic checks -test -z "$(gofmt -l -w . | tee /dev/stderr)" -test -z "$(goimports -l -w . | tee /dev/stderr)" -test -z "$(golint . | tee /dev/stderr)" -go vet ./... -env GORACE="halt_on_error=1" go test -v -race ./... +test -z "$(gometalinter --disable-all \ +--enable=gofmt \ +--enable=goimports \ +--enable=golint \ +--enable=vet \ +--enable=gosimple \ +--enable=unconvert \ +--deadline=120s ./... | grep -v 'ExampleNew' 2>&1 | tee /dev/stderr)" +env GORACE="halt_on_error=1" go test -race ./... # Run test coverage on each subdirectories and merge the coverage profile. diff --git a/vendor/github.com/btcsuite/btcutil/hash160.go b/vendor/github.com/btcsuite/btcutil/hash160.go index bc788418b2d..599a0fe5371 100644 --- a/vendor/github.com/btcsuite/btcutil/hash160.go +++ b/vendor/github.com/btcsuite/btcutil/hash160.go @@ -1,14 +1,14 @@ -// Copyright (c) 2013-2014 The btcsuite developers +// Copyright (c) 2013-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package btcutil import ( + "crypto/sha256" "hash" - "github.com/btcsuite/fastsha256" - "github.com/btcsuite/golangcrypto/ripemd160" + "golang.org/x/crypto/ripemd160" ) // Calculate the hash of hasher over buf. @@ -19,5 +19,5 @@ func calcHash(buf []byte, hasher hash.Hash) []byte { // Hash160 calculates the hash ripemd160(sha256(b)). func Hash160(buf []byte) []byte { - return calcHash(calcHash(buf, fastsha256.New()), ripemd160.New()) + return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) } diff --git a/vendor/github.com/btcsuite/btcutil/hdkeychain/README.md b/vendor/github.com/btcsuite/btcutil/hdkeychain/README.md deleted file mode 100644 index 842a2386681..00000000000 --- a/vendor/github.com/btcsuite/btcutil/hdkeychain/README.md +++ /dev/null @@ -1,64 +0,0 @@ -hdkeychain -========== - -[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)] -(https://travis-ci.org/btcsuite/btcutil) [![ISC License] -(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)] -(http://godoc.org/github.com/btcsuite/btcutil/hdkeychain) - -Package hdkeychain provides an API for bitcoin hierarchical deterministic -extended keys (BIP0032). - -A comprehensive suite of tests is provided to ensure proper functionality. See -`test_coverage.txt` for the gocov coverage report. Alternatively, if you are -running a POSIX OS, you can run the `cov_report.sh` script for a real-time -report. - -## Feature Overview - -- Full BIP0032 implementation -- Single type for private and public extended keys -- Convenient cryptograpically secure seed generation -- Simple creation of master nodes -- Support for multi-layer derivation -- Easy serialization and deserialization for both private and public extended - keys -- Support for custom networks by registering them with chaincfg -- Obtaining the underlying EC pubkeys, EC privkeys, and associated bitcoin - addresses ties in seamlessly with existing btcec and btcutil types which - provide powerful tools for working with them to do things like sign - transations and generate payment scripts -- Uses the btcec package which is highly optimized for secp256k1 -- Code examples including: - - Generating a cryptographically secure random seed and deriving a - master node from it - - Default HD wallet layout as described by BIP0032 - - Audits use case as described by BIP0032 -- Comprehensive test coverage including the BIP0032 test vectors -- Benchmarks - -## Installation and Updating - -```bash -$ go get -u github.com/btcsuite/btcutil/hdkeychain -``` - -## Examples - -* [NewMaster Example] - (http://godoc.org/github.com/btcsuite/btcutil/hdkeychain#example-NewMaster) - Demonstrates how to generate a cryptographically random seed then use it to - create a new master node (extended key). -* [Default Wallet Layout Example] - (http://godoc.org/github.com/btcsuite/btcutil/hdkeychain#example-package--DefaultWalletLayout) - Demonstrates the default hierarchical deterministic wallet layout as described - in BIP0032. -* [Audits Use Case Example] - (http://godoc.org/github.com/btcsuite/btcutil/hdkeychain#example-package--Audits) - Demonstrates the audits use case in BIP0032. - -## License - -Package hdkeychain is licensed under the [copyfree](http://copyfree.org) ISC -License. diff --git a/vendor/github.com/btcsuite/btcutil/hdkeychain/cov_report.sh b/vendor/github.com/btcsuite/btcutil/hdkeychain/cov_report.sh deleted file mode 100644 index 307f05b76ca..00000000000 --- a/vendor/github.com/btcsuite/btcutil/hdkeychain/cov_report.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# This script uses gocov to generate a test coverage report. -# The gocov tool my be obtained with the following command: -# go get github.com/axw/gocov/gocov -# -# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. - -# Check for gocov. -type gocov >/dev/null 2>&1 -if [ $? -ne 0 ]; then - echo >&2 "This script requires the gocov tool." - echo >&2 "You may obtain it with the following command:" - echo >&2 "go get github.com/axw/gocov/gocov" - exit 1 -fi -gocov test | gocov report diff --git a/vendor/github.com/btcsuite/btcutil/hdkeychain/doc.go b/vendor/github.com/btcsuite/btcutil/hdkeychain/doc.go deleted file mode 100644 index 652eb8ca05e..00000000000 --- a/vendor/github.com/btcsuite/btcutil/hdkeychain/doc.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2014 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -/* -Package hdkeychain provides an API for bitcoin hierarchical deterministic -extended keys (BIP0032). - -Overview - -The ability to implement hierarchical deterministic wallets depends on the -ability to create and derive hierarchical deterministic extended keys. - -At a high level, this package provides support for those hierarchical -deterministic extended keys by providing an ExtendedKey type and supporting -functions. Each extended key can either be a private or public extended key -which itself is capable of deriving a child extended key. - -Determining the Extended Key Type - -Whether an extended key is a private or public extended key can be determined -with the IsPrivate function. - -Transaction Signing Keys and Payment Addresses - -In order to create and sign transactions, or provide others with addresses to -send funds to, the underlying key and address material must be accessible. This -package provides the ECPubKey, ECPrivKey, and Address functions for this -purpose. - -The Master Node - -As previously mentioned, the extended keys are hierarchical meaning they are -used to form a tree. The root of that tree is called the master node and this -package provides the NewMaster function to create it from a cryptographically -random seed. The GenerateSeed function is provided as a convenient way to -create a random seed for use with the NewMaster function. - -Deriving Children - -Once you have created a tree root (or have deserialized an extended key as -discussed later), the child extended keys can be derived by using the Child -function. The Child function supports deriving both normal (non-hardened) and -hardened child extended keys. In order to derive a hardened extended key, use -the HardenedKeyStart constant + the hardened key number as the index to the -Child function. This provides the ability to cascade the keys into a tree and -hence generate the hierarchical deterministic key chains. - -Normal vs Hardened Child Extended Keys - -A private extended key can be used to derive both hardened and non-hardened -(normal) child private and public extended keys. A public extended key can only -be used to derive non-hardened child public extended keys. As enumerated in -BIP0032 "knowledge of the extended public key plus any non-hardened private key -descending from it is equivalent to knowing the extended private key (and thus -every private and public key descending from it). This means that extended -public keys must be treated more carefully than regular public keys. It is also -the reason for the existence of hardened keys, and why they are used for the -account level in the tree. This way, a leak of an account-specific (or below) -private key never risks compromising the master or other accounts." - -Neutering a Private Extended Key - -A private extended key can be converted to a new instance of the corresponding -public extended key with the Neuter function. The original extended key is not -modified. A public extended key is still capable of deriving non-hardened child -public extended keys. - -Serializing and Deserializing Extended Keys - -Extended keys are serialized and deserialized with the String and -NewKeyFromString functions. The serialized key is a Base58-encoded string which -looks like the following: - public key: xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw - private key: xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 - -Network - -Extended keys are much like normal Bitcoin addresses in that they have version -bytes which tie them to a specific network. The SetNet and IsForNet functions -are provided to set and determinine which network an extended key is associated -with. -*/ -package hdkeychain diff --git a/vendor/github.com/btcsuite/btcutil/hdkeychain/extendedkey.go b/vendor/github.com/btcsuite/btcutil/hdkeychain/extendedkey.go deleted file mode 100644 index 256b4cb4dcb..00000000000 --- a/vendor/github.com/btcsuite/btcutil/hdkeychain/extendedkey.go +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright (c) 2014-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package hdkeychain - -// References: -// [BIP32]: BIP0032 - Hierarchical Deterministic Wallets -// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki - -import ( - "bytes" - "crypto/hmac" - "crypto/rand" - "crypto/sha512" - "encoding/binary" - "errors" - "fmt" - "math/big" - - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/base58" -) - -const ( - // RecommendedSeedLen is the recommended length in bytes for a seed - // to a master node. - RecommendedSeedLen = 32 // 256 bits - - // HardenedKeyStart is the index at which a hardended key starts. Each - // extended key has 2^31 normal child keys and 2^31 hardned child keys. - // Thus the range for normal child keys is [0, 2^31 - 1] and the range - // for hardened child keys is [2^31, 2^32 - 1]. - HardenedKeyStart = 0x80000000 // 2^31 - - // MinSeedBytes is the minimum number of bytes allowed for a seed to - // a master node. - MinSeedBytes = 16 // 128 bits - - // MaxSeedBytes is the maximum number of bytes allowed for a seed to - // a master node. - MaxSeedBytes = 64 // 512 bits - - // serializedKeyLen is the length of a serialized public or private - // extended key. It consists of 4 bytes version, 1 byte depth, 4 bytes - // fingerprint, 4 bytes child number, 32 bytes chain code, and 33 bytes - // public/private key data. - serializedKeyLen = 4 + 1 + 4 + 4 + 32 + 33 // 78 bytes -) - -var ( - // ErrDeriveHardFromPublic describes an error in which the caller - // attempted to derive a hardened extended key from a public key. - ErrDeriveHardFromPublic = errors.New("cannot derive a hardened key " + - "from a public key") - - // ErrNotPrivExtKey describes an error in which the caller attempted - // to extract a private key from a public extended key. - ErrNotPrivExtKey = errors.New("unable to create private keys from a " + - "public extended key") - - // ErrInvalidChild describes an error in which the child at a specific - // index is invalid due to the derived key falling outside of the valid - // range for secp256k1 private keys. This error indicates the caller - // should simply ignore the invalid child extended key at this index and - // increment to the next index. - ErrInvalidChild = errors.New("the extended key at this index is invalid") - - // ErrUnusableSeed describes an error in which the provided seed is not - // usable due to the derived key falling outside of the valid range for - // secp256k1 private keys. This error indicates the caller must choose - // another seed. - ErrUnusableSeed = errors.New("unusable seed") - - // ErrInvalidSeedLen describes an error in which the provided seed or - // seed length is not in the allowed range. - ErrInvalidSeedLen = fmt.Errorf("seed length must be between %d and %d "+ - "bits", MinSeedBytes*8, MaxSeedBytes*8) - - // ErrBadChecksum describes an error in which the checksum encoded with - // a serialized extended key does not match the calculated value. - ErrBadChecksum = errors.New("bad extended key checksum") - - // ErrInvalidKeyLen describes an error in which the provided serialized - // key is not the expected length. - ErrInvalidKeyLen = errors.New("the provided serialized extended key " + - "length is invalid") -) - -// masterKey is the master key used along with a random seed used to generate -// the master node in the hierarchical tree. -var masterKey = []byte("Bitcoin seed") - -// ExtendedKey houses all the information needed to support a hierarchical -// deterministic extended key. See the package overview documentation for -// more details on how to use extended keys. -type ExtendedKey struct { - key []byte // This will be the pubkey for extended pub keys - pubKey []byte // This will only be set for extended priv keys - chainCode []byte - depth uint16 - parentFP []byte - childNum uint32 - version []byte - isPrivate bool -} - -// newExtendedKey returns a new instance of an extended key with the given -// fields. No error checking is performed here as it's only intended to be a -// convenience method used to create a populated struct. -func newExtendedKey(version, key, chainCode, parentFP []byte, depth uint16, - childNum uint32, isPrivate bool) *ExtendedKey { - - // NOTE: The pubKey field is intentionally left nil so it is only - // computed and memoized as required. - return &ExtendedKey{ - key: key, - chainCode: chainCode, - depth: depth, - parentFP: parentFP, - childNum: childNum, - version: version, - isPrivate: isPrivate, - } -} - -// pubKeyBytes returns bytes for the serialized compressed public key associated -// with this extended key in an efficient manner including memoization as -// necessary. -// -// When the extended key is already a public key, the key is simply returned as -// is since it's already in the correct form. However, when the extended key is -// a private key, the public key will be calculated and memoized so future -// accesses can simply return the cached result. -func (k *ExtendedKey) pubKeyBytes() []byte { - // Just return the key if it's already an extended public key. - if !k.isPrivate { - return k.key - } - - // This is a private extended key, so calculate and memoize the public - // key if needed. - if len(k.pubKey) == 0 { - pkx, pky := btcec.S256().ScalarBaseMult(k.key) - pubKey := btcec.PublicKey{Curve: btcec.S256(), X: pkx, Y: pky} - k.pubKey = pubKey.SerializeCompressed() - } - - return k.pubKey -} - -// IsPrivate returns whether or not the extended key is a private extended key. -// -// A private extended key can be used to derive both hardened and non-hardened -// child private and public extended keys. A public extended key can only be -// used to derive non-hardened child public extended keys. -func (k *ExtendedKey) IsPrivate() bool { - return k.isPrivate -} - -// ParentFingerprint returns a fingerprint of the parent extended key from which -// this one was derived. -func (k *ExtendedKey) ParentFingerprint() uint32 { - return binary.BigEndian.Uint32(k.parentFP) -} - -// Child returns a derived child extended key at the given index. When this -// extended key is a private extended key (as determined by the IsPrivate -// function), a private extended key will be derived. Otherwise, the derived -// extended key will be also be a public extended key. -// -// When the index is greater to or equal than the HardenedKeyStart constant, the -// derived extended key will be a hardened extended key. It is only possible to -// derive a hardended extended key from a private extended key. Consequently, -// this function will return ErrDeriveHardFromPublic if a hardened child -// extended key is requested from a public extended key. -// -// A hardened extended key is useful since, as previously mentioned, it requires -// a parent private extended key to derive. In other words, normal child -// extended public keys can be derived from a parent public extended key (no -// knowledge of the parent private key) whereas hardened extended keys may not -// be. -// -// NOTE: There is an extremely small chance (< 1 in 2^127) the specific child -// index does not derive to a usable child. The ErrInvalidChild error will be -// returned if this should occur, and the caller is expected to ignore the -// invalid child and simply increment to the next index. -func (k *ExtendedKey) Child(i uint32) (*ExtendedKey, error) { - // There are four scenarios that could happen here: - // 1) Private extended key -> Hardened child private extended key - // 2) Private extended key -> Non-hardened child private extended key - // 3) Public extended key -> Non-hardened child public extended key - // 4) Public extended key -> Hardened child public extended key (INVALID!) - - // Case #4 is invalid, so error out early. - // A hardened child extended key may not be created from a public - // extended key. - isChildHardened := i >= HardenedKeyStart - if !k.isPrivate && isChildHardened { - return nil, ErrDeriveHardFromPublic - } - - // The data used to derive the child key depends on whether or not the - // child is hardened per [BIP32]. - // - // For hardened children: - // 0x00 || ser256(parentKey) || ser32(i) - // - // For normal children: - // serP(parentPubKey) || ser32(i) - keyLen := 33 - data := make([]byte, keyLen+4) - if isChildHardened { - // Case #1. - // When the child is a hardened child, the key is known to be a - // private key due to the above early return. Pad it with a - // leading zero as required by [BIP32] for deriving the child. - copy(data[1:], k.key) - } else { - // Case #2 or #3. - // This is either a public or private extended key, but in - // either case, the data which is used to derive the child key - // starts with the secp256k1 compressed public key bytes. - copy(data, k.pubKeyBytes()) - } - binary.BigEndian.PutUint32(data[keyLen:], i) - - // Take the HMAC-SHA512 of the current key's chain code and the derived - // data: - // I = HMAC-SHA512(Key = chainCode, Data = data) - hmac512 := hmac.New(sha512.New, k.chainCode) - hmac512.Write(data) - ilr := hmac512.Sum(nil) - - // Split "I" into two 32-byte sequences Il and Ir where: - // Il = intermediate key used to derive the child - // Ir = child chain code - il := ilr[:len(ilr)/2] - childChainCode := ilr[len(ilr)/2:] - - // Both derived public or private keys rely on treating the left 32-byte - // sequence calculated above (Il) as a 256-bit integer that must be - // within the valid range for a secp256k1 private key. There is a small - // chance (< 1 in 2^127) this condition will not hold, and in that case, - // a child extended key can't be created for this index and the caller - // should simply increment to the next index. - ilNum := new(big.Int).SetBytes(il) - if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { - return nil, ErrInvalidChild - } - - // The algorithm used to derive the child key depends on whether or not - // a private or public child is being derived. - // - // For private children: - // childKey = parse256(Il) + parentKey - // - // For public children: - // childKey = serP(point(parse256(Il)) + parentKey) - var isPrivate bool - var childKey []byte - if k.isPrivate { - // Case #1 or #2. - // Add the parent private key to the intermediate private key to - // derive the final child key. - // - // childKey = parse256(Il) + parenKey - keyNum := new(big.Int).SetBytes(k.key) - ilNum.Add(ilNum, keyNum) - ilNum.Mod(ilNum, btcec.S256().N) - childKey = ilNum.Bytes() - isPrivate = true - } else { - // Case #3. - // Calculate the corresponding intermediate public key for - // intermediate private key. - ilx, ily := btcec.S256().ScalarBaseMult(il) - if ilx.Sign() == 0 || ily.Sign() == 0 { - return nil, ErrInvalidChild - } - - // Convert the serialized compressed parent public key into X - // and Y coordinates so it can be added to the intermediate - // public key. - pubKey, err := btcec.ParsePubKey(k.key, btcec.S256()) - if err != nil { - return nil, err - } - - // Add the intermediate public key to the parent public key to - // derive the final child key. - // - // childKey = serP(point(parse256(Il)) + parentKey) - childX, childY := btcec.S256().Add(ilx, ily, pubKey.X, pubKey.Y) - pk := btcec.PublicKey{Curve: btcec.S256(), X: childX, Y: childY} - childKey = pk.SerializeCompressed() - } - - // The fingerprint of the parent for the derived child is the first 4 - // bytes of the RIPEMD160(SHA256(parentPubKey)). - parentFP := btcutil.Hash160(k.pubKeyBytes())[:4] - return newExtendedKey(k.version, childKey, childChainCode, parentFP, - k.depth+1, i, isPrivate), nil -} - -// Neuter returns a new extended public key from this extended private key. The -// same extended key will be returned unaltered if it is already an extended -// public key. -// -// As the name implies, an extended public key does not have access to the -// private key, so it is not capable of signing transactions or deriving -// child extended private keys. However, it is capable of deriving further -// child extended public keys. -func (k *ExtendedKey) Neuter() (*ExtendedKey, error) { - // Already an extended public key. - if !k.isPrivate { - return k, nil - } - - // Get the associated public extended key version bytes. - version, err := chaincfg.HDPrivateKeyToPublicKeyID(k.version) - if err != nil { - return nil, err - } - - // Convert it to an extended public key. The key for the new extended - // key will simply be the pubkey of the current extended private key. - // - // This is the function N((k,c)) -> (K, c) from [BIP32]. - return newExtendedKey(version, k.pubKeyBytes(), k.chainCode, k.parentFP, - k.depth, k.childNum, false), nil -} - -// ECPubKey converts the extended key to a btcec public key and returns it. -func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error) { - return btcec.ParsePubKey(k.pubKeyBytes(), btcec.S256()) -} - -// ECPrivKey converts the extended key to a btcec private key and returns it. -// As you might imagine this is only possible if the extended key is a private -// extended key (as determined by the IsPrivate function). The ErrNotPrivExtKey -// error will be returned if this function is called on a public extended key. -func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error) { - if !k.isPrivate { - return nil, ErrNotPrivExtKey - } - - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), k.key) - return privKey, nil -} - -// Address converts the extended key to a standard bitcoin pay-to-pubkey-hash -// address for the passed network. -func (k *ExtendedKey) Address(net *chaincfg.Params) (*btcutil.AddressPubKeyHash, error) { - pkHash := btcutil.Hash160(k.pubKeyBytes()) - return btcutil.NewAddressPubKeyHash(pkHash, net) -} - -// paddedAppend appends the src byte slice to dst, returning the new slice. -// If the length of the source is smaller than the passed size, leading zero -// bytes are appended to the dst slice before appending src. -func paddedAppend(size uint, dst, src []byte) []byte { - for i := 0; i < int(size)-len(src); i++ { - dst = append(dst, 0) - } - return append(dst, src...) -} - -// String returns the extended key as a human-readable base58-encoded string. -func (k *ExtendedKey) String() string { - if len(k.key) == 0 { - return "zeroed extended key" - } - - var childNumBytes [4]byte - depthByte := byte(k.depth % 256) - binary.BigEndian.PutUint32(childNumBytes[:], k.childNum) - - // The serialized format is: - // version (4) || depth (1) || parent fingerprint (4)) || - // child num (4) || chain code (32) || key data (33) || checksum (4) - serializedBytes := make([]byte, 0, serializedKeyLen+4) - serializedBytes = append(serializedBytes, k.version...) - serializedBytes = append(serializedBytes, depthByte) - serializedBytes = append(serializedBytes, k.parentFP...) - serializedBytes = append(serializedBytes, childNumBytes[:]...) - serializedBytes = append(serializedBytes, k.chainCode...) - if k.isPrivate { - serializedBytes = append(serializedBytes, 0x00) - serializedBytes = paddedAppend(32, serializedBytes, k.key) - } else { - serializedBytes = append(serializedBytes, k.pubKeyBytes()...) - } - - checkSum := chainhash.DoubleHashB(serializedBytes)[:4] - serializedBytes = append(serializedBytes, checkSum...) - return base58.Encode(serializedBytes) -} - -// IsForNet returns whether or not the extended key is associated with the -// passed bitcoin network. -func (k *ExtendedKey) IsForNet(net *chaincfg.Params) bool { - return bytes.Equal(k.version, net.HDPrivateKeyID[:]) || - bytes.Equal(k.version, net.HDPublicKeyID[:]) -} - -// SetNet associates the extended key, and any child keys yet to be derived from -// it, with the passed network. -func (k *ExtendedKey) SetNet(net *chaincfg.Params) { - if k.isPrivate { - k.version = net.HDPrivateKeyID[:] - } else { - k.version = net.HDPublicKeyID[:] - } -} - -// zero sets all bytes in the passed slice to zero. This is used to -// explicitly clear private key material from memory. -func zero(b []byte) { - lenb := len(b) - for i := 0; i < lenb; i++ { - b[i] = 0 - } -} - -// Zero manually clears all fields and bytes in the extended key. This can be -// used to explicitly clear key material from memory for enhanced security -// against memory scraping. This function only clears this particular key and -// not any children that have already been derived. -func (k *ExtendedKey) Zero() { - zero(k.key) - zero(k.pubKey) - zero(k.chainCode) - zero(k.parentFP) - k.version = nil - k.key = nil - k.depth = 0 - k.childNum = 0 - k.isPrivate = false -} - -// NewMaster creates a new master node for use in creating a hierarchical -// deterministic key chain. The seed must be between 128 and 512 bits and -// should be generated by a cryptographically secure random generation source. -// -// NOTE: There is an extremely small chance (< 1 in 2^127) the provided seed -// will derive to an unusable secret key. The ErrUnusable error will be -// returned if this should occur, so the caller must check for it and generate a -// new seed accordingly. -func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) { - // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. - if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes { - return nil, ErrInvalidSeedLen - } - - // First take the HMAC-SHA512 of the master key and the seed data: - // I = HMAC-SHA512(Key = "Bitcoin seed", Data = S) - hmac512 := hmac.New(sha512.New, masterKey) - hmac512.Write(seed) - lr := hmac512.Sum(nil) - - // Split "I" into two 32-byte sequences Il and Ir where: - // Il = master secret key - // Ir = master chain code - secretKey := lr[:len(lr)/2] - chainCode := lr[len(lr)/2:] - - // Ensure the key in usable. - secretKeyNum := new(big.Int).SetBytes(secretKey) - if secretKeyNum.Cmp(btcec.S256().N) >= 0 || secretKeyNum.Sign() == 0 { - return nil, ErrUnusableSeed - } - - parentFP := []byte{0x00, 0x00, 0x00, 0x00} - return newExtendedKey(net.HDPrivateKeyID[:], secretKey, chainCode, - parentFP, 0, 0, true), nil -} - -// NewKeyFromString returns a new extended key instance from a base58-encoded -// extended key. -func NewKeyFromString(key string) (*ExtendedKey, error) { - // The base58-decoded extended key must consist of a serialized payload - // plus an additional 4 bytes for the checksum. - decoded := base58.Decode(key) - if len(decoded) != serializedKeyLen+4 { - return nil, ErrInvalidKeyLen - } - - // The serialized format is: - // version (4) || depth (1) || parent fingerprint (4)) || - // child num (4) || chain code (32) || key data (33) || checksum (4) - - // Split the payload and checksum up and ensure the checksum matches. - payload := decoded[:len(decoded)-4] - checkSum := decoded[len(decoded)-4:] - expectedCheckSum := chainhash.DoubleHashB(payload)[:4] - if !bytes.Equal(checkSum, expectedCheckSum) { - return nil, ErrBadChecksum - } - - // Deserialize each of the payload fields. - version := payload[:4] - depth := uint16(payload[4:5][0]) - parentFP := payload[5:9] - childNum := binary.BigEndian.Uint32(payload[9:13]) - chainCode := payload[13:45] - keyData := payload[45:78] - - // The key data is a private key if it starts with 0x00. Serialized - // compressed pubkeys either start with 0x02 or 0x03. - isPrivate := keyData[0] == 0x00 - if isPrivate { - // Ensure the private key is valid. It must be within the range - // of the order of the secp256k1 curve and not be 0. - keyData = keyData[1:] - keyNum := new(big.Int).SetBytes(keyData) - if keyNum.Cmp(btcec.S256().N) >= 0 || keyNum.Sign() == 0 { - return nil, ErrUnusableSeed - } - } else { - // Ensure the public key parses correctly and is actually on the - // secp256k1 curve. - _, err := btcec.ParsePubKey(keyData, btcec.S256()) - if err != nil { - return nil, err - } - } - - return newExtendedKey(version, keyData, chainCode, parentFP, depth, - childNum, isPrivate), nil -} - -// GenerateSeed returns a cryptographically secure random seed that can be used -// as the input for the NewMaster function to generate a new master node. -// -// The length is in bytes and it must be between 16 and 64 (128 to 512 bits). -// The recommended length is 32 (256 bits) as defined by the RecommendedSeedLen -// constant. -func GenerateSeed(length uint8) ([]byte, error) { - // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. - if length < MinSeedBytes || length > MaxSeedBytes { - return nil, ErrInvalidSeedLen - } - - buf := make([]byte, length) - _, err := rand.Read(buf) - if err != nil { - return nil, err - } - - return buf, nil -} diff --git a/vendor/github.com/btcsuite/btcutil/hdkeychain/test_coverage.txt b/vendor/github.com/btcsuite/btcutil/hdkeychain/test_coverage.txt deleted file mode 100644 index c0bc7ef0350..00000000000 --- a/vendor/github.com/btcsuite/btcutil/hdkeychain/test_coverage.txt +++ /dev/null @@ -1,20 +0,0 @@ - -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.String 100.00% (18/18) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Zero 100.00% (9/9) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.pubKeyBytes 100.00% (7/7) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Neuter 100.00% (6/6) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.ECPrivKey 100.00% (4/4) -github.com/conformal/btcutil/hdkeychain/extendedkey.go zero 100.00% (3/3) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.SetNet 100.00% (3/3) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Address 100.00% (2/2) -github.com/conformal/btcutil/hdkeychain/extendedkey.go newExtendedKey 100.00% (1/1) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.IsPrivate 100.00% (1/1) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.ParentFingerprint 100.00% (1/1) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.ECPubKey 100.00% (1/1) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.IsForNet 100.00% (1/1) -github.com/conformal/btcutil/hdkeychain/extendedkey.go NewKeyFromString 95.83% (23/24) -github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Child 91.67% (33/36) -github.com/conformal/btcutil/hdkeychain/extendedkey.go NewMaster 91.67% (11/12) -github.com/conformal/btcutil/hdkeychain/extendedkey.go GenerateSeed 85.71% (6/7) -github.com/conformal/btcutil/hdkeychain ----------------------------- 95.59% (130/136) - diff --git a/vendor/github.com/btcsuite/fastsha256/LICENSE.md b/vendor/github.com/btcsuite/fastsha256/LICENSE.md deleted file mode 100644 index 6b382e436b7..00000000000 --- a/vendor/github.com/btcsuite/fastsha256/LICENSE.md +++ /dev/null @@ -1,52 +0,0 @@ -The original code for the fastsha256 project -came from the Go crypto/sha256 package, -which is released under the BSD-3-Clause license: - - Copyright (c) 2009 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. - ------------------------------------------------------------------------------ - -The code that was added in the fastsha256 project for midstate calculations -is released under the ISC license: - - ISC License - - Copyright (c) 2013 Conformal Systems LLC. - - Permission to use, copy, modify, and distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/btcsuite/fastsha256/sha256.go b/vendor/github.com/btcsuite/fastsha256/sha256.go deleted file mode 100644 index a5464b0184b..00000000000 --- a/vendor/github.com/btcsuite/fastsha256/sha256.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2009 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 fastsha256 implements the SHA224 and SHA256 hash algorithms as defined -// in FIPS 180-4. -package fastsha256 - -import ( - "crypto" - "hash" -) - -func init() { - crypto.RegisterHash(crypto.SHA224, New224) - crypto.RegisterHash(crypto.SHA256, New) -} - -// The size of a SHA256 checksum in bytes. -const Size = 32 - -// The size of a SHA224 checksum in bytes. -const Size224 = 28 - -// The blocksize of SHA256 and SHA224 in bytes. -const BlockSize = 64 - -const ( - chunk = 64 - init0 = 0x6A09E667 - init1 = 0xBB67AE85 - init2 = 0x3C6EF372 - init3 = 0xA54FF53A - init4 = 0x510E527F - init5 = 0x9B05688C - init6 = 0x1F83D9AB - init7 = 0x5BE0CD19 - init0_224 = 0xC1059ED8 - init1_224 = 0x367CD507 - init2_224 = 0x3070DD17 - init3_224 = 0xF70E5939 - init4_224 = 0xFFC00B31 - init5_224 = 0x68581511 - init6_224 = 0x64F98FA7 - init7_224 = 0xBEFA4FA4 -) - -// digest represents the partial evaluation of a checksum. -type digest struct { - h [8]uint32 - x [chunk]byte - nx int - len uint64 - is224 bool // mark if this digest is SHA-224 -} - -func (d *digest) Reset() { - if !d.is224 { - d.h[0] = init0 - d.h[1] = init1 - d.h[2] = init2 - d.h[3] = init3 - d.h[4] = init4 - d.h[5] = init5 - d.h[6] = init6 - d.h[7] = init7 - } else { - d.h[0] = init0_224 - d.h[1] = init1_224 - d.h[2] = init2_224 - d.h[3] = init3_224 - d.h[4] = init4_224 - d.h[5] = init5_224 - d.h[6] = init6_224 - d.h[7] = init7_224 - } - d.nx = 0 - d.len = 0 -} - -// New returns a new hash.Hash computing the SHA256 checksum. -func New() hash.Hash { - d := new(digest) - d.Reset() - return d -} - -// New224 returns a new hash.Hash computing the SHA224 checksum. -func New224() hash.Hash { - d := new(digest) - d.is224 = true - d.Reset() - return d -} - -func (d *digest) Size() int { - if !d.is224 { - return Size - } - return Size224 -} - -func (d *digest) BlockSize() int { return BlockSize } - -func (d *digest) Write(p []byte) (nn int, err error) { - nn = len(p) - d.len += uint64(nn) - if d.nx > 0 { - n := copy(d.x[d.nx:], p) - d.nx += n - if d.nx == chunk { - block(d, d.x[:]) - d.nx = 0 - } - p = p[n:] - } - if len(p) >= chunk { - n := len(p) &^ (chunk - 1) - block(d, p[:n]) - p = p[n:] - } - if len(p) > 0 { - d.nx = copy(d.x[:], p) - } - return -} - -func (d *digest) Sum(in []byte) []byte { - // Make a copy of d so that caller can keep writing and summing. - d0 := *d - hash := d0.checkSum() - if d0.is224 { - return append(in, hash[:Size224]...) - } - return append(in, hash[:]...) -} - -func (d *digest) checkSum() [Size]byte { - len := d.len - // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. - var tmp [64]byte - tmp[0] = 0x80 - if len%64 < 56 { - d.Write(tmp[0 : 56-len%64]) - } else { - d.Write(tmp[0 : 64+56-len%64]) - } - - // Length in bits. - len <<= 3 - for i := uint(0); i < 8; i++ { - tmp[i] = byte(len >> (56 - 8*i)) - } - d.Write(tmp[0:8]) - - if d.nx != 0 { - panic("d.nx != 0") - } - - h := d.h[:] - if d.is224 { - h = d.h[:7] - } - - var digest [Size]byte - for i, s := range h { - digest[i*4] = byte(s >> 24) - digest[i*4+1] = byte(s >> 16) - digest[i*4+2] = byte(s >> 8) - digest[i*4+3] = byte(s) - } - - return digest -} - -// Sum256 returns the SHA256 checksum of the data. -func Sum256(data []byte) [Size]byte { - var d digest - d.Reset() - d.Write(data) - return d.checkSum() -} - -// Sum224 returns the SHA224 checksum of the data. -func Sum224(data []byte) (sum224 [Size224]byte) { - var d digest - d.is224 = true - d.Reset() - d.Write(data) - sum := d.checkSum() - copy(sum224[:], sum[:Size224]) - return -} - -// MidState256 returns the internal hashing state after hashing the first chunk -// (BlockSize) of the data. This implemenation does not provide any mechanism -// to initialize the internal hashing state, so this information can't be used -// to skip hashing the first chunk on subsequent calls, but it is exposed so -// sophisticated callers can make use of it. -func MidState256(data []byte) [Size]byte { - if len(data) > BlockSize { - data = data[:BlockSize] - } - - var d digest - d.Reset() - d.Write(data) - - var midState [Size]byte - for i, s := range d.h { - midState[i*4] = byte(s >> 24) - midState[i*4+1] = byte(s >> 16) - midState[i*4+2] = byte(s >> 8) - midState[i*4+3] = byte(s) - } - - return midState -} diff --git a/vendor/github.com/btcsuite/fastsha256/sha256block.go b/vendor/github.com/btcsuite/fastsha256/sha256block.go deleted file mode 100644 index ff0c3faa328..00000000000 --- a/vendor/github.com/btcsuite/fastsha256/sha256block.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2009 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 appengine !386,!amd64 - -// SHA256 block step. -// In its own file so that a faster assembly or C version -// can be substituted easily. - -package fastsha256 - -var _K = []uint32{ - 0x428a2f98, - 0x71374491, - 0xb5c0fbcf, - 0xe9b5dba5, - 0x3956c25b, - 0x59f111f1, - 0x923f82a4, - 0xab1c5ed5, - 0xd807aa98, - 0x12835b01, - 0x243185be, - 0x550c7dc3, - 0x72be5d74, - 0x80deb1fe, - 0x9bdc06a7, - 0xc19bf174, - 0xe49b69c1, - 0xefbe4786, - 0x0fc19dc6, - 0x240ca1cc, - 0x2de92c6f, - 0x4a7484aa, - 0x5cb0a9dc, - 0x76f988da, - 0x983e5152, - 0xa831c66d, - 0xb00327c8, - 0xbf597fc7, - 0xc6e00bf3, - 0xd5a79147, - 0x06ca6351, - 0x14292967, - 0x27b70a85, - 0x2e1b2138, - 0x4d2c6dfc, - 0x53380d13, - 0x650a7354, - 0x766a0abb, - 0x81c2c92e, - 0x92722c85, - 0xa2bfe8a1, - 0xa81a664b, - 0xc24b8b70, - 0xc76c51a3, - 0xd192e819, - 0xd6990624, - 0xf40e3585, - 0x106aa070, - 0x19a4c116, - 0x1e376c08, - 0x2748774c, - 0x34b0bcb5, - 0x391c0cb3, - 0x4ed8aa4a, - 0x5b9cca4f, - 0x682e6ff3, - 0x748f82ee, - 0x78a5636f, - 0x84c87814, - 0x8cc70208, - 0x90befffa, - 0xa4506ceb, - 0xbef9a3f7, - 0xc67178f2, -} - -func block(dig *digest, p []byte) { - var w [64]uint32 - h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] - for len(p) >= chunk { - // Can interlace the computation of w with the - // rounds below if needed for speed. - for i := 0; i < 16; i++ { - j := i * 4 - w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3]) - } - for i := 16; i < 64; i++ { - v1 := w[i-2] - t1 := (v1>>17 | v1<<(32-17)) ^ (v1>>19 | v1<<(32-19)) ^ (v1 >> 10) - v2 := w[i-15] - t2 := (v2>>7 | v2<<(32-7)) ^ (v2>>18 | v2<<(32-18)) ^ (v2 >> 3) - w[i] = t1 + w[i-7] + t2 + w[i-16] - } - - a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7 - - for i := 0; i < 64; i++ { - t1 := h + ((e>>6 | e<<(32-6)) ^ (e>>11 | e<<(32-11)) ^ (e>>25 | e<<(32-25))) + ((e & f) ^ (^e & g)) + _K[i] + w[i] - - t2 := ((a>>2 | a<<(32-2)) ^ (a>>13 | a<<(32-13)) ^ (a>>22 | a<<(32-22))) + ((a & b) ^ (a & c) ^ (b & c)) - - h = g - g = f - f = e - e = d + t1 - d = c - c = b - b = a - a = t1 + t2 - } - - h0 += a - h1 += b - h2 += c - h3 += d - h4 += e - h5 += f - h6 += g - h7 += h - - p = p[chunk:] - } - - dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7 -} diff --git a/vendor/github.com/btcsuite/fastsha256/sha256block_386.s b/vendor/github.com/btcsuite/fastsha256/sha256block_386.s deleted file mode 100644 index c34d9be91e4..00000000000 --- a/vendor/github.com/btcsuite/fastsha256/sha256block_386.s +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !appengine - -// SHA256 block routine. See sha256block.go for Go equivalent. -// -// The algorithm is detailed in FIPS 180-4: -// -// http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf -// -// Wt = Mt; for 0 <= t <= 15 -// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 -// -// a = H0 -// b = H1 -// c = H2 -// d = H3 -// e = H4 -// f = H5 -// g = H6 -// h = H7 -// -// for t = 0 to 63 { -// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt -// T2 = BIGSIGMA0(a) + Maj(a,b,c) -// h = g -// g = f -// f = e -// e = d + T1 -// d = c -// c = b -// b = a -// a = T1 + T2 -// } -// -// H0 = a + H0 -// H1 = b + H1 -// H2 = c + H2 -// H3 = d + H3 -// H4 = e + H4 -// H5 = f + H5 -// H6 = g + H6 -// H7 = h + H7 - -// Wt = Mt; for 0 <= t <= 15 -#define MSGSCHEDULE0(index) \ - MOVL (index*4)(SI), AX; \ - BSWAPL AX; \ - MOVL AX, (index*4)(BP) - -// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 -// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x) -// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x) -#define MSGSCHEDULE1(index) \ - MOVL ((index-2)*4)(BP), AX; \ - MOVL AX, CX; \ - RORL $17, AX; \ - MOVL CX, DX; \ - RORL $19, CX; \ - SHRL $10, DX; \ - MOVL ((index-15)*4)(BP), BX; \ - XORL CX, AX; \ - MOVL BX, CX; \ - XORL DX, AX; \ - RORL $7, BX; \ - MOVL CX, DX; \ - SHRL $3, DX; \ - RORL $18, CX; \ - ADDL ((index-7)*4)(BP), AX; \ - XORL CX, BX; \ - XORL DX, BX; \ - ADDL ((index-16)*4)(BP), BX; \ - ADDL BX, AX; \ - MOVL AX, ((index)*4)(BP) - -// Calculate T1 in AX - uses AX, BX, CX and DX registers. -// Wt is passed in AX. -// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt -// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) -// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) -#define SHA256T1(const, e, f, g, h) \ - MOVL (h*4)(DI), BX; \ - ADDL AX, BX; \ - MOVL (e*4)(DI), AX; \ - ADDL $const, BX; \ - MOVL (e*4)(DI), CX; \ - RORL $6, AX; \ - MOVL (e*4)(DI), DX; \ - RORL $11, CX; \ - XORL CX, AX; \ - MOVL (e*4)(DI), CX; \ - RORL $25, DX; \ - ANDL (f*4)(DI), CX; \ - XORL AX, DX; \ - MOVL (e*4)(DI), AX; \ - NOTL AX; \ - ADDL DX, BX; \ - ANDL (g*4)(DI), AX; \ - XORL CX, AX; \ - ADDL BX, AX - -// Calculate T2 in BX - uses AX, BX, CX and DX registers. -// T2 = BIGSIGMA0(a) + Maj(a, b, c) -// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) -// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) -#define SHA256T2(a, b, c) \ - MOVL (a*4)(DI), AX; \ - MOVL (c*4)(DI), BX; \ - RORL $2, AX; \ - MOVL (a*4)(DI), DX; \ - ANDL (b*4)(DI), BX; \ - RORL $13, DX; \ - MOVL (a*4)(DI), CX; \ - ANDL (c*4)(DI), CX; \ - XORL DX, AX; \ - XORL CX, BX; \ - MOVL (a*4)(DI), DX; \ - MOVL (b*4)(DI), CX; \ - RORL $22, DX; \ - ANDL (a*4)(DI), CX; \ - XORL CX, BX; \ - XORL DX, AX; \ - ADDL AX, BX - -// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. -// The values for e and a are stored in d and h, ready for rotation. -#define SHA256ROUND(index, const, a, b, c, d, e, f, g, h) \ - SHA256T1(const, e, f, g, h); \ - MOVL AX, 292(SP); \ - SHA256T2(a, b, c); \ - MOVL 292(SP), AX; \ - ADDL AX, BX; \ - ADDL AX, (d*4)(DI); \ - MOVL BX, (h*4)(DI) - -#define SHA256ROUND0(index, const, a, b, c, d, e, f, g, h) \ - MSGSCHEDULE0(index); \ - SHA256ROUND(index, const, a, b, c, d, e, f, g, h) - -#define SHA256ROUND1(index, const, a, b, c, d, e, f, g, h) \ - MSGSCHEDULE1(index); \ - SHA256ROUND(index, const, a, b, c, d, e, f, g, h) - -TEXT ·block(SB),0,$296-12 - MOVL p_base+4(FP), SI - MOVL p_len+8(FP), DX - SHRL $6, DX - SHLL $6, DX - - LEAL (SI)(DX*1), DI - MOVL DI, 288(SP) - CMPL SI, DI - JEQ end - - LEAL 256(SP), DI // variables - - MOVL dig+0(FP), BP - MOVL (0*4)(BP), AX // a = H0 - MOVL AX, (0*4)(DI) - MOVL (1*4)(BP), BX // b = H1 - MOVL BX, (1*4)(DI) - MOVL (2*4)(BP), CX // c = H2 - MOVL CX, (2*4)(DI) - MOVL (3*4)(BP), DX // d = H3 - MOVL DX, (3*4)(DI) - MOVL (4*4)(BP), AX // e = H4 - MOVL AX, (4*4)(DI) - MOVL (5*4)(BP), BX // f = H5 - MOVL BX, (5*4)(DI) - MOVL (6*4)(BP), CX // g = H6 - MOVL CX, (6*4)(DI) - MOVL (7*4)(BP), DX // h = H7 - MOVL DX, (7*4)(DI) - -loop: - MOVL SP, BP // message schedule - - SHA256ROUND0(0, 0x428a2f98, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND0(1, 0x71374491, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND0(2, 0xb5c0fbcf, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND0(3, 0xe9b5dba5, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND0(4, 0x3956c25b, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND0(5, 0x59f111f1, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND0(6, 0x923f82a4, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND0(7, 0xab1c5ed5, 1, 2, 3, 4, 5, 6, 7, 0) - SHA256ROUND0(8, 0xd807aa98, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND0(9, 0x12835b01, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND0(10, 0x243185be, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND0(11, 0x550c7dc3, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND0(12, 0x72be5d74, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND0(13, 0x80deb1fe, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND0(14, 0x9bdc06a7, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND0(15, 0xc19bf174, 1, 2, 3, 4, 5, 6, 7, 0) - - SHA256ROUND1(16, 0xe49b69c1, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND1(17, 0xefbe4786, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND1(18, 0x0fc19dc6, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND1(19, 0x240ca1cc, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND1(20, 0x2de92c6f, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND1(21, 0x4a7484aa, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND1(22, 0x5cb0a9dc, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND1(23, 0x76f988da, 1, 2, 3, 4, 5, 6, 7, 0) - SHA256ROUND1(24, 0x983e5152, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND1(25, 0xa831c66d, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND1(26, 0xb00327c8, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND1(27, 0xbf597fc7, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND1(28, 0xc6e00bf3, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND1(29, 0xd5a79147, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND1(30, 0x06ca6351, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND1(31, 0x14292967, 1, 2, 3, 4, 5, 6, 7, 0) - SHA256ROUND1(32, 0x27b70a85, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND1(33, 0x2e1b2138, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND1(34, 0x4d2c6dfc, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND1(35, 0x53380d13, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND1(36, 0x650a7354, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND1(37, 0x766a0abb, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND1(38, 0x81c2c92e, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND1(39, 0x92722c85, 1, 2, 3, 4, 5, 6, 7, 0) - SHA256ROUND1(40, 0xa2bfe8a1, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND1(41, 0xa81a664b, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND1(42, 0xc24b8b70, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND1(43, 0xc76c51a3, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND1(44, 0xd192e819, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND1(45, 0xd6990624, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND1(46, 0xf40e3585, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND1(47, 0x106aa070, 1, 2, 3, 4, 5, 6, 7, 0) - SHA256ROUND1(48, 0x19a4c116, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND1(49, 0x1e376c08, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND1(50, 0x2748774c, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND1(51, 0x34b0bcb5, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND1(52, 0x391c0cb3, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND1(53, 0x4ed8aa4a, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND1(54, 0x5b9cca4f, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND1(55, 0x682e6ff3, 1, 2, 3, 4, 5, 6, 7, 0) - SHA256ROUND1(56, 0x748f82ee, 0, 1, 2, 3, 4, 5, 6, 7) - SHA256ROUND1(57, 0x78a5636f, 7, 0, 1, 2, 3, 4, 5, 6) - SHA256ROUND1(58, 0x84c87814, 6, 7, 0, 1, 2, 3, 4, 5) - SHA256ROUND1(59, 0x8cc70208, 5, 6, 7, 0, 1, 2, 3, 4) - SHA256ROUND1(60, 0x90befffa, 4, 5, 6, 7, 0, 1, 2, 3) - SHA256ROUND1(61, 0xa4506ceb, 3, 4, 5, 6, 7, 0, 1, 2) - SHA256ROUND1(62, 0xbef9a3f7, 2, 3, 4, 5, 6, 7, 0, 1) - SHA256ROUND1(63, 0xc67178f2, 1, 2, 3, 4, 5, 6, 7, 0) - - MOVL dig+0(FP), BP - MOVL (0*4)(BP), AX // H0 = a + H0 - ADDL (0*4)(DI), AX - MOVL AX, (0*4)(DI) - MOVL AX, (0*4)(BP) - MOVL (1*4)(BP), BX // H1 = b + H1 - ADDL (1*4)(DI), BX - MOVL BX, (1*4)(DI) - MOVL BX, (1*4)(BP) - MOVL (2*4)(BP), CX // H2 = c + H2 - ADDL (2*4)(DI), CX - MOVL CX, (2*4)(DI) - MOVL CX, (2*4)(BP) - MOVL (3*4)(BP), DX // H3 = d + H3 - ADDL (3*4)(DI), DX - MOVL DX, (3*4)(DI) - MOVL DX, (3*4)(BP) - MOVL (4*4)(BP), AX // H4 = e + H4 - ADDL (4*4)(DI), AX - MOVL AX, (4*4)(DI) - MOVL AX, (4*4)(BP) - MOVL (5*4)(BP), BX // H5 = f + H5 - ADDL (5*4)(DI), BX - MOVL BX, (5*4)(DI) - MOVL BX, (5*4)(BP) - MOVL (6*4)(BP), CX // H6 = g + H6 - ADDL (6*4)(DI), CX - MOVL CX, (6*4)(DI) - MOVL CX, (6*4)(BP) - MOVL (7*4)(BP), DX // H7 = h + H7 - ADDL (7*4)(DI), DX - MOVL DX, (7*4)(DI) - MOVL DX, (7*4)(BP) - - ADDL $64, SI - CMPL SI, 288(SP) - JB loop - -end: - RET diff --git a/vendor/github.com/btcsuite/fastsha256/sha256block_amd64.s b/vendor/github.com/btcsuite/fastsha256/sha256block_amd64.s deleted file mode 100644 index 8e18b0648d2..00000000000 --- a/vendor/github.com/btcsuite/fastsha256/sha256block_amd64.s +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !appengine - -//#include "../../../cmd/ld/textflag.h" -// just use the #define for now since this isn't in the main repo yet. -#define NOSPLIT 4 - -// SHA256 block routine. See sha256block.go for Go equivalent. -// -// The algorithm is detailed in FIPS 180-4: -// -// http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf -// -// Wt = Mt; for 0 <= t <= 15 -// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 -// -// a = H0 -// b = H1 -// c = H2 -// d = H3 -// e = H4 -// f = H5 -// g = H6 -// h = H7 -// -// for t = 0 to 63 { -// T1 = h + BIGSIGMA1(e) + Ch(e,f,g) + Kt + Wt -// T2 = BIGSIGMA0(a) + Maj(a,b,c) -// h = g -// g = f -// f = e -// e = d + T1 -// d = c -// c = b -// b = a -// a = T1 + T2 -// } -// -// H0 = a + H0 -// H1 = b + H1 -// H2 = c + H2 -// H3 = d + H3 -// H4 = e + H4 -// H5 = f + H5 -// H6 = g + H6 -// H7 = h + H7 - -// Wt = Mt; for 0 <= t <= 15 -#define MSGSCHEDULE0(index) \ - MOVL (index*4)(SI), AX; \ - BSWAPL AX; \ - MOVL AX, (index*4)(BP) - -// Wt = SIGMA1(Wt-2) + Wt-7 + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63 -// SIGMA0(x) = ROTR(7,x) XOR ROTR(18,x) XOR SHR(3,x) -// SIGMA1(x) = ROTR(17,x) XOR ROTR(19,x) XOR SHR(10,x) -#define MSGSCHEDULE1(index) \ - MOVL ((index-2)*4)(BP), AX; \ - MOVL AX, CX; \ - RORL $17, AX; \ - MOVL CX, DX; \ - RORL $19, CX; \ - SHRL $10, DX; \ - MOVL ((index-15)*4)(BP), BX; \ - XORL CX, AX; \ - MOVL BX, CX; \ - XORL DX, AX; \ - RORL $7, BX; \ - MOVL CX, DX; \ - SHRL $3, DX; \ - RORL $18, CX; \ - ADDL ((index-7)*4)(BP), AX; \ - XORL CX, BX; \ - XORL DX, BX; \ - ADDL ((index-16)*4)(BP), BX; \ - ADDL BX, AX; \ - MOVL AX, ((index)*4)(BP) - -// Calculate T1 in AX - uses AX, CX and DX registers. -// h is also used as an accumulator. Wt is passed in AX. -// T1 = h + BIGSIGMA1(e) + Ch(e, f, g) + Kt + Wt -// BIGSIGMA1(x) = ROTR(6,x) XOR ROTR(11,x) XOR ROTR(25,x) -// Ch(x, y, z) = (x AND y) XOR (NOT x AND z) -#define SHA256T1(const, e, f, g, h) \ - ADDL AX, h; \ - MOVL e, AX; \ - ADDL $const, h; \ - MOVL e, CX; \ - RORL $6, AX; \ - MOVL e, DX; \ - RORL $11, CX; \ - XORL CX, AX; \ - MOVL e, CX; \ - RORL $25, DX; \ - ANDL f, CX; \ - XORL AX, DX; \ - MOVL e, AX; \ - NOTL AX; \ - ADDL DX, h; \ - ANDL g, AX; \ - XORL CX, AX; \ - ADDL h, AX - -// Calculate T2 in BX - uses BX, CX, DX and DI registers. -// T2 = BIGSIGMA0(a) + Maj(a, b, c) -// BIGSIGMA0(x) = ROTR(2,x) XOR ROTR(13,x) XOR ROTR(22,x) -// Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) -#define SHA256T2(a, b, c) \ - MOVL a, DI; \ - MOVL c, BX; \ - RORL $2, DI; \ - MOVL a, DX; \ - ANDL b, BX; \ - RORL $13, DX; \ - MOVL a, CX; \ - ANDL c, CX; \ - XORL DX, DI; \ - XORL CX, BX; \ - MOVL a, DX; \ - MOVL b, CX; \ - RORL $22, DX; \ - ANDL a, CX; \ - XORL CX, BX; \ - XORL DX, DI; \ - ADDL DI, BX - -// Calculate T1 and T2, then e = d + T1 and a = T1 + T2. -// The values for e and a are stored in d and h, ready for rotation. -#define SHA256ROUND(index, const, a, b, c, d, e, f, g, h) \ - SHA256T1(const, e, f, g, h); \ - SHA256T2(a, b, c); \ - MOVL BX, h; \ - ADDL AX, d; \ - ADDL AX, h - -#define SHA256ROUND0(index, const, a, b, c, d, e, f, g, h) \ - MSGSCHEDULE0(index); \ - SHA256ROUND(index, const, a, b, c, d, e, f, g, h) - -#define SHA256ROUND1(index, const, a, b, c, d, e, f, g, h) \ - MSGSCHEDULE1(index); \ - SHA256ROUND(index, const, a, b, c, d, e, f, g, h) - -TEXT ·block(SB),0,$264-32 - MOVQ p_base+8(FP), SI - MOVQ p_len+16(FP), DX - SHRQ $6, DX - SHLQ $6, DX - - LEAQ (SI)(DX*1), DI - MOVQ DI, 256(SP) - CMPQ SI, DI - JEQ end - - MOVQ dig+0(FP), BP - MOVL (0*4)(BP), R8 // a = H0 - MOVL (1*4)(BP), R9 // b = H1 - MOVL (2*4)(BP), R10 // c = H2 - MOVL (3*4)(BP), R11 // d = H3 - MOVL (4*4)(BP), R12 // e = H4 - MOVL (5*4)(BP), R13 // f = H5 - MOVL (6*4)(BP), R14 // g = H6 - MOVL (7*4)(BP), R15 // h = H7 - -loop: - MOVQ SP, BP // message schedule - - SHA256ROUND0(0, 0x428a2f98, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND0(1, 0x71374491, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND0(2, 0xb5c0fbcf, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND0(3, 0xe9b5dba5, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND0(4, 0x3956c25b, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND0(5, 0x59f111f1, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND0(6, 0x923f82a4, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND0(7, 0xab1c5ed5, R9, R10, R11, R12, R13, R14, R15, R8) - SHA256ROUND0(8, 0xd807aa98, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND0(9, 0x12835b01, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND0(10, 0x243185be, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND0(11, 0x550c7dc3, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND0(12, 0x72be5d74, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND0(13, 0x80deb1fe, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND0(14, 0x9bdc06a7, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND0(15, 0xc19bf174, R9, R10, R11, R12, R13, R14, R15, R8) - - SHA256ROUND1(16, 0xe49b69c1, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND1(17, 0xefbe4786, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND1(18, 0x0fc19dc6, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND1(19, 0x240ca1cc, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND1(20, 0x2de92c6f, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND1(21, 0x4a7484aa, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND1(22, 0x5cb0a9dc, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND1(23, 0x76f988da, R9, R10, R11, R12, R13, R14, R15, R8) - SHA256ROUND1(24, 0x983e5152, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND1(25, 0xa831c66d, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND1(26, 0xb00327c8, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND1(27, 0xbf597fc7, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND1(28, 0xc6e00bf3, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND1(29, 0xd5a79147, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND1(30, 0x06ca6351, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND1(31, 0x14292967, R9, R10, R11, R12, R13, R14, R15, R8) - SHA256ROUND1(32, 0x27b70a85, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND1(33, 0x2e1b2138, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND1(34, 0x4d2c6dfc, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND1(35, 0x53380d13, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND1(36, 0x650a7354, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND1(37, 0x766a0abb, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND1(38, 0x81c2c92e, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND1(39, 0x92722c85, R9, R10, R11, R12, R13, R14, R15, R8) - SHA256ROUND1(40, 0xa2bfe8a1, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND1(41, 0xa81a664b, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND1(42, 0xc24b8b70, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND1(43, 0xc76c51a3, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND1(44, 0xd192e819, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND1(45, 0xd6990624, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND1(46, 0xf40e3585, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND1(47, 0x106aa070, R9, R10, R11, R12, R13, R14, R15, R8) - SHA256ROUND1(48, 0x19a4c116, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND1(49, 0x1e376c08, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND1(50, 0x2748774c, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND1(51, 0x34b0bcb5, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND1(52, 0x391c0cb3, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND1(53, 0x4ed8aa4a, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND1(54, 0x5b9cca4f, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND1(55, 0x682e6ff3, R9, R10, R11, R12, R13, R14, R15, R8) - SHA256ROUND1(56, 0x748f82ee, R8, R9, R10, R11, R12, R13, R14, R15) - SHA256ROUND1(57, 0x78a5636f, R15, R8, R9, R10, R11, R12, R13, R14) - SHA256ROUND1(58, 0x84c87814, R14, R15, R8, R9, R10, R11, R12, R13) - SHA256ROUND1(59, 0x8cc70208, R13, R14, R15, R8, R9, R10, R11, R12) - SHA256ROUND1(60, 0x90befffa, R12, R13, R14, R15, R8, R9, R10, R11) - SHA256ROUND1(61, 0xa4506ceb, R11, R12, R13, R14, R15, R8, R9, R10) - SHA256ROUND1(62, 0xbef9a3f7, R10, R11, R12, R13, R14, R15, R8, R9) - SHA256ROUND1(63, 0xc67178f2, R9, R10, R11, R12, R13, R14, R15, R8) - - MOVQ dig+0(FP), BP - ADDL (0*4)(BP), R8 // H0 = a + H0 - MOVL R8, (0*4)(BP) - ADDL (1*4)(BP), R9 // H1 = b + H1 - MOVL R9, (1*4)(BP) - ADDL (2*4)(BP), R10 // H2 = c + H2 - MOVL R10, (2*4)(BP) - ADDL (3*4)(BP), R11 // H3 = d + H3 - MOVL R11, (3*4)(BP) - ADDL (4*4)(BP), R12 // H4 = e + H4 - MOVL R12, (4*4)(BP) - ADDL (5*4)(BP), R13 // H5 = f + H5 - MOVL R13, (5*4)(BP) - ADDL (6*4)(BP), R14 // H6 = g + H6 - MOVL R14, (6*4)(BP) - ADDL (7*4)(BP), R15 // H7 = h + H7 - MOVL R15, (7*4)(BP) - - ADDQ $64, SI - CMPQ SI, 256(SP) - JB loop - -end: - RET diff --git a/vendor/github.com/btcsuite/fastsha256/sha256block_decl.go b/vendor/github.com/btcsuite/fastsha256/sha256block_decl.go deleted file mode 100644 index 389add77e0b..00000000000 --- a/vendor/github.com/btcsuite/fastsha256/sha256block_decl.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build 386,!appengine amd64,!appengine - -package fastsha256 - -//go:noescape - -func block(dig *digest, p []byte) diff --git a/vendor/github.com/btcsuite/golangcrypto/ripemd160/ripemd160.go b/vendor/github.com/btcsuite/golangcrypto/ripemd160/ripemd160.go deleted file mode 100644 index 9472f15002a..00000000000 --- a/vendor/github.com/btcsuite/golangcrypto/ripemd160/ripemd160.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2010 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 ripemd160 implements the RIPEMD-160 hash algorithm. -package ripemd160 // import "github.com/btcsuite/golangcrypto/ripemd160" - -// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart -// Preneel with specifications available at: -// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf. - -import ( - "crypto" - "hash" -) - -func init() { - crypto.RegisterHash(crypto.RIPEMD160, New) -} - -// The size of the checksum in bytes. -const Size = 20 - -// The block size of the hash algorithm in bytes. -const BlockSize = 64 - -const ( - _s0 = 0x67452301 - _s1 = 0xefcdab89 - _s2 = 0x98badcfe - _s3 = 0x10325476 - _s4 = 0xc3d2e1f0 -) - -// digest represents the partial evaluation of a checksum. -type digest struct { - s [5]uint32 // running context - x [BlockSize]byte // temporary buffer - nx int // index into x - tc uint64 // total count of bytes processed -} - -func (d *digest) Reset() { - d.s[0], d.s[1], d.s[2], d.s[3], d.s[4] = _s0, _s1, _s2, _s3, _s4 - d.nx = 0 - d.tc = 0 -} - -// New returns a new hash.Hash computing the checksum. -func New() hash.Hash { - result := new(digest) - result.Reset() - return result -} - -func (d *digest) Size() int { return Size } - -func (d *digest) BlockSize() int { return BlockSize } - -func (d *digest) Write(p []byte) (nn int, err error) { - nn = len(p) - d.tc += uint64(nn) - if d.nx > 0 { - n := len(p) - if n > BlockSize-d.nx { - n = BlockSize - d.nx - } - for i := 0; i < n; i++ { - d.x[d.nx+i] = p[i] - } - d.nx += n - if d.nx == BlockSize { - _Block(d, d.x[0:]) - d.nx = 0 - } - p = p[n:] - } - n := _Block(d, p) - p = p[n:] - if len(p) > 0 { - d.nx = copy(d.x[:], p) - } - return -} - -func (d0 *digest) Sum(in []byte) []byte { - // Make a copy of d0 so that caller can keep writing and summing. - d := *d0 - - // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. - tc := d.tc - var tmp [64]byte - tmp[0] = 0x80 - if tc%64 < 56 { - d.Write(tmp[0 : 56-tc%64]) - } else { - d.Write(tmp[0 : 64+56-tc%64]) - } - - // Length in bits. - tc <<= 3 - for i := uint(0); i < 8; i++ { - tmp[i] = byte(tc >> (8 * i)) - } - d.Write(tmp[0:8]) - - if d.nx != 0 { - panic("d.nx != 0") - } - - var digest [Size]byte - for i, s := range d.s { - digest[i*4] = byte(s) - digest[i*4+1] = byte(s >> 8) - digest[i*4+2] = byte(s >> 16) - digest[i*4+3] = byte(s >> 24) - } - - return append(in, digest[:]...) -} diff --git a/vendor/github.com/btcsuite/golangcrypto/ripemd160/ripemd160block.go b/vendor/github.com/btcsuite/golangcrypto/ripemd160/ripemd160block.go deleted file mode 100644 index 7bc8e6c485e..00000000000 --- a/vendor/github.com/btcsuite/golangcrypto/ripemd160/ripemd160block.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2010 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. - -// RIPEMD-160 block step. -// In its own file so that a faster assembly or C version -// can be substituted easily. - -package ripemd160 - -// work buffer indices and roll amounts for one line -var _n = [80]uint{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, - 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, - 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, - 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, -} - -var _r = [80]uint{ - 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, - 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, - 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, - 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, - 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, -} - -// same for the other parallel one -var n_ = [80]uint{ - 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, - 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, - 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, - 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, - 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, -} - -var r_ = [80]uint{ - 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, - 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, - 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, - 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, - 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11, -} - -func _Block(md *digest, p []byte) int { - n := 0 - var x [16]uint32 - var alpha, beta uint32 - for len(p) >= BlockSize { - a, b, c, d, e := md.s[0], md.s[1], md.s[2], md.s[3], md.s[4] - aa, bb, cc, dd, ee := a, b, c, d, e - j := 0 - for i := 0; i < 16; i++ { - x[i] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24 - j += 4 - } - - // round 1 - i := 0 - for i < 16 { - alpha = a + (b ^ c ^ d) + x[_n[i]] - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 - a, b, c, d, e = e, alpha, b, beta, d - - // parallel line - alpha = aa + (bb ^ (cc | ^dd)) + x[n_[i]] + 0x50a28be6 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - - i++ - } - - // round 2 - for i < 32 { - alpha = a + (b&c | ^b&d) + x[_n[i]] + 0x5a827999 - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 - a, b, c, d, e = e, alpha, b, beta, d - - // parallel line - alpha = aa + (bb&dd | cc&^dd) + x[n_[i]] + 0x5c4dd124 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - - i++ - } - - // round 3 - for i < 48 { - alpha = a + (b | ^c ^ d) + x[_n[i]] + 0x6ed9eba1 - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 - a, b, c, d, e = e, alpha, b, beta, d - - // parallel line - alpha = aa + (bb | ^cc ^ dd) + x[n_[i]] + 0x6d703ef3 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - - i++ - } - - // round 4 - for i < 64 { - alpha = a + (b&d | c&^d) + x[_n[i]] + 0x8f1bbcdc - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 - a, b, c, d, e = e, alpha, b, beta, d - - // parallel line - alpha = aa + (bb&cc | ^bb&dd) + x[n_[i]] + 0x7a6d76e9 - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - - i++ - } - - // round 5 - for i < 80 { - alpha = a + (b ^ (c | ^d)) + x[_n[i]] + 0xa953fd4e - s := _r[i] - alpha = (alpha<>(32-s)) + e - beta = c<<10 | c>>22 - a, b, c, d, e = e, alpha, b, beta, d - - // parallel line - alpha = aa + (bb ^ cc ^ dd) + x[n_[i]] - s = r_[i] - alpha = (alpha<>(32-s)) + ee - beta = cc<<10 | cc>>22 - aa, bb, cc, dd, ee = ee, alpha, bb, beta, dd - - i++ - } - - // combine results - dd += c + md.s[1] - md.s[1] = md.s[2] + d + ee - md.s[2] = md.s[3] + e + aa - md.s[3] = md.s[4] + a + bb - md.s[4] = md.s[0] + b + cc - md.s[0] = dd - - p = p[BlockSize:] - n += BlockSize - } - return n -} diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE new file mode 100644 index 00000000000..c836416192d --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012-2016 Dave Collins + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go similarity index 98% rename from vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypass.go rename to vendor/github.com/davecgh/go-spew/spew/bypass.go index d42a0bc4afc..8a4a6589a2d 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -1,4 +1,4 @@ -// Copyright (c) 2015 Dave Collins +// Copyright (c) 2015-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go similarity index 96% rename from vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go rename to vendor/github.com/davecgh/go-spew/spew/bypasssafe.go index e47a4e79513..1fe3cf3d5d1 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -1,4 +1,4 @@ -// Copyright (c) 2015 Dave Collins +// Copyright (c) 2015-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go similarity index 99% rename from vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/common.go rename to vendor/github.com/davecgh/go-spew/spew/common.go index 14f02dc15b7..7c519ff47ac 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/common.go +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Dave Collins + * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go new file mode 100644 index 00000000000..2e3d22f3120 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/config.go @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. +type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + + // MaxDepth controls the maximum number of levels to descend into nested + // data structures. The default, 0, means there is no limit. + // + // NOTE: Circular data structures are properly detected, so it is not + // necessary to set this value unless you specifically want to limit deeply + // nested data structures. + MaxDepth int + + // DisableMethods specifies whether or not error and Stringer interfaces are + // invoked for types that implement them. + DisableMethods bool + + // DisablePointerMethods specifies whether or not to check for and invoke + // error and Stringer interfaces on types which only accept a pointer + // receiver when the current type is not a pointer. + // + // NOTE: This might be an unsafe action since calling one of these methods + // with a pointer receiver could technically mutate the value, however, + // in practice, types which choose to satisify an error or Stringer + // interface with a pointer receiver should not be mutating their state + // inside these interface methods. As a result, this option relies on + // access to the unsafe package, so it will not have any effect when + // running in environments without access to the unsafe package such as + // Google App Engine or with the "safe" build tag specified. + DisablePointerMethods bool + + // DisablePointerAddresses specifies whether to disable the printing of + // pointer addresses. This is useful when diffing data structures in tests. + DisablePointerAddresses bool + + // DisableCapacities specifies whether to disable the printing of capacities + // for arrays, slices, maps and channels. This is useful when diffing + // data structures in tests. + DisableCapacities bool + + // ContinueOnMethod specifies whether or not recursion should continue once + // a custom error or Stringer interface is invoked. The default, false, + // means it will print the results of invoking the custom error or Stringer + // interface and return immediately instead of continuing to recurse into + // the internals of the data type. + // + // NOTE: This flag does not have any effect if method invocation is disabled + // via the DisableMethods or DisablePointerMethods options. + ContinueOnMethod bool + + // SortKeys specifies map keys should be sorted before being printed. Use + // this to have a more deterministic, diffable output. Note that only + // native types (bool, int, uint, floats, uintptr and string) and types + // that support the error or Stringer interfaces (if methods are + // enabled) are supported, with other types sorted according to the + // reflect.Value.String() output which guarantees display stability. + SortKeys bool + + // SpewKeys specifies that, as a last resort attempt, map keys should + // be spewed to strings and sorted by those strings. This is only + // considered if SortKeys is true. + SpewKeys bool +} + +// Config is the active configuration of the top-level functions. +// The configuration can be changed by modifying the contents of spew.Config. +var Config = ConfigState{Indent: " "} + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprint(a ...interface{}) string { + return fmt.Sprint(c.convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, c.convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a Formatter interface returned by c.NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func (c *ConfigState) Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(c, &buf, a...) + return buf.String() +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +// ContinueOnMethod: false +// SortKeys: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go new file mode 100644 index 00000000000..aacaac6f1e1 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/doc.go @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package spew implements a deep pretty printer for Go data structures to aid in +debugging. + +A quick overview of the additional features spew provides over the built-in +printing facilities for Go data types are as follows: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output (only when using + Dump style) + +There are two different approaches spew allows for dumping Go data structures: + + * Dump style which prints with newlines, customizable indentation, + and additional debug information such as types and all pointer addresses + used to indirect to the final value + * A custom Formatter interface that integrates cleanly with the standard fmt + package and replaces %v, %+v, %#v, and %#+v to provide inline printing + similar to the default %v while providing the additional functionality + outlined above and passing unsupported format verbs such as %x and %q + along to fmt + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + spew.Dump(myVar1, myVar2, ...) + spew.Fdump(someWriter, myVar1, myVar2, ...) + str := spew.Sdump(myVar1, myVar2, ...) + +Alternatively, if you would prefer to use format strings with a compacted inline +printing style, use the convenience wrappers Printf, Fprintf, etc with +%v (most compact), %+v (adds pointer addresses), %#v (adds types), or +%#+v (adds types and pointer addresses): + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +Configuration Options + +Configuration of spew is handled by fields in the ConfigState type. For +convenience, all of the top-level functions use a global state available +via the spew.Config global. + +It is also possible to create a ConfigState instance that provides methods +equivalent to the top-level functions. This allows concurrent configuration +options. See the ConfigState documentation for more details. + +The following configuration options are available: + * Indent + String to use for each indentation level for Dump functions. + It is a single space by default. A popular alternative is "\t". + + * MaxDepth + Maximum number of levels to descend into nested data structures. + There is no limit by default. + + * DisableMethods + Disables invocation of error and Stringer interface methods. + Method invocation is enabled by default. + + * DisablePointerMethods + Disables invocation of error and Stringer interface methods on types + which only accept pointer receivers from non-pointer variables. + Pointer method invocation is enabled by default. + + * DisablePointerAddresses + DisablePointerAddresses specifies whether to disable the printing of + pointer addresses. This is useful when diffing data structures in tests. + + * DisableCapacities + DisableCapacities specifies whether to disable the printing of + capacities for arrays, slices, maps and channels. This is useful when + diffing data structures in tests. + + * ContinueOnMethod + Enables recursion into types after invoking error and Stringer interface + methods. Recursion after method invocation is disabled by default. + + * SortKeys + Specifies map keys should be sorted before being printed. Use + this to have a more deterministic, diffable output. Note that + only native types (bool, int, uint, floats, uintptr and string) + and types which implement error or Stringer interfaces are + supported with other types sorted according to the + reflect.Value.String() output which guarantees display + stability. Natural map order is used by default. + + * SpewKeys + Specifies that, as a last resort attempt, map keys should be + spewed to strings and sorted by those strings. This is only + considered if SortKeys is true. + +Dump Usage + +Simply call spew.Dump with a list of variables you want to dump: + + spew.Dump(myVar1, myVar2, ...) + +You may also call spew.Fdump if you would prefer to output to an arbitrary +io.Writer. For example, to dump to standard error: + + spew.Fdump(os.Stderr, myVar1, myVar2, ...) + +A third option is to call spew.Sdump to get the formatted output as a string: + + str := spew.Sdump(myVar1, myVar2, ...) + +Sample Dump Output + +See the Dump example for details on the setup of the types and variables being +shown here. + + (main.Foo) { + unexportedField: (*main.Bar)(0xf84002e210)({ + flag: (main.Flag) flagTwo, + data: (uintptr) + }), + ExportedField: (map[interface {}]interface {}) (len=1) { + (string) (len=3) "one": (bool) true + } + } + +Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C +command as shown. + ([]uint8) (len=32 cap=32) { + 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + 00000020 31 32 |12| + } + +Custom Formatter + +Spew provides a custom formatter that implements the fmt.Formatter interface +so that it integrates cleanly with standard fmt package printing functions. The +formatter is useful for inline printing of smaller data types similar to the +standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Custom Formatter Usage + +The simplest way to make use of the spew custom formatter is to call one of the +convenience functions such as spew.Printf, spew.Println, or spew.Printf. The +functions have syntax you are most likely already familiar with: + + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Println(myVar, myVar2) + spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +See the Index for the full list convenience functions. + +Sample Formatter Output + +Double pointer to a uint8: + %v: <**>5 + %+v: <**>(0xf8400420d0->0xf8400420c8)5 + %#v: (**uint8)5 + %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 + +Pointer to circular struct with a uint8 field and a pointer to itself: + %v: <*>{1 <*>} + %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} + %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} + %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} + +See the Printf example for details on the setup of variables being shown +here. + +Errors + +Since it is possible for custom Stringer/error interfaces to panic, spew +detects them and handles them internally by printing the panic information +inline with the output. Since spew is intended to provide deep pretty printing +capabilities on structures, it intentionally does not return any errors. +*/ +package spew diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go similarity index 99% rename from vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/dump.go rename to vendor/github.com/davecgh/go-spew/spew/dump.go index 95f9dbfe50b..df1d582a728 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/dump.go +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Dave Collins + * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go similarity index 99% rename from vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/format.go rename to vendor/github.com/davecgh/go-spew/spew/format.go index ecf3b80e24b..c49875bacbb 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/format.go +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Dave Collins + * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go similarity index 99% rename from vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/spew.go rename to vendor/github.com/davecgh/go-spew/spew/spew.go index d8233f542e1..32c0e338825 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew/spew.go +++ b/vendor/github.com/davecgh/go-spew/spew/spew.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Dave Collins + * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/vendor/github.com/edsrzf/mmap-go/.gitignore b/vendor/github.com/edsrzf/mmap-go/.gitignore new file mode 100644 index 00000000000..9aa02c1ed3d --- /dev/null +++ b/vendor/github.com/edsrzf/mmap-go/.gitignore @@ -0,0 +1,8 @@ +*.out +*.5 +*.6 +*.8 +*.swp +_obj +_test +testdata diff --git a/vendor/github.com/edsrzf/mmap-go/mmap.go b/vendor/github.com/edsrzf/mmap-go/mmap.go index 14fb22580a8..7bb4965ed52 100644 --- a/vendor/github.com/edsrzf/mmap-go/mmap.go +++ b/vendor/github.com/edsrzf/mmap-go/mmap.go @@ -54,10 +54,6 @@ func Map(f *os.File, prot, flags int) (MMap, error) { // If length < 0, the entire file will be mapped. // If ANON is set in flags, f is ignored. func MapRegion(f *os.File, length int, prot, flags int, offset int64) (MMap, error) { - if offset%int64(os.Getpagesize()) != 0 { - return nil, errors.New("offset parameter must be a multiple of the system's page size") - } - var fd uintptr if flags&ANON == 0 { fd = uintptr(f.Fd()) diff --git a/vendor/github.com/ethereum/go-ethereum/build/ci-notes.md b/vendor/github.com/ethereum/go-ethereum/build/ci-notes.md new file mode 100644 index 00000000000..78e9575c010 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/ci-notes.md @@ -0,0 +1,49 @@ +# Debian Packaging + +Tagged releases and develop branch commits are available as installable Debian packages +for Ubuntu. Packages are built for the all Ubuntu versions which are supported by +Canonical: + +- Trusty Tahr (14.04 LTS) +- Xenial Xerus (16.04 LTS) +- Yakkety Yak (16.10) +- Zesty Zapus (17.04) + +Packages of develop branch commits have suffix -unstable and cannot be installed alongside +the stable version. Switching between release streams requires user intervention. + +The packages are built and served by launchpad.net. We generate a Debian source package +for each distribution and upload it. Their builder picks up the source package, builds it +and installs the new version into the PPA repository. Launchpad requires a valid signature +by a team member for source package uploads. The signing key is stored in an environment +variable which Travis CI makes available to certain builds. + +We want to build go-ethereum with the most recent version of Go, irrespective of the Go +version that is available in the main Ubuntu repository. In order to make this possible, +our PPA depends on the ~gophers/ubuntu/archive PPA. Our source package build-depends on +golang-1.9, which is co-installable alongside the regular golang package. PPA dependencies +can be edited at https://launchpad.net/%7Eethereum/+archive/ubuntu/ethereum/+edit-dependencies + +## Building Packages Locally (for testing) + +You need to run Ubuntu to do test packaging. + +Add the gophers PPA and install Go 1.9 and Debian packaging tools: + + $ sudo apt-add-repository ppa:gophers/ubuntu/archive + $ sudo apt-get update + $ sudo apt-get install build-essential golang-1.9 devscripts debhelper + +Create the source packages: + + $ go run build/ci.go debsrc -workdir dist + +Then go into the source package directory for your running distribution and build the package: + + $ cd dist/ethereum-unstable-1.6.0+xenial + $ dpkg-buildpackage + +Built packages are placed in the dist/ directory. + + $ cd .. + $ dpkg-deb -c geth-unstable_1.6.0+xenial_amd64.deb diff --git a/vendor/github.com/ethereum/go-ethereum/build/ci.go b/vendor/github.com/ethereum/go-ethereum/build/ci.go new file mode 100644 index 00000000000..0c825ef31e6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/ci.go @@ -0,0 +1,1024 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build none + +/* +The ci command is called from Continuous Integration scripts. + +Usage: go run ci.go + +Available commands are: + + install [ -arch architecture ] [ packages... ] -- builds packages and executables + test [ -coverage ] [ packages... ] -- runs the tests + lint -- runs certain pre-selected linters + archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts + importkeys -- imports signing keys from env + debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package + nsis -- creates a Windows NSIS installer + aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive + xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework + xgo [ -alltools ] [ options ] -- cross builds according to options + purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore + +For all commands, -n prevents execution of external programs (dry run mode). + +*/ +package main + +import ( + "bufio" + "bytes" + "encoding/base64" + "flag" + "fmt" + "go/parser" + "go/token" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + "time" + + "github.com/ethereum/go-ethereum/internal/build" +) + +var ( + // Files that end up in the geth*.zip archive. + gethArchiveFiles = []string{ + "COPYING", + executablePath("geth"), + } + + // Files that end up in the geth-alltools*.zip archive. + allToolsArchiveFiles = []string{ + "COPYING", + executablePath("abigen"), + executablePath("bootnode"), + executablePath("evm"), + executablePath("geth"), + executablePath("puppeth"), + executablePath("rlpdump"), + executablePath("swarm"), + executablePath("wnode"), + } + + // A debian package is created for all executables listed here. + debExecutables = []debExecutable{ + { + Name: "abigen", + Description: "Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages.", + }, + { + Name: "bootnode", + Description: "Ethereum bootnode.", + }, + { + Name: "evm", + Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.", + }, + { + Name: "geth", + Description: "Ethereum CLI client.", + }, + { + Name: "puppeth", + Description: "Ethereum private network manager.", + }, + { + Name: "rlpdump", + Description: "Developer utility tool that prints RLP structures.", + }, + { + Name: "swarm", + Description: "Ethereum Swarm daemon and tools", + }, + { + Name: "wnode", + Description: "Ethereum Whisper diagnostic tool", + }, + } + + // Distros for which packages are created. + // Note: vivid is unsupported because there is no golang-1.6 package for it. + // Note: wily is unsupported because it was officially deprecated on lanchpad. + // Note: yakkety is unsupported because it was officially deprecated on lanchpad. + debDistros = []string{"trusty", "xenial", "zesty", "artful"} +) + +var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) + +func executablePath(name string) string { + if runtime.GOOS == "windows" { + name += ".exe" + } + return filepath.Join(GOBIN, name) +} + +func main() { + log.SetFlags(log.Lshortfile) + + if _, err := os.Stat(filepath.Join("build", "ci.go")); os.IsNotExist(err) { + log.Fatal("this script must be run from the root of the repository") + } + if len(os.Args) < 2 { + log.Fatal("need subcommand as first argument") + } + switch os.Args[1] { + case "install": + doInstall(os.Args[2:]) + case "test": + doTest(os.Args[2:]) + case "lint": + doLint(os.Args[2:]) + case "archive": + doArchive(os.Args[2:]) + case "debsrc": + doDebianSource(os.Args[2:]) + case "nsis": + doWindowsInstaller(os.Args[2:]) + case "aar": + doAndroidArchive(os.Args[2:]) + case "xcode": + doXCodeFramework(os.Args[2:]) + case "xgo": + doXgo(os.Args[2:]) + case "purge": + doPurge(os.Args[2:]) + default: + log.Fatal("unknown command ", os.Args[1]) + } +} + +// Compiling + +func doInstall(cmdline []string) { + var ( + arch = flag.String("arch", "", "Architecture to cross build for") + ) + flag.CommandLine.Parse(cmdline) + env := build.Env() + + // Check Go version. People regularly open issues about compilation + // failure with outdated Go. This should save them the trouble. + if runtime.Version() < "go1.7" && !strings.Contains(runtime.Version(), "devel") { + log.Println("You have Go version", runtime.Version()) + log.Println("go-ethereum requires at least Go version 1.7 and cannot") + log.Println("be compiled with an earlier version. Please upgrade your Go installation.") + os.Exit(1) + } + // Compile packages given as arguments, or everything if there are no arguments. + packages := []string{"./..."} + if flag.NArg() > 0 { + packages = flag.Args() + } + packages = build.ExpandPackagesNoVendor(packages) + + if *arch == "" || *arch == runtime.GOARCH { + goinstall := goTool("install", buildFlags(env)...) + goinstall.Args = append(goinstall.Args, "-v") + goinstall.Args = append(goinstall.Args, packages...) + build.MustRun(goinstall) + return + } + // If we are cross compiling to ARMv5 ARMv6 or ARMv7, clean any prvious builds + if *arch == "arm" { + os.RemoveAll(filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_arm")) + for _, path := range filepath.SplitList(build.GOPATH()) { + os.RemoveAll(filepath.Join(path, "pkg", runtime.GOOS+"_arm")) + } + } + // Seems we are cross compiling, work around forbidden GOBIN + goinstall := goToolArch(*arch, "install", buildFlags(env)...) + goinstall.Args = append(goinstall.Args, "-v") + goinstall.Args = append(goinstall.Args, []string{"-buildmode", "archive"}...) + goinstall.Args = append(goinstall.Args, packages...) + build.MustRun(goinstall) + + if cmds, err := ioutil.ReadDir("cmd"); err == nil { + for _, cmd := range cmds { + pkgs, err := parser.ParseDir(token.NewFileSet(), filepath.Join(".", "cmd", cmd.Name()), nil, parser.PackageClauseOnly) + if err != nil { + log.Fatal(err) + } + for name := range pkgs { + if name == "main" { + gobuild := goToolArch(*arch, "build", buildFlags(env)...) + gobuild.Args = append(gobuild.Args, "-v") + gobuild.Args = append(gobuild.Args, []string{"-o", executablePath(cmd.Name())}...) + gobuild.Args = append(gobuild.Args, "."+string(filepath.Separator)+filepath.Join("cmd", cmd.Name())) + build.MustRun(gobuild) + break + } + } + } + } +} + +func buildFlags(env build.Environment) (flags []string) { + var ld []string + if env.Commit != "" { + ld = append(ld, "-X", "main.gitCommit="+env.Commit) + } + if runtime.GOOS == "darwin" { + ld = append(ld, "-s") + } + + if len(ld) > 0 { + flags = append(flags, "-ldflags", strings.Join(ld, " ")) + } + return flags +} + +func goTool(subcmd string, args ...string) *exec.Cmd { + return goToolArch(runtime.GOARCH, subcmd, args...) +} + +func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd { + cmd := build.GoTool(subcmd, args...) + if subcmd == "build" || subcmd == "install" || subcmd == "test" { + // Go CGO has a Windows linker error prior to 1.8 (https://github.com/golang/go/issues/8756). + // Work around issue by allowing multiple definitions for <1.8 builds. + if runtime.GOOS == "windows" && runtime.Version() < "go1.8" { + cmd.Args = append(cmd.Args, []string{"-ldflags", "-extldflags -Wl,--allow-multiple-definition"}...) + } + } + cmd.Env = []string{"GOPATH=" + build.GOPATH()} + if arch == "" || arch == runtime.GOARCH { + cmd.Env = append(cmd.Env, "GOBIN="+GOBIN) + } else { + cmd.Env = append(cmd.Env, "CGO_ENABLED=1") + cmd.Env = append(cmd.Env, "GOARCH="+arch) + } + for _, e := range os.Environ() { + if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") { + continue + } + cmd.Env = append(cmd.Env, e) + } + return cmd +} + +// Running The Tests +// +// "tests" also includes static analysis tools such as vet. + +func doTest(cmdline []string) { + var ( + coverage = flag.Bool("coverage", false, "Whether to record code coverage") + ) + flag.CommandLine.Parse(cmdline) + env := build.Env() + + packages := []string{"./..."} + if len(flag.CommandLine.Args()) > 0 { + packages = flag.CommandLine.Args() + } + packages = build.ExpandPackagesNoVendor(packages) + + // Run analysis tools before the tests. + build.MustRun(goTool("vet", packages...)) + + // Run the actual tests. + gotest := goTool("test", buildFlags(env)...) + // Test a single package at a time. CI builders are slow + // and some tests run into timeouts under load. + gotest.Args = append(gotest.Args, "-p", "1") + if *coverage { + gotest.Args = append(gotest.Args, "-covermode=atomic", "-cover") + } + + gotest.Args = append(gotest.Args, packages...) + build.MustRun(gotest) +} + +// runs gometalinter on requested packages +func doLint(cmdline []string) { + flag.CommandLine.Parse(cmdline) + + packages := []string{"./..."} + if len(flag.CommandLine.Args()) > 0 { + packages = flag.CommandLine.Args() + } + // Get metalinter and install all supported linters + build.MustRun(goTool("get", "gopkg.in/alecthomas/gometalinter.v1")) + build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), "--install") + + // Run fast linters batched together + configs := []string{"--vendor", "--disable-all", "--enable=vet", "--enable=gofmt", "--enable=misspell"} + build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), append(configs, packages...)...) + + // Run slow linters one by one + for _, linter := range []string{"unconvert"} { + configs = []string{"--vendor", "--deadline=10m", "--disable-all", "--enable=" + linter} + build.MustRunCommand(filepath.Join(GOBIN, "gometalinter.v1"), append(configs, packages...)...) + } +} + +// Release Packaging + +func doArchive(cmdline []string) { + var ( + arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging") + atype = flag.String("type", "zip", "Type of archive to write (zip|tar)") + signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`) + upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) + ext string + ) + flag.CommandLine.Parse(cmdline) + switch *atype { + case "zip": + ext = ".zip" + case "tar": + ext = ".tar.gz" + default: + log.Fatal("unknown archive type: ", atype) + } + + var ( + env = build.Env() + base = archiveBasename(*arch, env) + geth = "geth-" + base + ext + alltools = "geth-alltools-" + base + ext + ) + maybeSkipArchive(env) + if err := build.WriteArchive(geth, gethArchiveFiles); err != nil { + log.Fatal(err) + } + if err := build.WriteArchive(alltools, allToolsArchiveFiles); err != nil { + log.Fatal(err) + } + for _, archive := range []string{geth, alltools} { + if err := archiveUpload(archive, *upload, *signer); err != nil { + log.Fatal(err) + } + } +} + +func archiveBasename(arch string, env build.Environment) string { + platform := runtime.GOOS + "-" + arch + if arch == "arm" { + platform += os.Getenv("GOARM") + } + if arch == "android" { + platform = "android-all" + } + if arch == "ios" { + platform = "ios-all" + } + return platform + "-" + archiveVersion(env) +} + +func archiveVersion(env build.Environment) string { + version := build.VERSION() + if isUnstableBuild(env) { + version += "-unstable" + } + if env.Commit != "" { + version += "-" + env.Commit[:8] + } + return version +} + +func archiveUpload(archive string, blobstore string, signer string) error { + // If signing was requested, generate the signature files + if signer != "" { + pgpkey, err := base64.StdEncoding.DecodeString(os.Getenv(signer)) + if err != nil { + return fmt.Errorf("invalid base64 %s", signer) + } + if err := build.PGPSignFile(archive, archive+".asc", string(pgpkey)); err != nil { + return err + } + } + // If uploading to Azure was requested, push the archive possibly with its signature + if blobstore != "" { + auth := build.AzureBlobstoreConfig{ + Account: strings.Split(blobstore, "/")[0], + Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"), + Container: strings.SplitN(blobstore, "/", 2)[1], + } + if err := build.AzureBlobstoreUpload(archive, filepath.Base(archive), auth); err != nil { + return err + } + if signer != "" { + if err := build.AzureBlobstoreUpload(archive+".asc", filepath.Base(archive+".asc"), auth); err != nil { + return err + } + } + } + return nil +} + +// skips archiving for some build configurations. +func maybeSkipArchive(env build.Environment) { + if env.IsPullRequest { + log.Printf("skipping because this is a PR build") + os.Exit(0) + } + if env.IsCronJob { + log.Printf("skipping because this is a cron job") + os.Exit(0) + } + if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") { + log.Printf("skipping because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag) + os.Exit(0) + } +} + +// Debian Packaging + +func doDebianSource(cmdline []string) { + var ( + signer = flag.String("signer", "", `Signing key name, also used as package author`) + upload = flag.String("upload", "", `Where to upload the source package (usually "ppa:ethereum/ethereum")`) + workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) + now = time.Now() + ) + flag.CommandLine.Parse(cmdline) + *workdir = makeWorkdir(*workdir) + env := build.Env() + maybeSkipArchive(env) + + // Import the signing key. + if b64key := os.Getenv("PPA_SIGNING_KEY"); b64key != "" { + key, err := base64.StdEncoding.DecodeString(b64key) + if err != nil { + log.Fatal("invalid base64 PPA_SIGNING_KEY") + } + gpg := exec.Command("gpg", "--import") + gpg.Stdin = bytes.NewReader(key) + build.MustRun(gpg) + } + + // Create the packages. + for _, distro := range debDistros { + meta := newDebMetadata(distro, *signer, env, now) + pkgdir := stageDebianSource(*workdir, meta) + debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc") + debuild.Dir = pkgdir + build.MustRun(debuild) + + changes := fmt.Sprintf("%s_%s_source.changes", meta.Name(), meta.VersionString()) + changes = filepath.Join(*workdir, changes) + if *signer != "" { + build.MustRunCommand("debsign", changes) + } + if *upload != "" { + build.MustRunCommand("dput", *upload, changes) + } + } +} + +func makeWorkdir(wdflag string) string { + var err error + if wdflag != "" { + err = os.MkdirAll(wdflag, 0744) + } else { + wdflag, err = ioutil.TempDir("", "geth-build-") + } + if err != nil { + log.Fatal(err) + } + return wdflag +} + +func isUnstableBuild(env build.Environment) bool { + if env.Tag != "" { + return false + } + return true +} + +type debMetadata struct { + Env build.Environment + + // go-ethereum version being built. Note that this + // is not the debian package version. The package version + // is constructed by VersionString. + Version string + + Author string // "name ", also selects signing key + Distro, Time string + Executables []debExecutable +} + +type debExecutable struct { + Name, Description string +} + +func newDebMetadata(distro, author string, env build.Environment, t time.Time) debMetadata { + if author == "" { + // No signing key, use default author. + author = "Ethereum Builds " + } + return debMetadata{ + Env: env, + Author: author, + Distro: distro, + Version: build.VERSION(), + Time: t.Format(time.RFC1123Z), + Executables: debExecutables, + } +} + +// Name returns the name of the metapackage that depends +// on all executable packages. +func (meta debMetadata) Name() string { + if isUnstableBuild(meta.Env) { + return "ethereum-unstable" + } + return "ethereum" +} + +// VersionString returns the debian version of the packages. +func (meta debMetadata) VersionString() string { + vsn := meta.Version + if meta.Env.Buildnum != "" { + vsn += "+build" + meta.Env.Buildnum + } + if meta.Distro != "" { + vsn += "+" + meta.Distro + } + return vsn +} + +// ExeList returns the list of all executable packages. +func (meta debMetadata) ExeList() string { + names := make([]string, len(meta.Executables)) + for i, e := range meta.Executables { + names[i] = meta.ExeName(e) + } + return strings.Join(names, ", ") +} + +// ExeName returns the package name of an executable package. +func (meta debMetadata) ExeName(exe debExecutable) string { + if isUnstableBuild(meta.Env) { + return exe.Name + "-unstable" + } + return exe.Name +} + +// ExeConflicts returns the content of the Conflicts field +// for executable packages. +func (meta debMetadata) ExeConflicts(exe debExecutable) string { + if isUnstableBuild(meta.Env) { + // Set up the conflicts list so that the *-unstable packages + // cannot be installed alongside the regular version. + // + // https://www.debian.org/doc/debian-policy/ch-relationships.html + // is very explicit about Conflicts: and says that Breaks: should + // be preferred and the conflicting files should be handled via + // alternates. We might do this eventually but using a conflict is + // easier now. + return "ethereum, " + exe.Name + } + return "" +} + +func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) { + pkg := meta.Name() + "-" + meta.VersionString() + pkgdir = filepath.Join(tmpdir, pkg) + if err := os.Mkdir(pkgdir, 0755); err != nil { + log.Fatal(err) + } + + // Copy the source code. + build.MustRunCommand("git", "checkout-index", "-a", "--prefix", pkgdir+string(filepath.Separator)) + + // Put the debian build files in place. + debian := filepath.Join(pkgdir, "debian") + build.Render("build/deb.rules", filepath.Join(debian, "rules"), 0755, meta) + build.Render("build/deb.changelog", filepath.Join(debian, "changelog"), 0644, meta) + build.Render("build/deb.control", filepath.Join(debian, "control"), 0644, meta) + build.Render("build/deb.copyright", filepath.Join(debian, "copyright"), 0644, meta) + build.RenderString("8\n", filepath.Join(debian, "compat"), 0644, meta) + build.RenderString("3.0 (native)\n", filepath.Join(debian, "source/format"), 0644, meta) + for _, exe := range meta.Executables { + install := filepath.Join(debian, meta.ExeName(exe)+".install") + docs := filepath.Join(debian, meta.ExeName(exe)+".docs") + build.Render("build/deb.install", install, 0644, exe) + build.Render("build/deb.docs", docs, 0644, exe) + } + + return pkgdir +} + +// Windows installer + +func doWindowsInstaller(cmdline []string) { + // Parse the flags and make skip installer generation on PRs + var ( + arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging") + signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`) + upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) + workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) + ) + flag.CommandLine.Parse(cmdline) + *workdir = makeWorkdir(*workdir) + env := build.Env() + maybeSkipArchive(env) + + // Aggregate binaries that are included in the installer + var ( + devTools []string + allTools []string + gethTool string + ) + for _, file := range allToolsArchiveFiles { + if file == "COPYING" { // license, copied later + continue + } + allTools = append(allTools, filepath.Base(file)) + if filepath.Base(file) == "geth.exe" { + gethTool = file + } else { + devTools = append(devTools, file) + } + } + + // Render NSIS scripts: Installer NSIS contains two installer sections, + // first section contains the geth binary, second section holds the dev tools. + templateData := map[string]interface{}{ + "License": "COPYING", + "Geth": gethTool, + "DevTools": devTools, + } + build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil) + build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData) + build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools) + build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil) + build.Render("build/nsis.envvarupdate.nsh", filepath.Join(*workdir, "EnvVarUpdate.nsh"), 0644, nil) + build.CopyFile(filepath.Join(*workdir, "SimpleFC.dll"), "build/nsis.simplefc.dll", 0755) + build.CopyFile(filepath.Join(*workdir, "COPYING"), "COPYING", 0755) + + // Build the installer. This assumes that all the needed files have been previously + // built (don't mix building and packaging to keep cross compilation complexity to a + // minimum). + version := strings.Split(build.VERSION(), ".") + if env.Commit != "" { + version[2] += "-" + env.Commit[:8] + } + installer, _ := filepath.Abs("geth-" + archiveBasename(*arch, env) + ".exe") + build.MustRunCommand("makensis.exe", + "/DOUTPUTFILE="+installer, + "/DMAJORVERSION="+version[0], + "/DMINORVERSION="+version[1], + "/DBUILDVERSION="+version[2], + "/DARCH="+*arch, + filepath.Join(*workdir, "geth.nsi"), + ) + + // Sign and publish installer. + if err := archiveUpload(installer, *upload, *signer); err != nil { + log.Fatal(err) + } +} + +// Android archives + +func doAndroidArchive(cmdline []string) { + var ( + local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`) + signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`) + deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`) + upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`) + ) + flag.CommandLine.Parse(cmdline) + env := build.Env() + + // Sanity check that the SDK and NDK are installed and set + if os.Getenv("ANDROID_HOME") == "" { + log.Fatal("Please ensure ANDROID_HOME points to your Android SDK") + } + if os.Getenv("ANDROID_NDK") == "" { + log.Fatal("Please ensure ANDROID_NDK points to your Android NDK") + } + // Build the Android archive and Maven resources + build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile")) + build.MustRun(gomobileTool("init", "--ndk", os.Getenv("ANDROID_NDK"))) + build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile")) + + if *local { + // If we're building locally, copy bundle to build dir and skip Maven + os.Rename("geth.aar", filepath.Join(GOBIN, "geth.aar")) + return + } + meta := newMavenMetadata(env) + build.Render("build/mvn.pom", meta.Package+".pom", 0755, meta) + + // Skip Maven deploy and Azure upload for PR builds + maybeSkipArchive(env) + + // Sign and upload the archive to Azure + archive := "geth-" + archiveBasename("android", env) + ".aar" + os.Rename("geth.aar", archive) + + if err := archiveUpload(archive, *upload, *signer); err != nil { + log.Fatal(err) + } + // Sign and upload all the artifacts to Maven Central + os.Rename(archive, meta.Package+".aar") + if *signer != "" && *deploy != "" { + // Import the signing key into the local GPG instance + if b64key := os.Getenv(*signer); b64key != "" { + key, err := base64.StdEncoding.DecodeString(b64key) + if err != nil { + log.Fatalf("invalid base64 %s", *signer) + } + gpg := exec.Command("gpg", "--import") + gpg.Stdin = bytes.NewReader(key) + build.MustRun(gpg) + } + // Upload the artifacts to Sonatype and/or Maven Central + repo := *deploy + "/service/local/staging/deploy/maven2" + if meta.Develop { + repo = *deploy + "/content/repositories/snapshots" + } + build.MustRunCommand("mvn", "gpg:sign-and-deploy-file", + "-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh", + "-DpomFile="+meta.Package+".pom", "-Dfile="+meta.Package+".aar") + } +} + +func gomobileTool(subcmd string, args ...string) *exec.Cmd { + cmd := exec.Command(filepath.Join(GOBIN, "gomobile"), subcmd) + cmd.Args = append(cmd.Args, args...) + cmd.Env = []string{ + "GOPATH=" + build.GOPATH(), + } + for _, e := range os.Environ() { + if strings.HasPrefix(e, "GOPATH=") { + continue + } + cmd.Env = append(cmd.Env, e) + } + return cmd +} + +type mavenMetadata struct { + Version string + Package string + Develop bool + Contributors []mavenContributor +} + +type mavenContributor struct { + Name string + Email string +} + +func newMavenMetadata(env build.Environment) mavenMetadata { + // Collect the list of authors from the repo root + contribs := []mavenContributor{} + if authors, err := os.Open("AUTHORS"); err == nil { + defer authors.Close() + + scanner := bufio.NewScanner(authors) + for scanner.Scan() { + // Skip any whitespace from the authors list + line := strings.TrimSpace(scanner.Text()) + if line == "" || line[0] == '#' { + continue + } + // Split the author and insert as a contributor + re := regexp.MustCompile("([^<]+) <(.+)>") + parts := re.FindStringSubmatch(line) + if len(parts) == 3 { + contribs = append(contribs, mavenContributor{Name: parts[1], Email: parts[2]}) + } + } + } + // Render the version and package strings + version := build.VERSION() + if isUnstableBuild(env) { + version += "-SNAPSHOT" + } + return mavenMetadata{ + Version: version, + Package: "geth-" + version, + Develop: isUnstableBuild(env), + Contributors: contribs, + } +} + +// XCode frameworks + +func doXCodeFramework(cmdline []string) { + var ( + local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`) + signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`) + deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`) + upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) + ) + flag.CommandLine.Parse(cmdline) + env := build.Env() + + // Build the iOS XCode framework + build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile")) + build.MustRun(gomobileTool("init")) + bind := gomobileTool("bind", "--target", "ios", "--tags", "ios", "-v", "github.com/ethereum/go-ethereum/mobile") + + if *local { + // If we're building locally, use the build folder and stop afterwards + bind.Dir, _ = filepath.Abs(GOBIN) + build.MustRun(bind) + return + } + archive := "geth-" + archiveBasename("ios", env) + if err := os.Mkdir(archive, os.ModePerm); err != nil { + log.Fatal(err) + } + bind.Dir, _ = filepath.Abs(archive) + build.MustRun(bind) + build.MustRunCommand("tar", "-zcvf", archive+".tar.gz", archive) + + // Skip CocoaPods deploy and Azure upload for PR builds + maybeSkipArchive(env) + + // Sign and upload the framework to Azure + if err := archiveUpload(archive+".tar.gz", *upload, *signer); err != nil { + log.Fatal(err) + } + // Prepare and upload a PodSpec to CocoaPods + if *deploy != "" { + meta := newPodMetadata(env, archive) + build.Render("build/pod.podspec", "Geth.podspec", 0755, meta) + build.MustRunCommand("pod", *deploy, "push", "Geth.podspec", "--allow-warnings", "--verbose") + } +} + +type podMetadata struct { + Version string + Commit string + Archive string + Contributors []podContributor +} + +type podContributor struct { + Name string + Email string +} + +func newPodMetadata(env build.Environment, archive string) podMetadata { + // Collect the list of authors from the repo root + contribs := []podContributor{} + if authors, err := os.Open("AUTHORS"); err == nil { + defer authors.Close() + + scanner := bufio.NewScanner(authors) + for scanner.Scan() { + // Skip any whitespace from the authors list + line := strings.TrimSpace(scanner.Text()) + if line == "" || line[0] == '#' { + continue + } + // Split the author and insert as a contributor + re := regexp.MustCompile("([^<]+) <(.+)>") + parts := re.FindStringSubmatch(line) + if len(parts) == 3 { + contribs = append(contribs, podContributor{Name: parts[1], Email: parts[2]}) + } + } + } + version := build.VERSION() + if isUnstableBuild(env) { + version += "-unstable." + env.Buildnum + } + return podMetadata{ + Archive: archive, + Version: version, + Commit: env.Commit, + Contributors: contribs, + } +} + +// Cross compilation + +func doXgo(cmdline []string) { + var ( + alltools = flag.Bool("alltools", false, `Flag whether we're building all known tools, or only on in particular`) + ) + flag.CommandLine.Parse(cmdline) + env := build.Env() + + // Make sure xgo is available for cross compilation + gogetxgo := goTool("get", "github.com/karalabe/xgo") + build.MustRun(gogetxgo) + + // If all tools building is requested, build everything the builder wants + args := append(buildFlags(env), flag.Args()...) + + if *alltools { + args = append(args, []string{"--dest", GOBIN}...) + for _, res := range allToolsArchiveFiles { + if strings.HasPrefix(res, GOBIN) { + // Binary tool found, cross build it explicitly + args = append(args, "./"+filepath.Join("cmd", filepath.Base(res))) + xgo := xgoTool(args) + build.MustRun(xgo) + args = args[:len(args)-1] + } + } + return + } + // Otherwise xxecute the explicit cross compilation + path := args[len(args)-1] + args = append(args[:len(args)-1], []string{"--dest", GOBIN, path}...) + + xgo := xgoTool(args) + build.MustRun(xgo) +} + +func xgoTool(args []string) *exec.Cmd { + cmd := exec.Command(filepath.Join(GOBIN, "xgo"), args...) + cmd.Env = []string{ + "GOPATH=" + build.GOPATH(), + "GOBIN=" + GOBIN, + } + for _, e := range os.Environ() { + if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") { + continue + } + cmd.Env = append(cmd.Env, e) + } + return cmd +} + +// Binary distribution cleanups + +func doPurge(cmdline []string) { + var ( + store = flag.String("store", "", `Destination from where to purge archives (usually "gethstore/builds")`) + limit = flag.Int("days", 30, `Age threshold above which to delete unstalbe archives`) + ) + flag.CommandLine.Parse(cmdline) + + if env := build.Env(); !env.IsCronJob { + log.Printf("skipping because not a cron job") + os.Exit(0) + } + // Create the azure authentication and list the current archives + auth := build.AzureBlobstoreConfig{ + Account: strings.Split(*store, "/")[0], + Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"), + Container: strings.SplitN(*store, "/", 2)[1], + } + blobs, err := build.AzureBlobstoreList(auth) + if err != nil { + log.Fatal(err) + } + // Iterate over the blobs, collect and sort all unstable builds + for i := 0; i < len(blobs); i++ { + if !strings.Contains(blobs[i].Name, "unstable") { + blobs = append(blobs[:i], blobs[i+1:]...) + i-- + } + } + for i := 0; i < len(blobs); i++ { + for j := i + 1; j < len(blobs); j++ { + iTime, err := time.Parse(time.RFC1123, blobs[i].Properties.LastModified) + if err != nil { + log.Fatal(err) + } + jTime, err := time.Parse(time.RFC1123, blobs[j].Properties.LastModified) + if err != nil { + log.Fatal(err) + } + if iTime.After(jTime) { + blobs[i], blobs[j] = blobs[j], blobs[i] + } + } + } + // Filter out all archives more recent that the given threshold + for i, blob := range blobs { + timestamp, _ := time.Parse(time.RFC1123, blob.Properties.LastModified) + if time.Since(timestamp) < time.Duration(*limit)*24*time.Hour { + blobs = blobs[:i] + break + } + } + // Delete all marked as such and return + if err := build.AzureBlobstoreDelete(auth, blobs); err != nil { + log.Fatal(err) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/build/deb.changelog b/vendor/github.com/ethereum/go-ethereum/build/deb.changelog new file mode 100644 index 00000000000..83f804a8338 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/deb.changelog @@ -0,0 +1,5 @@ +{{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low + + * git build of {{.Env.Commit}} + + -- {{.Author}} {{.Time}} diff --git a/vendor/github.com/ethereum/go-ethereum/build/deb.control b/vendor/github.com/ethereum/go-ethereum/build/deb.control new file mode 100644 index 00000000000..5c9ce6705c2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/deb.control @@ -0,0 +1,25 @@ +Source: {{.Name}} +Section: science +Priority: extra +Maintainer: {{.Author}} +Build-Depends: debhelper (>= 8.0.0), golang-1.9 +Standards-Version: 3.9.5 +Homepage: https://ethereum.org +Vcs-Git: git://github.com/ethereum/go-ethereum.git +Vcs-Browser: https://github.com/ethereum/go-ethereum + +Package: {{.Name}} +Architecture: any +Depends: ${misc:Depends}, {{.ExeList}} +Description: Meta-package to install geth and other tools + Meta-package to install geth and other tools + +{{range .Executables}} +Package: {{$.ExeName .}} +Conflicts: {{$.ExeConflicts .}} +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Built-Using: ${misc:Built-Using} +Description: {{.Description}} + {{.Description}} +{{end}} diff --git a/vendor/github.com/ethereum/go-ethereum/build/deb.copyright b/vendor/github.com/ethereum/go-ethereum/build/deb.copyright new file mode 100644 index 00000000000..513be45b193 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/deb.copyright @@ -0,0 +1,14 @@ +Copyright 2016 The go-ethereum Authors + +go-ethereum is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +go-ethereum is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with go-ethereum. If not, see . diff --git a/vendor/github.com/ethereum/go-ethereum/build/deb.docs b/vendor/github.com/ethereum/go-ethereum/build/deb.docs new file mode 100644 index 00000000000..62deb04972d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/deb.docs @@ -0,0 +1 @@ +AUTHORS diff --git a/vendor/github.com/ethereum/go-ethereum/build/deb.install b/vendor/github.com/ethereum/go-ethereum/build/deb.install new file mode 100644 index 00000000000..7dc76e1f567 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/deb.install @@ -0,0 +1 @@ +build/bin/{{.Name}} usr/bin diff --git a/vendor/github.com/ethereum/go-ethereum/build/deb.rules b/vendor/github.com/ethereum/go-ethereum/build/deb.rules new file mode 100644 index 00000000000..7a785251397 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/deb.rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +override_dh_auto_build: + build/env.sh /usr/lib/go-1.9/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}} + +override_dh_auto_test: + +%: + dh $@ diff --git a/vendor/github.com/ethereum/go-ethereum/build/env.sh b/vendor/github.com/ethereum/go-ethereum/build/env.sh new file mode 100755 index 00000000000..3914555d1bb --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/env.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +set -e + +if [ ! -f "build/env.sh" ]; then + echo "$0 must be run from the root of the repository." + exit 2 +fi + +# Create fake Go workspace if it doesn't exist yet. +workspace="$PWD/build/_workspace" +root="$PWD" +ethdir="$workspace/src/github.com/ethereum" +if [ ! -L "$ethdir/go-ethereum" ]; then + mkdir -p "$ethdir" + cd "$ethdir" + ln -s ../../../../../. go-ethereum + cd "$root" +fi + +# Set up the environment to use the workspace. +GOPATH="$workspace" +export GOPATH + +# Run the command inside the workspace. +cd "$ethdir/go-ethereum" +PWD="$ethdir/go-ethereum" + +# Launch the arguments with the configured environment. +exec "$@" diff --git a/vendor/github.com/ethereum/go-ethereum/build/mvn.pom b/vendor/github.com/ethereum/go-ethereum/build/mvn.pom new file mode 100644 index 00000000000..7670246ba9f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/mvn.pom @@ -0,0 +1,57 @@ + + 4.0.0 + + org.ethereum + geth + {{.Version}} + aar + + Android Ethereum Client + Android port of the go-ethereum libraries and node + https://github.com/ethereum/go-ethereum + 2015 + + + + GNU Lesser General Public License, Version 3.0 + https://www.gnu.org/licenses/lgpl-3.0.en.html + repo + + + + + Ethereum + https://ethereum.org + + + + + karalabe + Péter Szilágyi + peterke@gmail.com + https://github.com/karalabe + + https://www.gravatar.com/avatar/2ecbf0f5b4b79eebf8c193e5d324357f?s=256 + + + + + {{range .Contributors}} + + {{.Name}} + {{.Email}} + {{end}} + + + + GitHub Issues + https://github.com/ethereum/go-ethereum/issues/ + + + + https://github.com/ethereum/go-ethereum + + diff --git a/vendor/github.com/ethereum/go-ethereum/build/mvn.settings b/vendor/github.com/ethereum/go-ethereum/build/mvn.settings new file mode 100644 index 00000000000..406b409b9b5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/mvn.settings @@ -0,0 +1,24 @@ + + + + ossrh + ${env.ANDROID_SONATYPE_USERNAME} + ${env.ANDROID_SONATYPE_PASSWORD} + + + + + ossrh + + true + + + gpg + + + + + diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.envvarupdate.nsh b/vendor/github.com/ethereum/go-ethereum/build/nsis.envvarupdate.nsh new file mode 100644 index 00000000000..9c3ecbe3372 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/nsis.envvarupdate.nsh @@ -0,0 +1,327 @@ +/** + * EnvVarUpdate.nsh + * : Environmental Variables: append, prepend, and remove entries + * + * WARNING: If you use StrFunc.nsh header then include it before this file + * with all required definitions. This is to avoid conflicts + * + * Usage: + * ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString" + * + * Credits: + * Version 1.0 + * * Cal Turney (turnec2) + * * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this + * function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, + * WriteEnvStr, and un.DeleteEnvStr + * * Diego Pedroso (deguix) for StrTok + * * Kevin English (kenglish_hi) for StrContains + * * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry + * (dandaman32) for StrReplace + * + * Version 1.1 (compatibility with StrFunc.nsh) + * * techtonik + * + * http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries + * + */ + + +!ifndef ENVVARUPDATE_FUNCTION +!define ENVVARUPDATE_FUNCTION +!verbose push +!verbose 3 +!include "LogicLib.nsh" +!include "WinMessages.NSH" +!include "StrFunc.nsh" + +; ---- Fix for conflict if StrFunc.nsh is already includes in main file ----------------------- +!macro _IncludeStrFunction StrFuncName + !ifndef ${StrFuncName}_INCLUDED + ${${StrFuncName}} + !endif + !ifndef Un${StrFuncName}_INCLUDED + ${Un${StrFuncName}} + !endif + !define un.${StrFuncName} "${Un${StrFuncName}}" +!macroend + +!insertmacro _IncludeStrFunction StrTok +!insertmacro _IncludeStrFunction StrStr +!insertmacro _IncludeStrFunction StrRep + +; ---------------------------------- Macro Definitions ---------------------------------------- +!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString + Push "${EnvVarName}" + Push "${Action}" + Push "${RegLoc}" + Push "${PathString}" + Call EnvVarUpdate + Pop "${ResultVar}" +!macroend +!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' + +!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString + Push "${EnvVarName}" + Push "${Action}" + Push "${RegLoc}" + Push "${PathString}" + Call un.EnvVarUpdate + Pop "${ResultVar}" +!macroend +!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"' +; ---------------------------------- Macro Definitions end------------------------------------- + +;----------------------------------- EnvVarUpdate start---------------------------------------- +!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' +!define hkcu_current_user 'HKCU "Environment"' + +!macro EnvVarUpdate UN + +Function ${UN}EnvVarUpdate + + Push $0 + Exch 4 + Exch $1 + Exch 3 + Exch $2 + Exch 2 + Exch $3 + Exch + Exch $4 + Push $5 + Push $6 + Push $7 + Push $8 + Push $9 + Push $R0 + + /* After this point: + ------------------------- + $0 = ResultVar (returned) + $1 = EnvVarName (input) + $2 = Action (input) + $3 = RegLoc (input) + $4 = PathString (input) + $5 = Orig EnvVar (read from registry) + $6 = Len of $0 (temp) + $7 = tempstr1 (temp) + $8 = Entry counter (temp) + $9 = tempstr2 (temp) + $R0 = tempChar (temp) */ + + ; Step 1: Read contents of EnvVarName from RegLoc + ; + ; Check for empty EnvVarName + ${If} $1 == "" + SetErrors + DetailPrint "ERROR: EnvVarName is blank" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Check for valid Action + ${If} $2 != "A" + ${AndIf} $2 != "P" + ${AndIf} $2 != "R" + SetErrors + DetailPrint "ERROR: Invalid Action - must be A, P, or R" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ${If} $3 == HKLM + ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5 + ${ElseIf} $3 == HKCU + ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5 + ${Else} + SetErrors + DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"' + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Check for empty PathString + ${If} $4 == "" + SetErrors + DetailPrint "ERROR: PathString is blank" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Make sure we've got some work to do + ${If} $5 == "" + ${AndIf} $2 == "R" + SetErrors + DetailPrint "$1 is empty - Nothing to remove" + Goto EnvVarUpdate_Restore_Vars + ${EndIf} + + ; Step 2: Scrub EnvVar + ; + StrCpy $0 $5 ; Copy the contents to $0 + ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or + ; after the last one are not removed here but instead in Step 3) + ${If} $0 != "" ; If EnvVar is not empty ... + ${Do} + ${${UN}StrStr} $7 $0 " ;" + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${${UN}StrRep} $0 $0 " ;" ";" ; Remove ';' + ${Loop} + ${Do} + ${${UN}StrStr} $7 $0 "; " + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${${UN}StrRep} $0 $0 "; " ";" ; Remove ';' + ${Loop} + ${Do} + ${${UN}StrStr} $7 $0 ";;" + ${If} $7 == "" + ${ExitDo} + ${EndIf} + ${${UN}StrRep} $0 $0 ";;" ";" + ${Loop} + + ; Remove a leading or trailing semicolon from EnvVar + StrCpy $7 $0 1 0 + ${If} $7 == ";" + StrCpy $0 $0 "" 1 ; Change ';' to '' + ${EndIf} + StrLen $6 $0 + IntOp $6 $6 - 1 + StrCpy $7 $0 1 $6 + ${If} $7 == ";" + StrCpy $0 $0 $6 ; Change ';' to '' + ${EndIf} + ; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug + ${EndIf} + + /* Step 3. Remove all instances of the target path/string (even if "A" or "P") + $6 = bool flag (1 = found and removed PathString) + $7 = a string (e.g. path) delimited by semicolon(s) + $8 = entry counter starting at 0 + $9 = copy of $0 + $R0 = tempChar */ + + ${If} $5 != "" ; If EnvVar is not empty ... + StrCpy $9 $0 + StrCpy $0 "" + StrCpy $8 0 + StrCpy $6 0 + + ${Do} + ${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter + + ${If} $7 == "" ; If we've run out of entries, + ${ExitDo} ; were done + ${EndIf} ; + + ; Remove leading and trailing spaces from this entry (critical step for Action=Remove) + ${Do} + StrCpy $R0 $7 1 + ${If} $R0 != " " + ${ExitDo} + ${EndIf} + StrCpy $7 $7 "" 1 ; Remove leading space + ${Loop} + ${Do} + StrCpy $R0 $7 1 -1 + ${If} $R0 != " " + ${ExitDo} + ${EndIf} + StrCpy $7 $7 -1 ; Remove trailing space + ${Loop} + ${If} $7 == $4 ; If string matches, remove it by not appending it + StrCpy $6 1 ; Set 'found' flag + ${ElseIf} $7 != $4 ; If string does NOT match + ${AndIf} $0 == "" ; and the 1st string being added to $0, + StrCpy $0 $7 ; copy it to $0 without a prepended semicolon + ${ElseIf} $7 != $4 ; If string does NOT match + ${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0, + StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon + ${EndIf} ; + + IntOp $8 $8 + 1 ; Bump counter + ${Loop} ; Check for duplicates until we run out of paths + ${EndIf} + + ; Step 4: Perform the requested Action + ; + ${If} $2 != "R" ; If Append or Prepend + ${If} $6 == 1 ; And if we found the target + DetailPrint "Target is already present in $1. It will be removed and" + ${EndIf} + ${If} $0 == "" ; If EnvVar is (now) empty + StrCpy $0 $4 ; just copy PathString to EnvVar + ${If} $6 == 0 ; If found flag is either 0 + ${OrIf} $6 == "" ; or blank (if EnvVarName is empty) + DetailPrint "$1 was empty and has been updated with the target" + ${EndIf} + ${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty), + StrCpy $0 $0;$4 ; append PathString + ${If} $6 == 1 + DetailPrint "appended to $1" + ${Else} + DetailPrint "Target was appended to $1" + ${EndIf} + ${Else} ; If Prepend (and EnvVar is not empty), + StrCpy $0 $4;$0 ; prepend PathString + ${If} $6 == 1 + DetailPrint "prepended to $1" + ${Else} + DetailPrint "Target was prepended to $1" + ${EndIf} + ${EndIf} + ${Else} ; If Action = Remove + ${If} $6 == 1 ; and we found the target + DetailPrint "Target was found and removed from $1" + ${Else} + DetailPrint "Target was NOT found in $1 (nothing to remove)" + ${EndIf} + ${If} $0 == "" + DetailPrint "$1 is now empty" + ${EndIf} + ${EndIf} + + ; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change + ; + ClearErrors + ${If} $3 == HKLM + WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section + ${ElseIf} $3 == HKCU + WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section + ${EndIf} + + IfErrors 0 +4 + MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3" + DetailPrint "Could not write updated $1 to $3" + Goto EnvVarUpdate_Restore_Vars + + ; "Export" our change + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + EnvVarUpdate_Restore_Vars: + ; + ; Restore the user's variables and return ResultVar + Pop $R0 + Pop $9 + Pop $8 + Pop $7 + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Push $0 ; Push my $0 (ResultVar) + Exch + Pop $0 ; Restore his $0 + +FunctionEnd + +!macroend ; EnvVarUpdate UN +!insertmacro EnvVarUpdate "" +!insertmacro EnvVarUpdate "un." +;----------------------------------- EnvVarUpdate end---------------------------------------- + +!verbose pop +!endif \ No newline at end of file diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.geth.nsi b/vendor/github.com/ethereum/go-ethereum/build/nsis.geth.nsi new file mode 100644 index 00000000000..1034f30235d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/nsis.geth.nsi @@ -0,0 +1,70 @@ +# Builds a Windows installer with NSIS. +# It expects the following command line arguments: +# - OUTPUTFILE, filename of the installer (without extension) +# - MAJORVERSION, major build version +# - MINORVERSION, minor build version +# - BUILDVERSION, build id version +# +# The created installer executes the following steps: +# 1. install geth for all users +# 2. install optional development tools such as abigen +# 3. create an uninstaller +# 4. configures the Windows firewall for geth +# 5. create geth, attach and uninstall start menu entries +# 6. configures the registry that allows Windows to manage the package through its platform tools +# 7. adds the environment system wide variable ETHEREUM_SOCKET +# 8. adds the install directory to %PATH% +# +# Requirements: +# - NSIS, http://nsis.sourceforge.net/Main_Page +# - NSIS Large Strings build, http://nsis.sourceforge.net/Special_Builds +# - SFP, http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin (put dll in NSIS\Plugins\x86-ansi) +# +# After intalling NSIS extra the NSIS Large Strings build zip and replace the makensis.exe and the +# files found in Stub. +# +# based on: http://nsis.sourceforge.net/A_simple_installer_with_start_menu_shortcut_and_uninstaller +# +# TODO: +# - sign installer +CRCCheck on + +!define GROUPNAME "Ethereum" +!define APPNAME "Geth" +!define DESCRIPTION "Official Go implementation of the Ethereum protocol" +!addplugindir .\ + +# Require admin rights on NT6+ (When UAC is turned on) +RequestExecutionLevel admin + +# Use LZMA compression +SetCompressor /SOLID lzma + +!include LogicLib.nsh +!include PathUpdate.nsh +!include EnvVarUpdate.nsh + +!macro VerifyUserIsAdmin +UserInfo::GetAccountType +pop $0 +${If} $0 != "admin" # Require admin rights on NT4+ + messageBox mb_iconstop "Administrator rights required!" + setErrorLevel 740 # ERROR_ELEVATION_REQUIRED + quit +${EndIf} +!macroend + +function .onInit + # make vars are global for all users since geth is installed global + setShellVarContext all + !insertmacro VerifyUserIsAdmin + + ${If} ${ARCH} == "amd64" + StrCpy $InstDir "$PROGRAMFILES64\${APPNAME}" + ${Else} + StrCpy $InstDir "$PROGRAMFILES32\${APPNAME}" + ${Endif} +functionEnd + +!include install.nsh +!include uninstall.nsh diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.install.nsh b/vendor/github.com/ethereum/go-ethereum/build/nsis.install.nsh new file mode 100644 index 00000000000..57ef5a37c6a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/nsis.install.nsh @@ -0,0 +1,103 @@ +Name "geth ${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}" # VERSION variables set through command line arguments +InstallDir "$InstDir" +OutFile "${OUTPUTFILE}" # set through command line arguments + +# Links for "Add/Remove Programs" +!define HELPURL "https://github.com/ethereum/go-ethereum/issues" +!define UPDATEURL "https://github.com/ethereum/go-ethereum/releases" +!define ABOUTURL "https://github.com/ethereum/go-ethereum#ethereum-go" +!define /date NOW "%Y%m%d" + +PageEx license + LicenseData {{.License}} +PageExEnd + +# Install geth binary +Section "Geth" GETH_IDX + SetOutPath $INSTDIR + file {{.Geth}} + + # Create start menu launcher + createDirectory "$SMPROGRAMS\${APPNAME}" + createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe" "--fast" "--cache=512" + createShortCut "$SMPROGRAMS\${APPNAME}\Attach.lnk" "$INSTDIR\geth.exe" "attach" "" "" + createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "" "" + + # Firewall - remove rules (if exists) + SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Geth outgoing peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)" + + # Firewall - add rules + SimpleFC::AdvAddRule "Geth incoming peers (TCP:30303)" "" 6 1 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" 30303 "" "" "" + SimpleFC::AdvAddRule "Geth outgoing peers (TCP:30303)" "" 6 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" "" + SimpleFC::AdvAddRule "Geth UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" "" + + # Set default IPC endpoint (https://github.com/ethereum/EIPs/issues/147) + ${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc" + ${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "A" "HKLM" "\\.\pipe\geth.ipc" + + # Add instdir to PATH + Push "$INSTDIR" + Call AddToPath +SectionEnd + +# Install optional develop tools. +Section /o "Development tools" DEV_TOOLS_IDX + SetOutPath $INSTDIR + {{range .DevTools}}file {{.}} + {{end}} +SectionEnd + +# Return on top of stack the total size (as DWORD) of the selected/installed sections. +Var GetInstalledSize.total +Function GetInstalledSize + StrCpy $GetInstalledSize.total 0 + + ${if} ${SectionIsSelected} ${GETH_IDX} + SectionGetSize ${GETH_IDX} $0 + IntOp $GetInstalledSize.total $GetInstalledSize.total + $0 + ${endif} + + ${if} ${SectionIsSelected} ${DEV_TOOLS_IDX} + SectionGetSize ${DEV_TOOLS_IDX} $0 + IntOp $GetInstalledSize.total $GetInstalledSize.total + $0 + ${endif} + + IntFmt $GetInstalledSize.total "0x%08X" $GetInstalledSize.total + Push $GetInstalledSize.total +FunctionEnd + +# Write registry, Windows uses these values in various tools such as add/remove program. +# PowerShell: Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, InstallLocation, InstallDate | Format-Table –AutoSize +function .onInstSuccess + # Save information in registry in HKEY_LOCAL_MACHINE branch, Windows add/remove functionality depends on this + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayName" "${GROUPNAME} - ${APPNAME} - ${DESCRIPTION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "InstallLocation" "$INSTDIR" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "InstallDate" "${NOW}" + # Wait for Alex + #WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "Publisher" "${GROUPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "HelpLink" "${HELPURL}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "URLUpdateInfo" "${UPDATEURL}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "URLInfoAbout" "${ABOUTURL}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayVersion" "${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "VersionMajor" ${MAJORVERSION} + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "VersionMinor" ${MINORVERSION} + # There is no option for modifying or repairing the install + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "NoRepair" 1 + + Call GetInstalledSize + Pop $0 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "EstimatedSize" "$0" + + # Create uninstaller + writeUninstaller "$INSTDIR\uninstall.exe" +functionEnd + +Page components +Page directory +Page instfiles diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.pathupdate.nsh b/vendor/github.com/ethereum/go-ethereum/build/nsis.pathupdate.nsh new file mode 100644 index 00000000000..f54b7e3e13b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/nsis.pathupdate.nsh @@ -0,0 +1,153 @@ +!include "WinMessages.nsh" + +; see https://support.microsoft.com/en-us/kb/104011 +!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' +; HKEY_LOCAL_MACHINE = 0x80000002 + +; AddToPath - Appends dir to PATH +; (does not work on Win9x/ME) +; +; Usage: +; Push "dir" +; Call AddToPath +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + + ; NSIS ReadRegStr returns empty string on string overflow + ; Native calls are used here to check actual length of PATH + ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3) + System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4" + IntCmp $4 0 0 done done + + ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) + ; RegCloseKey($3) + System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" + System::Call "advapi32::RegCloseKey(i $3)" + + IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA + DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}" + MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" + Goto done + + IntCmp $4 0 +5 ; $4 != NO_ERROR + IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND + DetailPrint "AddToPath: unexpected error code $4" + Goto done + StrCpy $1 "" + + ; Check if already in PATH + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" 0 done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" 0 done + + ; Prevent NSIS string overflow + StrLen $2 $0 + StrLen $3 $1 + IntOp $2 $2 + $3 + IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";") + IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0 + DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}" + MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}." + Goto done + + ; Append dir to PATH + DetailPrint "Add to PATH: $0" + StrCpy $2 $1 1 -1 + StrCmp $2 ";" 0 +2 + StrCpy $1 $1 -1 ; remove trailing ';' + StrCmp $1 "" +2 ; no leading ';' + StrCpy $0 "$1;$0" + + WriteRegExpandStr ${Environ} "PATH" $0 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + +done: + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + +; RemoveFromPath - Removes dir from PATH +; +; Usage: +; Push "dir" +; Call RemoveFromPath +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + ; NSIS ReadRegStr returns empty string on string overflow + ; Native calls are used here to check actual length of PATH + ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3) + System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4" + IntCmp $4 0 0 done done + + ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) + ; RegCloseKey($3) + System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" + System::Call "advapi32::RegCloseKey(i $3)" + + IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA + DetailPrint "RemoveFromPath: original length $2 > ${NSIS_MAX_STRLEN}" + MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" + Goto done + + IntCmp $4 0 +5 ; $4 != NO_ERROR + IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND + DetailPrint "RemoveFromPath: unexpected error code $4" + Goto done + StrCpy $1 "" + + ; length < ${NSIS_MAX_STRLEN} -> ReadRegStr can be used + ReadRegStr $1 ${Environ} "PATH" + StrCpy $5 $1 1 -1 + StrCmp $5 ";" +2 + StrCpy $1 "$1;" ; ensure trailing ';' + Push $1 + Push "$0;" + Call un.StrStr + Pop $2 ; pos of our dir + StrCmp $2 "" done + + DetailPrint "Remove from PATH: $0" + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove + StrCpy $3 "$5$6" + StrCpy $5 $3 1 -1 + StrCmp $5 ";" 0 +2 + StrCpy $3 $3 -1 ; remove trailing ';' + WriteRegExpandStr ${Environ} "PATH" $3 + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + +done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.simplefc.dll b/vendor/github.com/ethereum/go-ethereum/build/nsis.simplefc.dll new file mode 100644 index 00000000000..73b7d9634de Binary files /dev/null and b/vendor/github.com/ethereum/go-ethereum/build/nsis.simplefc.dll differ diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.simplefc.source.zip b/vendor/github.com/ethereum/go-ethereum/build/nsis.simplefc.source.zip new file mode 100644 index 00000000000..d7476022ad9 Binary files /dev/null and b/vendor/github.com/ethereum/go-ethereum/build/nsis.simplefc.source.zip differ diff --git a/vendor/github.com/ethereum/go-ethereum/build/nsis.uninstall.nsh b/vendor/github.com/ethereum/go-ethereum/build/nsis.uninstall.nsh new file mode 100644 index 00000000000..6358faa74ec --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/nsis.uninstall.nsh @@ -0,0 +1,33 @@ +Section "Uninstall" + # uninstall for all users + setShellVarContext all + + # Delete (optionally) installed files + {{range $}}Delete $INSTDIR\{{.}} + {{end}} + Delete $INSTDIR\uninstall.exe + + # Delete install directory + rmDir $INSTDIR + + # Delete start menu launcher + Delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" + Delete "$SMPROGRAMS\${APPNAME}\Attach.lnk" + Delete "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" + rmDir "$SMPROGRAMS\${APPNAME}" + + # Firewall - remove rules if exists + SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Geth outgoing peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)" + + # Remove IPC endpoint (https://github.com/ethereum/EIPs/issues/147) + ${un.EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc" + + # Remove install directory from PATH + Push "$INSTDIR" + Call un.RemoveFromPath + + # Cleanup registry (deletes all sub keys) + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" +SectionEnd diff --git a/vendor/github.com/ethereum/go-ethereum/build/pod.podspec b/vendor/github.com/ethereum/go-ethereum/build/pod.podspec new file mode 100644 index 00000000000..2c14c280c7c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/pod.podspec @@ -0,0 +1,22 @@ +Pod::Spec.new do |spec| + spec.name = 'Geth' + spec.version = '{{.Version}}' + spec.license = { :type => 'GNU Lesser General Public License, Version 3.0' } + spec.homepage = 'https://github.com/ethereum/go-ethereum' + spec.authors = { {{range .Contributors}} + '{{.Name}}' => '{{.Email}}',{{end}} + } + spec.summary = 'iOS Ethereum Client' + spec.source = { :git => 'https://github.com/ethereum/go-ethereum.git', :commit => '{{.Commit}}' } + + spec.platform = :ios + spec.ios.deployment_target = '9.0' + spec.ios.vendored_frameworks = 'Frameworks/Geth.framework' + + spec.prepare_command = <<-CMD + curl https://gethstore.blob.core.windows.net/builds/{{.Archive}}.tar.gz | tar -xvz + mkdir Frameworks + mv {{.Archive}}/Geth.framework Frameworks + rm -rf {{.Archive}} + CMD +end diff --git a/vendor/github.com/ethereum/go-ethereum/build/update-license.go b/vendor/github.com/ethereum/go-ethereum/build/update-license.go new file mode 100644 index 00000000000..3d69598b754 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/build/update-license.go @@ -0,0 +1,396 @@ +// +build none + +/* +This command generates GPL license headers on top of all source files. +You can run it once per month, before cutting a release or just +whenever you feel like it. + + go run update-license.go + +All authors (people who have contributed code) are listed in the +AUTHORS file. The author names are mapped and deduplicated using the +.mailmap file. You can use .mailmap to set the canonical name and +address for each author. See git-shortlog(1) for an explanation of the +.mailmap format. + +Please review the resulting diff to check whether the correct +copyright assignments are performed. +*/ + +package main + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "sort" + "strconv" + "strings" + "sync" + "text/template" + "time" +) + +var ( + // only files with these extensions will be considered + extensions = []string{".go", ".js", ".qml"} + + // paths with any of these prefixes will be skipped + skipPrefixes = []string{ + // boring stuff + "vendor/", "tests/testdata/", "build/", + // don't relicense vendored sources + "cmd/internal/browser", + "consensus/ethash/xor.go", + "crypto/bn256/", + "crypto/ecies/", + "crypto/secp256k1/curve.go", + "crypto/sha3/", + "internal/jsre/deps", + "log/", + // don't license generated files + "contracts/chequebook/contract/", + "contracts/ens/contract/", + "contracts/release/contract.go", + } + + // paths with this prefix are licensed as GPL. all other files are LGPL. + gplPrefixes = []string{"cmd/"} + + // this regexp must match the entire license comment at the + // beginning of each file. + licenseCommentRE = regexp.MustCompile(`^//\s*(Copyright|This file is part of).*?\n(?://.*?\n)*\n*`) + + // this text appears at the start of AUTHORS + authorsFileHeader = "# This is the official list of go-ethereum authors for copyright purposes.\n\n" +) + +// this template generates the license comment. +// its input is an info structure. +var licenseT = template.Must(template.New("").Parse(` +// Copyright {{.Year}} The go-ethereum Authors +// This file is part of {{.Whole false}}. +// +// {{.Whole true}} is free software: you can redistribute it and/or modify +// it under the terms of the GNU {{.License}} as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// {{.Whole true}} is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU {{.License}} for more details. +// +// You should have received a copy of the GNU {{.License}} +// along with {{.Whole false}}. If not, see . + +`[1:])) + +type info struct { + file string + Year int64 +} + +func (i info) License() string { + if i.gpl() { + return "General Public License" + } + return "Lesser General Public License" +} + +func (i info) ShortLicense() string { + if i.gpl() { + return "GPL" + } + return "LGPL" +} + +func (i info) Whole(startOfSentence bool) string { + if i.gpl() { + return "go-ethereum" + } + if startOfSentence { + return "The go-ethereum library" + } + return "the go-ethereum library" +} + +func (i info) gpl() bool { + for _, p := range gplPrefixes { + if strings.HasPrefix(i.file, p) { + return true + } + } + return false +} + +func main() { + var ( + files = getFiles() + filec = make(chan string) + infoc = make(chan *info, 20) + wg sync.WaitGroup + ) + + writeAuthors(files) + + go func() { + for _, f := range files { + filec <- f + } + close(filec) + }() + for i := runtime.NumCPU(); i >= 0; i-- { + // getting file info is slow and needs to be parallel. + // it traverses git history for each file. + wg.Add(1) + go getInfo(filec, infoc, &wg) + } + go func() { + wg.Wait() + close(infoc) + }() + writeLicenses(infoc) +} + +func skipFile(path string) bool { + if strings.Contains(path, "/testdata/") { + return true + } + for _, p := range skipPrefixes { + if strings.HasPrefix(path, p) { + return true + } + } + return false +} + +func getFiles() []string { + cmd := exec.Command("git", "ls-tree", "-r", "--name-only", "HEAD") + var files []string + err := doLines(cmd, func(line string) { + if skipFile(line) { + return + } + ext := filepath.Ext(line) + for _, wantExt := range extensions { + if ext == wantExt { + goto keep + } + } + return + keep: + files = append(files, line) + }) + if err != nil { + log.Fatal("error getting files:", err) + } + return files +} + +var authorRegexp = regexp.MustCompile(`\s*[0-9]+\s*(.*)`) + +func gitAuthors(files []string) []string { + cmds := []string{"shortlog", "-s", "-n", "-e", "HEAD", "--"} + cmds = append(cmds, files...) + cmd := exec.Command("git", cmds...) + var authors []string + err := doLines(cmd, func(line string) { + m := authorRegexp.FindStringSubmatch(line) + if len(m) > 1 { + authors = append(authors, m[1]) + } + }) + if err != nil { + log.Fatalln("error getting authors:", err) + } + return authors +} + +func readAuthors() []string { + content, err := ioutil.ReadFile("AUTHORS") + if err != nil && !os.IsNotExist(err) { + log.Fatalln("error reading AUTHORS:", err) + } + var authors []string + for _, a := range bytes.Split(content, []byte("\n")) { + if len(a) > 0 && a[0] != '#' { + authors = append(authors, string(a)) + } + } + // Retranslate existing authors through .mailmap. + // This should catch email address changes. + authors = mailmapLookup(authors) + return authors +} + +func mailmapLookup(authors []string) []string { + if len(authors) == 0 { + return nil + } + cmds := []string{"check-mailmap", "--"} + cmds = append(cmds, authors...) + cmd := exec.Command("git", cmds...) + var translated []string + err := doLines(cmd, func(line string) { + translated = append(translated, line) + }) + if err != nil { + log.Fatalln("error translating authors:", err) + } + return translated +} + +func writeAuthors(files []string) { + merge := make(map[string]bool) + // Add authors that Git reports as contributorxs. + // This is the primary source of author information. + for _, a := range gitAuthors(files) { + merge[a] = true + } + // Add existing authors from the file. This should ensure that we + // never lose authors, even if Git stops listing them. We can also + // add authors manually this way. + for _, a := range readAuthors() { + merge[a] = true + } + // Write sorted list of authors back to the file. + var result []string + for a := range merge { + result = append(result, a) + } + sort.Strings(result) + content := new(bytes.Buffer) + content.WriteString(authorsFileHeader) + for _, a := range result { + content.WriteString(a) + content.WriteString("\n") + } + fmt.Println("writing AUTHORS") + if err := ioutil.WriteFile("AUTHORS", content.Bytes(), 0644); err != nil { + log.Fatalln(err) + } +} + +func getInfo(files <-chan string, out chan<- *info, wg *sync.WaitGroup) { + for file := range files { + stat, err := os.Lstat(file) + if err != nil { + fmt.Printf("ERROR %s: %v\n", file, err) + continue + } + if !stat.Mode().IsRegular() { + continue + } + if isGenerated(file) { + continue + } + info, err := fileInfo(file) + if err != nil { + fmt.Printf("ERROR %s: %v\n", file, err) + continue + } + out <- info + } + wg.Done() +} + +func isGenerated(file string) bool { + fd, err := os.Open(file) + if err != nil { + return false + } + defer fd.Close() + buf := make([]byte, 2048) + n, _ := fd.Read(buf) + buf = buf[:n] + for _, l := range bytes.Split(buf, []byte("\n")) { + if bytes.HasPrefix(l, []byte("// Code generated")) { + return true + } + } + return false +} + +// fileInfo finds the lowest year in which the given file was committed. +func fileInfo(file string) (*info, error) { + info := &info{file: file, Year: int64(time.Now().Year())} + cmd := exec.Command("git", "log", "--follow", "--find-renames=80", "--find-copies=80", "--pretty=format:%ai", "--", file) + err := doLines(cmd, func(line string) { + y, err := strconv.ParseInt(line[:4], 10, 64) + if err != nil { + fmt.Printf("cannot parse year: %q", line[:4]) + } + if y < info.Year { + info.Year = y + } + }) + return info, err +} + +func writeLicenses(infos <-chan *info) { + for i := range infos { + writeLicense(i) + } +} + +func writeLicense(info *info) { + fi, err := os.Stat(info.file) + if os.IsNotExist(err) { + fmt.Println("skipping (does not exist)", info.file) + return + } + if err != nil { + log.Fatalf("error stat'ing %s: %v\n", info.file, err) + } + content, err := ioutil.ReadFile(info.file) + if err != nil { + log.Fatalf("error reading %s: %v\n", info.file, err) + } + // Construct new file content. + buf := new(bytes.Buffer) + licenseT.Execute(buf, info) + if m := licenseCommentRE.FindIndex(content); m != nil && m[0] == 0 { + buf.Write(content[:m[0]]) + buf.Write(content[m[1]:]) + } else { + buf.Write(content) + } + // Write it to the file. + if bytes.Equal(content, buf.Bytes()) { + fmt.Println("skipping (no changes)", info.file) + return + } + fmt.Println("writing", info.ShortLicense(), info.file) + if err := ioutil.WriteFile(info.file, buf.Bytes(), fi.Mode()); err != nil { + log.Fatalf("error writing %s: %v", info.file, err) + } +} + +func doLines(cmd *exec.Cmd, f func(string)) error { + stdout, err := cmd.StdoutPipe() + if err != nil { + return err + } + if err := cmd.Start(); err != nil { + return err + } + s := bufio.NewScanner(stdout) + for s.Scan() { + f(s.Text()) + } + if s.Err() != nil { + return s.Err() + } + if err := cmd.Wait(); err != nil { + return fmt.Errorf("%v (for %s)", err, strings.Join(cmd.Args, " ")) + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/cmd/wnode/main.go b/vendor/github.com/ethereum/go-ethereum/cmd/wnode/main.go index 05e6b290863..235d368ad78 100644 --- a/vendor/github.com/ethereum/go-ethereum/cmd/wnode/main.go +++ b/vendor/github.com/ethereum/go-ethereum/cmd/wnode/main.go @@ -98,6 +98,8 @@ var ( argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)") argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)") argSaveDir = flag.String("savedir", "", "directory where incoming messages will be saved as files") + argSymPass = flag.String("sympass", "", "SymKey password") + argMsPass = flag.String("mspass", "", "Mailserver password") ) func main() { @@ -146,6 +148,13 @@ func processArgs() { } else if *fileExMode { utils.Fatalf("Parameter 'savedir' is mandatory for file exchange mode") } + if len(*argSymPass) > 0 { + symPass = *argSymPass + } + + if len(*argMsPass) > 0 { + msPassword = *argMsPass + } if *echoMode { echo() @@ -415,8 +424,22 @@ func run() { } else if *fileExMode { sendFilesLoop() } else { - sendLoop() + pingLoop() // instead of sendLoop() + } +} + +func pingLoop() { + ticker := time.NewTicker(time.Second * 120) + + for { + select { + case <-ticker.C: + fmt.Println("I am alive: ", time.Now()) + case <-done: + return + } } + } func sendLoop() { diff --git a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go index 6d509ec63fc..44779502f16 100644 --- a/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go +++ b/vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go @@ -1169,6 +1169,7 @@ func (s *PublicTransactionPoolAPI) SendTransactionWithPassphrase(ctx context.Con } // Assemble the transaction and sign with the wallet tx := args.toTransaction() + var chainID *big.Int if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { chainID = config.ChainId diff --git a/vendor/github.com/go-playground/locales/.gitignore b/vendor/github.com/go-playground/locales/.gitignore new file mode 100644 index 00000000000..daf913b1b34 --- /dev/null +++ b/vendor/github.com/go-playground/locales/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/go-playground/locales/LICENSE b/vendor/github.com/go-playground/locales/LICENSE new file mode 100644 index 00000000000..75854ac4f01 --- /dev/null +++ b/vendor/github.com/go-playground/locales/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Go Playground + +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. \ No newline at end of file diff --git a/vendor/github.com/go-playground/locales/README.md b/vendor/github.com/go-playground/locales/README.md new file mode 100644 index 00000000000..b462c93a097 --- /dev/null +++ b/vendor/github.com/go-playground/locales/README.md @@ -0,0 +1,172 @@ +## locales +![Project status](https://img.shields.io/badge/version-0.11.1-green.svg) +[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/locales/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/locales) +[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/locales)](https://goreportcard.com/report/github.com/go-playground/locales) +[![GoDoc](https://godoc.org/github.com/go-playground/locales?status.svg)](https://godoc.org/github.com/go-playground/locales) +![License](https://img.shields.io/dub/l/vibe-d.svg) +[![Gitter](https://badges.gitter.im/go-playground/locales.svg)](https://gitter.im/go-playground/locales?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +Locales is a set of locales generated from the [Unicode CLDR Project](http://cldr.unicode.org/) which can be used independently or within +an i18n package; these were built for use with, but not exclusive to, [Universal Translator](https://github.com/go-playground/universal-translator). + +Features +-------- +- [x] Rules generated from the latest [CLDR](http://cldr.unicode.org/index/downloads) data, v31.0.1 +- [x] Contains Cardinal, Ordinal and Range Plural Rules +- [x] Contains Month, Weekday and Timezone translations built in +- [x] Contains Date & Time formatting functions +- [x] Contains Number, Currency, Accounting and Percent formatting functions +- [x] Supports the "Gregorian" calendar only ( my time isn't unlimited, had to draw the line somewhere ) + +Full Tests +-------------------- +I could sure use your help adding tests for every locale, it is a huge undertaking and I just don't have the free time to do it all at the moment; +any help would be **greatly appreciated!!!!** please see [issue](https://github.com/go-playground/locales/issues/1) for details. + +Installation +----------- + +Use go get + +```shell +go get github.com/go-playground/locales +``` + +NOTES +-------- +You'll notice most return types are []byte, this is because most of the time the results will be concatenated with a larger body +of text and can avoid some allocations if already appending to a byte array, otherwise just cast as string. + +Usage +------- +```go +package main + +import ( + "fmt" + "time" + + "github.com/go-playground/locales/currency" + "github.com/go-playground/locales/en_CA" +) + +func main() { + + loc, _ := time.LoadLocation("America/Toronto") + datetime := time.Date(2016, 02, 03, 9, 0, 1, 0, loc) + + l := en_CA.New() + + // Dates + fmt.Println(l.FmtDateFull(datetime)) + fmt.Println(l.FmtDateLong(datetime)) + fmt.Println(l.FmtDateMedium(datetime)) + fmt.Println(l.FmtDateShort(datetime)) + + // Times + fmt.Println(l.FmtTimeFull(datetime)) + fmt.Println(l.FmtTimeLong(datetime)) + fmt.Println(l.FmtTimeMedium(datetime)) + fmt.Println(l.FmtTimeShort(datetime)) + + // Months Wide + fmt.Println(l.MonthWide(time.January)) + fmt.Println(l.MonthWide(time.February)) + fmt.Println(l.MonthWide(time.March)) + // ... + + // Months Abbreviated + fmt.Println(l.MonthAbbreviated(time.January)) + fmt.Println(l.MonthAbbreviated(time.February)) + fmt.Println(l.MonthAbbreviated(time.March)) + // ... + + // Months Narrow + fmt.Println(l.MonthNarrow(time.January)) + fmt.Println(l.MonthNarrow(time.February)) + fmt.Println(l.MonthNarrow(time.March)) + // ... + + // Weekdays Wide + fmt.Println(l.WeekdayWide(time.Sunday)) + fmt.Println(l.WeekdayWide(time.Monday)) + fmt.Println(l.WeekdayWide(time.Tuesday)) + // ... + + // Weekdays Abbreviated + fmt.Println(l.WeekdayAbbreviated(time.Sunday)) + fmt.Println(l.WeekdayAbbreviated(time.Monday)) + fmt.Println(l.WeekdayAbbreviated(time.Tuesday)) + // ... + + // Weekdays Short + fmt.Println(l.WeekdayShort(time.Sunday)) + fmt.Println(l.WeekdayShort(time.Monday)) + fmt.Println(l.WeekdayShort(time.Tuesday)) + // ... + + // Weekdays Narrow + fmt.Println(l.WeekdayNarrow(time.Sunday)) + fmt.Println(l.WeekdayNarrow(time.Monday)) + fmt.Println(l.WeekdayNarrow(time.Tuesday)) + // ... + + var f64 float64 + + f64 = -10356.4523 + + // Number + fmt.Println(l.FmtNumber(f64, 2)) + + // Currency + fmt.Println(l.FmtCurrency(f64, 2, currency.CAD)) + fmt.Println(l.FmtCurrency(f64, 2, currency.USD)) + + // Accounting + fmt.Println(l.FmtAccounting(f64, 2, currency.CAD)) + fmt.Println(l.FmtAccounting(f64, 2, currency.USD)) + + f64 = 78.12 + + // Percent + fmt.Println(l.FmtPercent(f64, 0)) + + // Plural Rules for locale, so you know what rules you must cover + fmt.Println(l.PluralsCardinal()) + fmt.Println(l.PluralsOrdinal()) + + // Cardinal Plural Rules + fmt.Println(l.CardinalPluralRule(1, 0)) + fmt.Println(l.CardinalPluralRule(1.0, 0)) + fmt.Println(l.CardinalPluralRule(1.0, 1)) + fmt.Println(l.CardinalPluralRule(3, 0)) + + // Ordinal Plural Rules + fmt.Println(l.OrdinalPluralRule(21, 0)) // 21st + fmt.Println(l.OrdinalPluralRule(22, 0)) // 22nd + fmt.Println(l.OrdinalPluralRule(33, 0)) // 33rd + fmt.Println(l.OrdinalPluralRule(34, 0)) // 34th + + // Range Plural Rules + fmt.Println(l.RangePluralRule(1, 0, 1, 0)) // 1-1 + fmt.Println(l.RangePluralRule(1, 0, 2, 0)) // 1-2 + fmt.Println(l.RangePluralRule(5, 0, 8, 0)) // 5-8 +} +``` + +NOTES: +------- +These rules were generated from the [Unicode CLDR Project](http://cldr.unicode.org/), if you encounter any issues +I strongly encourage contributing to the CLDR project to get the locale information corrected and the next time +these locales are regenerated the fix will come with. + +I do however realize that time constraints are often important and so there are two options: + +1. Create your own locale, copy, paste and modify, and ensure it complies with the `Translator` interface. +2. Add an exception in the locale generation code directly and once regenerated, fix will be in place. + +Please to not make fixes inside the locale files, they WILL get overwritten when the locales are regenerated. + +License +------ +Distributed under MIT License, please see license file in code for more details. diff --git a/vendor/github.com/go-playground/locales/logo.png b/vendor/github.com/go-playground/locales/logo.png new file mode 100644 index 00000000000..3038276e687 Binary files /dev/null and b/vendor/github.com/go-playground/locales/logo.png differ diff --git a/vendor/github.com/go-playground/universal-translator/README.md b/vendor/github.com/go-playground/universal-translator/README.md index 2840a7e1035..24aef158598 100644 --- a/vendor/github.com/go-playground/universal-translator/README.md +++ b/vendor/github.com/go-playground/universal-translator/README.md @@ -1,5 +1,6 @@ ## universal-translator -![Project status](https://img.shields.io/badge/version-0.16.0-green.svg) + +![Project status](https://img.shields.io/badge/version-0.16.0-green.svg) [![Build Status](https://semaphoreci.com/api/v1/joeybloggs/universal-translator/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/universal-translator) [![Coverage Status](https://coveralls.io/repos/github/go-playground/universal-translator/badge.svg)](https://coveralls.io/github/go-playground/universal-translator) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/universal-translator)](https://goreportcard.com/report/github.com/go-playground/universal-translator) diff --git a/vendor/github.com/go-playground/universal-translator/examples/basic/main.go b/vendor/github.com/go-playground/universal-translator/examples/basic/main.go deleted file mode 100644 index c0f4fca36ca..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/basic/main.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/go-playground/locales" - "github.com/go-playground/locales/en" - "github.com/go-playground/locales/en_CA" - "github.com/go-playground/locales/fr" - "github.com/go-playground/locales/nl" - "github.com/go-playground/universal-translator" -) - -// only one instance as translators within are shared + goroutine safe -var universalTraslator *ut.UniversalTranslator - -func main() { - - // NOTE: this example is omitting a lot of error checking for brevity - e := en.New() - universalTraslator = ut.New(e, e, en_CA.New(), nl.New(), fr.New()) - - en, _ := universalTraslator.GetTranslator("en") - - // generally used after parsing an http 'Accept-Language' header - // and this will try to find a matching locale you support or - // fallback locale. - // en, _ := ut.FindTranslator([]string{"en", "en_CA", "nl"}) - - // this will help - fmt.Println("Cardinal Plural Rules:", en.PluralsCardinal()) - fmt.Println("Ordinal Plural Rules:", en.PluralsOrdinal()) - fmt.Println("Range Plural Rules:", en.PluralsRange()) - - // add basic language only translations - // last param indicates if it's ok to override the translation if one already exists - en.Add("welcome", "Welcome {0} to our test", false) - - // add language translations dependant on cardinal plural rules - en.AddCardinal("days", "You have {0} day left to register", locales.PluralRuleOne, false) - en.AddCardinal("days", "You have {0} days left to register", locales.PluralRuleOther, false) - - // add language translations dependant on ordinal plural rules - en.AddOrdinal("day-of-month", "{0}st", locales.PluralRuleOne, false) - en.AddOrdinal("day-of-month", "{0}nd", locales.PluralRuleTwo, false) - en.AddOrdinal("day-of-month", "{0}rd", locales.PluralRuleFew, false) - en.AddOrdinal("day-of-month", "{0}th", locales.PluralRuleOther, false) - - // add language translations dependant on range plural rules - // NOTE: only one plural rule for range in 'en' locale - en.AddRange("between", "It's {0}-{1} days away", locales.PluralRuleOther, false) - - // now lets use the translations we just added, in the same order we added them - - fmt.Println(en.T("welcome", "Joeybloggs")) - - fmt.Println(en.C("days", 1, 0, en.FmtNumber(1, 0))) // you'd normally have variables defined for 1 and 0 - fmt.Println(en.C("days", 2, 0, en.FmtNumber(2, 0))) - fmt.Println(en.C("days", 10456.25, 2, en.FmtNumber(10456.25, 2))) - - fmt.Println(en.O("day-of-month", 1, 0, en.FmtNumber(1, 0))) - fmt.Println(en.O("day-of-month", 2, 0, en.FmtNumber(2, 0))) - fmt.Println(en.O("day-of-month", 3, 0, en.FmtNumber(3, 0))) - fmt.Println(en.O("day-of-month", 4, 0, en.FmtNumber(4, 0))) - fmt.Println(en.O("day-of-month", 10456.25, 0, en.FmtNumber(10456.25, 0))) - - fmt.Println(en.R("between", 0, 0, 1, 0, en.FmtNumber(0, 0), en.FmtNumber(1, 0))) - fmt.Println(en.R("between", 1, 0, 2, 0, en.FmtNumber(1, 0), en.FmtNumber(2, 0))) - fmt.Println(en.R("between", 1, 0, 100, 0, en.FmtNumber(1, 0), en.FmtNumber(100, 0))) -} diff --git a/vendor/github.com/go-playground/universal-translator/examples/file-formats/cardinal.json b/vendor/github.com/go-playground/universal-translator/examples/file-formats/cardinal.json deleted file mode 100644 index ca605894abc..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/file-formats/cardinal.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "locale": "en", - "key": "cardinal_test", - "trans": "You have {0} day left.", - "type": "Cardinal", - "rule": "One" - }, - { - "locale": "en", - "key": "cardinal_test", - "trans": "You have {0} days left.", - "type": "Cardinal", - "rule": "Other" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/file-formats/ordinal.json b/vendor/github.com/go-playground/universal-translator/examples/file-formats/ordinal.json deleted file mode 100644 index 364255a4db8..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/file-formats/ordinal.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "locale": "en", - "key": "day", - "trans": "{0}st", - "type": "Ordinal", - "rule": "One" - }, - { - "locale": "en", - "key": "day", - "trans": "{0}nd", - "type": "Ordinal", - "rule": "Two" - }, - { - "locale": "en", - "key": "day", - "trans": "{0}rd", - "type": "Ordinal", - "rule": "Few" - }, - { - "locale": "en", - "key": "day", - "trans": "{0}th", - "type": "Ordinal", - "rule": "Other" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/file-formats/plain-substitution.json b/vendor/github.com/go-playground/universal-translator/examples/file-formats/plain-substitution.json deleted file mode 100644 index 407422db9de..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/file-formats/plain-substitution.json +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "locale": "en", - "key": "test_trans4", - "trans": "{0}{1}" - }, - { - "locale": "en", - "key": "test_trans", - "trans": "Welcome {0} to the {1}." - }, - { - "locale": "en", - "key": -1, - "trans": "Welcome {0}" - }, - { - "locale": "en", - "key": "test_trans2", - "trans": "{0} to the {1}." - }, - { - "locale": "en", - "key": "test_trans3", - "trans": "Welcome {0} to the {1}" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/file-formats/range.json b/vendor/github.com/go-playground/universal-translator/examples/file-formats/range.json deleted file mode 100644 index 7986566dde7..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/file-formats/range.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "locale": "nl", - "key": "day", - "trans": "er {0}-{1} dag vertrokken", - "type": "Range", - "rule": "One" - }, - { - "locale": "nl", - "key": "day", - "trans": "er zijn {0}-{1} dagen over", - "type": "Range", - "rule": "Other" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/full-no-files/home.tmpl b/vendor/github.com/go-playground/universal-translator/examples/full-no-files/home.tmpl deleted file mode 100644 index 2b37f276319..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/full-no-files/home.tmpl +++ /dev/null @@ -1,35 +0,0 @@ -{{ define "home" }} - - - - Home - - -

Locale: {{ .Trans.Locale }}

-

Trans1: {{ .Trans.C "days-left" 1 0 "1" }}

-

Trans2: {{ .Trans.C "days-left" 2 0 "2" }}

-

FmtNumber Positive: {{ .Trans.FmtNumber .PositiveNum 2 }}

-

FmtNumber Negative: {{ .Trans.FmtNumber .NegativeNum 2 }}

-

FmtPercent Negative: {{ .Trans.FmtPercent .Percent 2 }}

-

FmtCurrency Negative: {{ .Trans.FmtCurrency .PositiveNum 2 .Trans.Currency }}

-

FmtCurrency Negative: {{ .Trans.FmtCurrency .NegativeNum 2 .Trans.Currency }}

-

FmtAccounting Negative: {{ .Trans.FmtAccounting .PositiveNum 2 .Trans.Currency }}

-

FmtAccounting Negative: {{ .Trans.FmtAccounting .NegativeNum 2 .Trans.Currency }}

-

FmtDateShort: {{ .Trans.FmtDateShort .Now }}

-

FmtDateMedium: {{ .Trans.FmtDateMedium .Now }}

-

FmtDateLong: {{ .Trans.FmtDateLong .Now }}

-

FmtDateFull: {{ .Trans.FmtDateFull .Now }}

-

FmtTimeShort: {{ .Trans.FmtTimeShort .Now }}

-

FmtTimeMedium: {{ .Trans.FmtTimeMedium .Now }}

-

FmtTimeLong: {{ .Trans.FmtTimeLong .Now }}

-

FmtTimeFull: {{ .Trans.FmtTimeFull .Now }}

-

MonthsAbbreviated: {{ .Trans.MonthsAbbreviated }}

-

MonthsNarrow: {{ .Trans.MonthsNarrow }}

-

MonthsWide: {{ .Trans.MonthsWide }}

-

WeekdaysAbbreviated: {{ .Trans.WeekdaysAbbreviated }}

-

WeekdaysNarrow: {{ .Trans.WeekdaysNarrow }}

-

WeekdaysShort: {{ .Trans.WeekdaysShort }}

-

WeekdaysWide: {{ .Trans.WeekdaysWide }}

- - -{{ end }} \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/full-no-files/main.go b/vendor/github.com/go-playground/universal-translator/examples/full-no-files/main.go deleted file mode 100644 index 392d36bd7f3..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/full-no-files/main.go +++ /dev/null @@ -1,210 +0,0 @@ -package main - -import ( - "context" - "html/template" - "log" - "net/http" - "time" - - "github.com/go-playground/locales" - "github.com/go-playground/locales/currency" - "github.com/go-playground/locales/en" - "github.com/go-playground/locales/fr" - "github.com/go-playground/pure" - "github.com/go-playground/pure/examples/middleware/logging-recovery" - "github.com/go-playground/universal-translator" -) - -var ( - tmpls *template.Template - utrans *ut.UniversalTranslator - transKey = struct { - name string - }{ - name: "transKey", - } -) - -// Translator wraps ut.Translator in order to handle errors transparently -// it is totally optional but recommended as it can now be used directly in -// templates and nobody can add translations where they're not supposed to. -type Translator interface { - locales.Translator - - // creates the translation for the locale given the 'key' and params passed in. - // wraps ut.Translator.T to handle errors - T(key interface{}, params ...string) string - - // creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments - // and param passed in. - // wraps ut.Translator.C to handle errors - C(key interface{}, num float64, digits uint64, param string) string - - // creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments - // and param passed in. - // wraps ut.Translator.O to handle errors - O(key interface{}, num float64, digits uint64, param string) string - - // creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and - // 'digit2' arguments and 'param1' and 'param2' passed in - // wraps ut.Translator.R to handle errors - R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string - - // Currency returns the type used by the given locale. - Currency() currency.Type -} - -// implements Translator interface definition above. -type translator struct { - locales.Translator - trans ut.Translator -} - -var _ Translator = (*translator)(nil) - -func (t *translator) T(key interface{}, params ...string) string { - - s, err := t.trans.T(key, params...) - if err != nil { - log.Printf("issue translating key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) C(key interface{}, num float64, digits uint64, param string) string { - - s, err := t.trans.C(key, num, digits, param) - if err != nil { - log.Printf("issue translating cardinal key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) O(key interface{}, num float64, digits uint64, param string) string { - - s, err := t.trans.C(key, num, digits, param) - if err != nil { - log.Printf("issue translating ordinal key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string { - - s, err := t.trans.R(key, num1, digits1, num2, digits2, param1, param2) - if err != nil { - log.Printf("issue translating range key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) Currency() currency.Type { - - // choose your own locale. The reason it isn't mapped for you is because many - // countries have multiple currencies; it's up to you and you're application how - // and which currencies to use. I recommend adding a function it to to your custon translator - // interface like defined above. - switch t.Locale() { - case "en": - return currency.USD - case "fr": - return currency.EUR - default: - return currency.USD - } -} - -func main() { - - en := en.New() - utrans = ut.New(en, en, fr.New()) - setup() - - tmpls, _ = template.ParseFiles("home.tmpl") - - r := pure.New() - r.Use(middleware.LoggingAndRecovery(true), translatorMiddleware) - r.Get("/", home) - - log.Println("Running on Port :8080") - log.Println("Try me with URL http://localhost:8080/?locale=en") - log.Println("and then http://localhost:8080/?locale=fr") - http.ListenAndServe(":8080", r.Serve()) -} - -func home(w http.ResponseWriter, r *http.Request) { - - // get locale translator ( could be wrapped into a helper function ) - t := r.Context().Value(transKey).(Translator) - - s := struct { - Trans Translator - Now time.Time - PositiveNum float64 - NegativeNum float64 - Percent float64 - }{ - Trans: t, - Now: time.Now(), - PositiveNum: 1234576.45, - NegativeNum: -35900394.34, - Percent: 96.76, - } - - if err := tmpls.ExecuteTemplate(w, "home", s); err != nil { - log.Fatal(err) - } -} - -func translatorMiddleware(next http.HandlerFunc) http.HandlerFunc { - - return func(w http.ResponseWriter, r *http.Request) { - - // there are many ways to check, this is just checking for query param & - // Accept-Language header but can be expanded to Cookie's etc.... - - params := r.URL.Query() - - locale := params.Get("locale") - var t ut.Translator - - if len(locale) > 0 { - - var found bool - - if t, found = utrans.GetTranslator(locale); found { - goto END - } - } - - // get and parse the "Accept-Language" http header and return an array - t, _ = utrans.FindTranslator(pure.AcceptedLanguages(r)...) - END: - // I would normally wrap ut.Translator with one with my own functions in order - // to handle errors and be able to use all functions from translator within the templates. - r = r.WithContext(context.WithValue(r.Context(), transKey, &translator{trans: t, Translator: t.(locales.Translator)})) - - next(w, r) - } -} - -func setup() { - - en, _ := utrans.FindTranslator("en") - en.AddCardinal("days-left", "There is {0} day left", locales.PluralRuleOne, false) - en.AddCardinal("days-left", "There are {0} days left", locales.PluralRuleOther, false) - - fr, _ := utrans.FindTranslator("fr") - fr.AddCardinal("days-left", "Il reste {0} jour", locales.PluralRuleOne, false) - fr.AddCardinal("days-left", "Il reste {0} jours", locales.PluralRuleOther, false) - - err := utrans.VerifyTranslations() - if err != nil { - log.Fatal(err) - } -} diff --git a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/home.tmpl b/vendor/github.com/go-playground/universal-translator/examples/full-with-files/home.tmpl deleted file mode 100644 index 2b37f276319..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/home.tmpl +++ /dev/null @@ -1,35 +0,0 @@ -{{ define "home" }} - - - - Home - - -

Locale: {{ .Trans.Locale }}

-

Trans1: {{ .Trans.C "days-left" 1 0 "1" }}

-

Trans2: {{ .Trans.C "days-left" 2 0 "2" }}

-

FmtNumber Positive: {{ .Trans.FmtNumber .PositiveNum 2 }}

-

FmtNumber Negative: {{ .Trans.FmtNumber .NegativeNum 2 }}

-

FmtPercent Negative: {{ .Trans.FmtPercent .Percent 2 }}

-

FmtCurrency Negative: {{ .Trans.FmtCurrency .PositiveNum 2 .Trans.Currency }}

-

FmtCurrency Negative: {{ .Trans.FmtCurrency .NegativeNum 2 .Trans.Currency }}

-

FmtAccounting Negative: {{ .Trans.FmtAccounting .PositiveNum 2 .Trans.Currency }}

-

FmtAccounting Negative: {{ .Trans.FmtAccounting .NegativeNum 2 .Trans.Currency }}

-

FmtDateShort: {{ .Trans.FmtDateShort .Now }}

-

FmtDateMedium: {{ .Trans.FmtDateMedium .Now }}

-

FmtDateLong: {{ .Trans.FmtDateLong .Now }}

-

FmtDateFull: {{ .Trans.FmtDateFull .Now }}

-

FmtTimeShort: {{ .Trans.FmtTimeShort .Now }}

-

FmtTimeMedium: {{ .Trans.FmtTimeMedium .Now }}

-

FmtTimeLong: {{ .Trans.FmtTimeLong .Now }}

-

FmtTimeFull: {{ .Trans.FmtTimeFull .Now }}

-

MonthsAbbreviated: {{ .Trans.MonthsAbbreviated }}

-

MonthsNarrow: {{ .Trans.MonthsNarrow }}

-

MonthsWide: {{ .Trans.MonthsWide }}

-

WeekdaysAbbreviated: {{ .Trans.WeekdaysAbbreviated }}

-

WeekdaysNarrow: {{ .Trans.WeekdaysNarrow }}

-

WeekdaysShort: {{ .Trans.WeekdaysShort }}

-

WeekdaysWide: {{ .Trans.WeekdaysWide }}

- - -{{ end }} \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/main.go b/vendor/github.com/go-playground/universal-translator/examples/full-with-files/main.go deleted file mode 100644 index 97553ee880c..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/main.go +++ /dev/null @@ -1,207 +0,0 @@ -package main - -import ( - "context" - "html/template" - "log" - "net/http" - "time" - - "github.com/go-playground/locales" - "github.com/go-playground/locales/currency" - "github.com/go-playground/locales/en" - "github.com/go-playground/locales/fr" - "github.com/go-playground/pure" - "github.com/go-playground/pure/examples/middleware/logging-recovery" - "github.com/go-playground/universal-translator" -) - -var ( - tmpls *template.Template - utrans *ut.UniversalTranslator - transKey = struct { - name string - }{ - name: "transKey", - } -) - -// Translator wraps ut.Translator in order to handle errors transparently -// it is totally optional but recommended as it can now be used directly in -// templates and nobody can add translations where they're not supposed to. -type Translator interface { - locales.Translator - - // creates the translation for the locale given the 'key' and params passed in. - // wraps ut.Translator.T to handle errors - T(key interface{}, params ...string) string - - // creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments - // and param passed in. - // wraps ut.Translator.C to handle errors - C(key interface{}, num float64, digits uint64, param string) string - - // creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments - // and param passed in. - // wraps ut.Translator.O to handle errors - O(key interface{}, num float64, digits uint64, param string) string - - // creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and - // 'digit2' arguments and 'param1' and 'param2' passed in - // wraps ut.Translator.R to handle errors - R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string - - // Currency returns the type used by the given locale. - Currency() currency.Type -} - -// implements Translator interface definition above. -type translator struct { - locales.Translator - trans ut.Translator -} - -var _ Translator = (*translator)(nil) - -func (t *translator) T(key interface{}, params ...string) string { - - s, err := t.trans.T(key, params...) - if err != nil { - log.Printf("issue translating key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) C(key interface{}, num float64, digits uint64, param string) string { - - s, err := t.trans.C(key, num, digits, param) - if err != nil { - log.Printf("issue translating cardinal key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) O(key interface{}, num float64, digits uint64, param string) string { - - s, err := t.trans.C(key, num, digits, param) - if err != nil { - log.Printf("issue translating ordinal key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string { - - s, err := t.trans.R(key, num1, digits1, num2, digits2, param1, param2) - if err != nil { - log.Printf("issue translating range key: '%v' error: '%s'", key, err) - } - - return s -} - -func (t *translator) Currency() currency.Type { - - // choose your own locale. The reason it isn't mapped for you is because many - // countries have multiple currencies; it's up to you and you're application how - // and which currencies to use. I recommend adding a function it to to your custon translator - // interface like defined above. - switch t.Locale() { - case "en": - return currency.USD - case "fr": - return currency.EUR - default: - return currency.USD - } -} - -func main() { - - en := en.New() - utrans = ut.New(en, en, fr.New()) - setup() - - tmpls, _ = template.ParseFiles("home.tmpl") - - r := pure.New() - r.Use(middleware.LoggingAndRecovery(true), translatorMiddleware) - r.Get("/", home) - - log.Println("Running on Port :8080") - log.Println("Try me with URL http://localhost:8080/?locale=en") - log.Println("and then http://localhost:8080/?locale=fr") - http.ListenAndServe(":8080", r.Serve()) -} - -func home(w http.ResponseWriter, r *http.Request) { - - // get locale translator ( could be wrapped into a helper function ) - t := r.Context().Value(transKey).(Translator) - - s := struct { - Trans Translator - Now time.Time - PositiveNum float64 - NegativeNum float64 - Percent float64 - }{ - Trans: t, - Now: time.Now(), - PositiveNum: 1234576.45, - NegativeNum: -35900394.34, - Percent: 96.76, - } - - if err := tmpls.ExecuteTemplate(w, "home", s); err != nil { - log.Fatal(err) - } -} - -func translatorMiddleware(next http.HandlerFunc) http.HandlerFunc { - - return func(w http.ResponseWriter, r *http.Request) { - - // there are many ways to check, this is just checking for query param & - // Accept-Language header but can be expanded to Cookie's etc.... - - params := r.URL.Query() - - locale := params.Get("locale") - var t ut.Translator - - if len(locale) > 0 { - - var found bool - - if t, found = utrans.GetTranslator(locale); found { - goto END - } - } - - // get and parse the "Accept-Language" http header and return an array - t, _ = utrans.FindTranslator(pure.AcceptedLanguages(r)...) - END: - // I would normally wrap ut.Translator with one with my own functions in order - // to handle errors and be able to use all functions from translator within the templates. - r = r.WithContext(context.WithValue(r.Context(), transKey, &translator{trans: t, Translator: t.(locales.Translator)})) - - next(w, r) - } -} - -func setup() { - - err := utrans.Import(ut.FormatJSON, "translations") - if err != nil { - log.Fatal(err) - } - - err = utrans.VerifyTranslations() - if err != nil { - log.Fatal(err) - } -} diff --git a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/translations/en/home.json b/vendor/github.com/go-playground/universal-translator/examples/full-with-files/translations/en/home.json deleted file mode 100644 index 395b66f60fd..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/translations/en/home.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "locale": "en", - "key": "days-left", - "trans": "There is {0} day left", - "type": "Cardinal", - "rule": "One" - }, - { - "locale": "en", - "key": "days-left", - "trans": "There are {0} days left", - "type": "Cardinal", - "rule": "Other" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/translations/fr/home.json b/vendor/github.com/go-playground/universal-translator/examples/full-with-files/translations/fr/home.json deleted file mode 100644 index e694bd775e6..00000000000 --- a/vendor/github.com/go-playground/universal-translator/examples/full-with-files/translations/fr/home.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "locale": "fr", - "key": "days-left", - "trans": "Il reste {0} jour", - "type": "Cardinal", - "rule": "One" - }, - { - "locale": "fr", - "key": "days-left", - "trans": "Il reste {0} jours", - "type": "Cardinal", - "rule": "Other" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/.gitignore b/vendor/github.com/go-playground/universal-translator/testdata/.gitignore deleted file mode 100644 index 1b452a52311..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -* - -!.gitignore -!*/ -!bad-translation1.json -!bad-translation2.json -!bad-translation3.json -!bad-translation4.json -!bad-translation5.json -!bad-translation6.json -!/nested1/** \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation1.json b/vendor/github.com/go-playground/universal-translator/testdata/bad-translation1.json deleted file mode 100644 index baba335b008..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation1.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "locale": "en", - "key": "test_trans3", - "trans": "Welcome {lettersnotpermitted} to the {1}" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation2.json b/vendor/github.com/go-playground/universal-translator/testdata/bad-translation2.json deleted file mode 100644 index 92692375b01..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation2.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "locale": "en", - "key": "test_trans3", - "trans": "Welcome {0 to the {1}" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation3.json b/vendor/github.com/go-playground/universal-translator/testdata/bad-translation3.json deleted file mode 100644 index 0e742a877ca..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation3.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "locale": "nl", - "key": "test_trans3", - "trans": "Welcome {0 to the {1}" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation4.json b/vendor/github.com/go-playground/universal-translator/testdata/bad-translation4.json deleted file mode 100644 index 51609d7d69f..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation4.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "locale": "en", - "key": "cardinal_test", - "trans": "You have {0} day left.", - "type": "NotAPluralType", - "rule": "One" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation5.json b/vendor/github.com/go-playground/universal-translator/testdata/bad-translation5.json deleted file mode 100644 index 880c1dafd59..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation5.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "locale": "en", - "key": "cardinal_test", - "trans": "You have {0} day left.", - "type": "Cardinal", - "rule": "Many" - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation6.json b/vendor/github.com/go-playground/universal-translator/testdata/bad-translation6.json deleted file mode 100644 index d93208f7818..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/bad-translation6.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "locale": "en", - "key": "cardinal_test", - "trans": "You have {0} day left.", - "type": "Cardinal", - "rule": "Many" - -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested1.json b/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested1.json deleted file mode 100644 index 3d9ce536161..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested1.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "locale": "en", - "key": -1, - "trans": "Welcome {0}" - }, - { - "locale": "en", - "key": "test_trans2", - "trans": "{0} to the {1}." - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested2/nested2.json b/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested2/nested2.json deleted file mode 100644 index c1d90170eed..00000000000 --- a/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested2/nested2.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "locale": "en", - "key": "test_trans3", - "trans": "Welcome {0} to the {1}" - }, - { - "locale": "en", - "key": "test_trans4", - "trans": "{0}{1}" - }, - { - "locale": "en", - "key": "test_trans", - "trans": "Welcome {0} to the {1}." - } -] \ No newline at end of file diff --git a/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested2/unrelated-file.txt b/vendor/github.com/go-playground/universal-translator/testdata/nested1/nested2/unrelated-file.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/vendor/github.com/golang/mock/AUTHORS b/vendor/github.com/golang/mock/AUTHORS new file mode 100644 index 00000000000..660b8ccc8ae --- /dev/null +++ b/vendor/github.com/golang/mock/AUTHORS @@ -0,0 +1,12 @@ +# This is the official list of GoMock authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. + +Alex Reece +Google Inc. diff --git a/vendor/github.com/golang/mock/CONTRIBUTORS b/vendor/github.com/golang/mock/CONTRIBUTORS new file mode 100644 index 00000000000..def849cab1b --- /dev/null +++ b/vendor/github.com/golang/mock/CONTRIBUTORS @@ -0,0 +1,37 @@ +# This is the official list of people who can contribute (and typically +# have contributed) code to the gomock repository. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# The submission process automatically checks to make sure +# that people submitting code are listed in this file (by email address). +# +# Names should be added to this file only after verifying that +# the individual or the individual's organization has agreed to +# the appropriate Contributor License Agreement, found here: +# +# http://code.google.com/legal/individual-cla-v1.0.html +# http://code.google.com/legal/corporate-cla-v1.0.html +# +# The agreement for individuals can be filled out on the web. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file, depending on whether the +# individual or corporate CLA was used. + +# Names should be added to this file like so: +# Name +# +# An entry with two email addresses specifies that the +# first address should be used in the submit logs and +# that the second address should be recognized as the +# same person when interacting with Rietveld. + +# Please keep the list sorted. + +Aaron Jacobs +Alex Reece +David Symonds +Ryan Barrett diff --git a/vendor/github.com/karalabe/gousb/LICENSE b/vendor/github.com/golang/mock/LICENSE similarity index 100% rename from vendor/github.com/karalabe/gousb/LICENSE rename to vendor/github.com/golang/mock/LICENSE diff --git a/vendor/github.com/golang/mock/gomock/call.go b/vendor/github.com/golang/mock/gomock/call.go index dc2a479d112..cc8dfffeb6c 100644 --- a/vendor/github.com/golang/mock/gomock/call.go +++ b/vendor/github.com/golang/mock/gomock/call.go @@ -17,7 +17,6 @@ package gomock import ( "fmt" "reflect" - "strconv" "strings" ) @@ -30,7 +29,6 @@ type Call struct { methodType reflect.Type // the type of the method args []Matcher // the args rets []interface{} // the return values (if any) - origin string // file and line number of call setup preReqs []*Call // prerequisite calls @@ -81,8 +79,8 @@ func (c *Call) Do(f interface{}) *Call { func (c *Call) Return(rets ...interface{}) *Call { mt := c.methodType if len(rets) != mt.NumOut() { - c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]", - c.receiver, c.method, len(rets), mt.NumOut(), c.origin) + c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d", + c.receiver, c.method, len(rets), mt.NumOut()) } for i, ret := range rets { if got, want := reflect.TypeOf(ret), mt.Out(i); got == want { @@ -93,8 +91,8 @@ func (c *Call) Return(rets ...interface{}) *Call { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: // ok default: - c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]", - i, c.receiver, c.method, want, c.origin) + c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable", + i, c.receiver, c.method, want) } } else if got.AssignableTo(want) { // Assignable type relation. Make the assignment now so that the generated code @@ -103,8 +101,8 @@ func (c *Call) Return(rets ...interface{}) *Call { v.Set(reflect.ValueOf(ret)) rets[i] = v.Interface() } else { - c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]", - i, c.receiver, c.method, got, want, c.origin) + c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v", + i, c.receiver, c.method, got, want) } } @@ -118,8 +116,7 @@ func (c *Call) Times(n int) *Call { } // SetArg declares an action that will set the nth argument's value, -// indirected through a pointer. Or, in the case of a slice, SetArg -// will copy value's elements into the nth argument. +// indirected through a pointer. func (c *Call) SetArg(n int, value interface{}) *Call { if c.setArgs == nil { c.setArgs = make(map[int]reflect.Value) @@ -128,8 +125,7 @@ func (c *Call) SetArg(n int, value interface{}) *Call { // TODO: This will break on variadic methods. // We will need to check those at invocation time. if n < 0 || n >= mt.NumIn() { - c.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]", - n, mt.NumIn(), c.origin) + c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn()) } // Permit setting argument through an interface. // In the interface case, we don't (nay, can't) check the type here. @@ -138,16 +134,12 @@ func (c *Call) SetArg(n int, value interface{}) *Call { case reflect.Ptr: dt := at.Elem() if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) { - c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]", - n, vt, dt, c.origin) + c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt) } case reflect.Interface: // nothing to do - case reflect.Slice: - // nothing to do default: - c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v", - n, at, c.origin) + c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at) } c.setArgs[n] = reflect.ValueOf(value) return c @@ -166,7 +158,7 @@ func (c *Call) isPreReq(other *Call) bool { // After declares that the call may only match after preReq has been exhausted. func (c *Call) After(preReq *Call) *Call { if c == preReq { - c.t.Fatalf("A call isn't allowed to be its own prerequisite") + c.t.Fatalf("A call isn't allowed to be it's own prerequisite") } if preReq.isPreReq(c) { c.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", c, preReq) @@ -176,7 +168,7 @@ func (c *Call) After(preReq *Call) *Call { return c } -// Returns true if the minimum number of calls have been made. +// Returns true iff the minimum number of calls have been made. func (c *Call) satisfied() bool { return c.numCalls >= c.minCalls } @@ -192,35 +184,31 @@ func (c *Call) String() string { args[i] = arg.String() } arguments := strings.Join(args, ", ") - return fmt.Sprintf("%T.%v(%s) %s", c.receiver, c.method, arguments, c.origin) + return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments) } // Tests if the given call matches the expected call. -// If yes, returns nil. If no, returns error with message explaining why it does not match. -func (c *Call) matches(args []interface{}) error { +func (c *Call) matches(args []interface{}) bool { if len(args) != len(c.args) { - return fmt.Errorf("Expected call at %s has the wrong number of arguments. Got: %s, want: %s", - c.origin, strconv.Itoa(len(args)), strconv.Itoa(len(c.args))) + return false } for i, m := range c.args { if !m.Matches(args[i]) { - return fmt.Errorf("Expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v\n", - c.origin, strconv.Itoa(i), args[i], m) + return false } } // Check that all prerequisite calls have been satisfied. for _, preReqCall := range c.preReqs { if !preReqCall.satisfied() { - return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v", - c.origin, preReqCall, c) + return false } } - return nil + return true } -// dropPrereqs tells the expected Call to not re-check prerequisite calls any +// dropPrereqs tells the expected Call to not re-check prerequite calls any // longer, and to return its current set. func (c *Call) dropPrereqs() (preReqs []*Call) { preReqs = c.preReqs @@ -246,12 +234,7 @@ func (c *Call) call(args []interface{}) (rets []interface{}, action func()) { action = func() { c.doFunc.Call(doArgs) } } for n, v := range c.setArgs { - switch reflect.TypeOf(args[n]).Kind() { - case reflect.Slice: - setSlice(args[n], v) - default: - reflect.ValueOf(args[n]).Elem().Set(v) - } + reflect.ValueOf(args[n]).Elem().Set(v) } rets = c.rets @@ -273,10 +256,3 @@ func InOrder(calls ...*Call) { calls[i].After(calls[i-1]) } } - -func setSlice(arg interface{}, v reflect.Value) { - va := reflect.ValueOf(arg) - for i := 0; i < v.Len(); i++ { - va.Index(i).Set(v.Index(i)) - } -} diff --git a/vendor/github.com/golang/mock/gomock/callset.go b/vendor/github.com/golang/mock/gomock/callset.go index a88a172f846..1b7de4c0b32 100644 --- a/vendor/github.com/golang/mock/gomock/callset.go +++ b/vendor/github.com/golang/mock/gomock/callset.go @@ -14,11 +14,6 @@ package gomock -import ( - "errors" - "fmt" -) - // callSet represents a set of expected calls, indexed by receiver and method // name. type callSet map[interface{}]map[string][]*Call @@ -52,35 +47,30 @@ func (cs callSet) Remove(call *Call) { } } -// FindMatch searches for a matching call. Returns error with explanation message if no call matched. -func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) { +// FindMatch searches for a matching call. Returns nil if no call matched. +func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) *Call { methodMap, ok := cs[receiver] if !ok { - return nil, errors.New("there are no expected method calls for that receiver") + return nil } calls, ok := methodMap[method] if !ok { - return nil, fmt.Errorf("there are no expected calls of the method: %s for that receiver", method) + return nil } // Search through the unordered set of calls expected on a method on a // receiver. - callsErrors := "" for _, call := range calls { // A call should not normally still be here if exhausted, // but it can happen if, for instance, .Times(0) was used. // Pretend the call doesn't match. if call.exhausted() { - callsErrors += "\nThe call was exhausted." continue } - err := call.matches(args) - if err != nil { - callsErrors += "\n" + err.Error() - } else { - return call, nil + if call.matches(args) { + return call } } - return nil, fmt.Errorf(callsErrors) + return nil } diff --git a/vendor/github.com/golang/mock/gomock/controller.go b/vendor/github.com/golang/mock/gomock/controller.go index d06dfbbe852..6bff78d1dce 100644 --- a/vendor/github.com/golang/mock/gomock/controller.go +++ b/vendor/github.com/golang/mock/gomock/controller.go @@ -58,7 +58,6 @@ package gomock import ( "fmt" "reflect" - "runtime" "sync" ) @@ -115,8 +114,7 @@ func (ctrl *Controller) RecordCallWithMethodType(receiver interface{}, method st ctrl.mu.Lock() defer ctrl.mu.Unlock() - origin := callerInfo(2) - call := &Call{t: ctrl.t, receiver: receiver, method: method, methodType: methodType, args: margs, origin: origin, minCalls: 1, maxCalls: 1} + call := &Call{t: ctrl.t, receiver: receiver, method: method, methodType: methodType, args: margs, minCalls: 1, maxCalls: 1} ctrl.expectedCalls.Add(call) return call @@ -126,10 +124,9 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf ctrl.mu.Lock() defer ctrl.mu.Unlock() - expected, err := ctrl.expectedCalls.FindMatch(receiver, method, args) - if err != nil { - origin := callerInfo(2) - ctrl.t.Fatalf("Unexpected call to %T.%v(%v) at %s because: %s", receiver, method, args, origin, err) + expected := ctrl.expectedCalls.FindMatch(receiver, method, args) + if expected == nil { + ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args) } // Two things happen here: @@ -184,10 +181,3 @@ func (ctrl *Controller) Finish() { ctrl.t.Fatalf("aborting test due to missing call(s)") } } - -func callerInfo(skip int) string { - if _, file, line, ok := runtime.Caller(skip + 1); ok { - return fmt.Sprintf("%s:%d", file, line) - } - return "unknown file" -} diff --git a/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go b/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go deleted file mode 100644 index 3328ab7a0a4..00000000000 --- a/vendor/github.com/golang/mock/gomock/mock_matcher/mock_matcher.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/golang/mock/gomock (interfaces: Matcher) - -package mock_gomock - -import ( - gomock "github.com/golang/mock/gomock" - reflect "reflect" -) - -// MockMatcher is a mock of Matcher interface -type MockMatcher struct { - ctrl *gomock.Controller - recorder *MockMatcherMockRecorder -} - -// MockMatcherMockRecorder is the mock recorder for MockMatcher -type MockMatcherMockRecorder struct { - mock *MockMatcher -} - -// NewMockMatcher creates a new mock instance -func NewMockMatcher(ctrl *gomock.Controller) *MockMatcher { - mock := &MockMatcher{ctrl: ctrl} - mock.recorder = &MockMatcherMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockMatcher) EXPECT() *MockMatcherMockRecorder { - return m.recorder -} - -// Matches mocks base method -func (m *MockMatcher) Matches(arg0 interface{}) bool { - ret := m.ctrl.Call(m, "Matches", arg0) - ret0, _ := ret[0].(bool) - return ret0 -} - -// Matches indicates an expected call of Matches -func (mr *MockMatcherMockRecorder) Matches(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Matches", reflect.TypeOf((*MockMatcher)(nil).Matches), arg0) -} - -// String mocks base method -func (m *MockMatcher) String() string { - ret := m.ctrl.Call(m, "String") - ret0, _ := ret[0].(string) - return ret0 -} - -// String indicates an expected call of String -func (mr *MockMatcherMockRecorder) String() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "String", reflect.TypeOf((*MockMatcher)(nil).String)) -} diff --git a/vendor/github.com/golang/protobuf/AUTHORS b/vendor/github.com/golang/protobuf/AUTHORS new file mode 100644 index 00000000000..15167cd746c --- /dev/null +++ b/vendor/github.com/golang/protobuf/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/golang/protobuf/CONTRIBUTORS b/vendor/github.com/golang/protobuf/CONTRIBUTORS new file mode 100644 index 00000000000..1c4577e9680 --- /dev/null +++ b/vendor/github.com/golang/protobuf/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/golang/snappy/encode.go b/vendor/github.com/golang/snappy/encode.go index 87496890609..8d393e904bb 100644 --- a/vendor/github.com/golang/snappy/encode.go +++ b/vendor/github.com/golang/snappy/encode.go @@ -138,7 +138,7 @@ func NewBufferedWriter(w io.Writer) *Writer { } } -// Writer is an io.Writer than can write Snappy-compressed bytes. +// Writer is an io.Writer that can write Snappy-compressed bytes. type Writer struct { w io.Writer err error diff --git a/vendor/github.com/golang/snappy/snappy.go b/vendor/github.com/golang/snappy/snappy.go index c7f445f62c6..0cf5e379c47 100644 --- a/vendor/github.com/golang/snappy/snappy.go +++ b/vendor/github.com/golang/snappy/snappy.go @@ -6,7 +6,7 @@ // It aims for very high speeds and reasonable compression. // // The C++ snappy implementation is at https://github.com/google/snappy -package snappy +package snappy // import "github.com/golang/snappy" import ( "hash/crc32" diff --git a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go index 68d097a1c06..cb416b394f2 100644 --- a/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go @@ -47,7 +47,7 @@ func (c *LRU) Purge() { c.evictList.Init() } -// Add adds a value to the cache. Returns true if an eviction occured. +// Add adds a value to the cache. Returns true if an eviction occurred. func (c *LRU) Add(key, value interface{}) bool { // Check for existing item if ent, ok := c.items[key]; ok { diff --git a/vendor/github.com/huin/goupnp/README.md b/vendor/github.com/huin/goupnp/README.md index a228ccea640..433ba5c6825 100644 --- a/vendor/github.com/huin/goupnp/README.md +++ b/vendor/github.com/huin/goupnp/README.md @@ -8,18 +8,18 @@ Run `go get -u github.com/huin/goupnp`. Documentation ------------- -All doc links below are for ![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg). - Supported DCPs (you probably want to start with one of these): -* [av1](https://godoc.org/github.com/huin/goupnp/dcps/av1) - Client for UPnP Device Control Protocol MediaServer v1 and MediaRenderer v1. -* [internetgateway1](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway1) - Client for UPnP Device Control Protocol Internet Gateway Device v1. -* [internetgateway2](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway2) - Client for UPnP Device Control Protocol Internet Gateway Device v2. + +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) av1](https://godoc.org/github.com/huin/goupnp/dcps/av1) - Client for UPnP Device Control Protocol MediaServer v1 and MediaRenderer v1. +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) internetgateway1](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway1) - Client for UPnP Device Control Protocol Internet Gateway Device v1. +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) internetgateway2](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway2) - Client for UPnP Device Control Protocol Internet Gateway Device v2. Core components: -* [(goupnp)](https://godoc.org/github.com/huin/goupnp) core library - contains datastructures and utilities typically used by the implemented DCPs. -* [httpu](https://godoc.org/github.com/huin/goupnp/httpu) HTTPU implementation, underlies SSDP. -* [ssdp](https://godoc.org/github.com/huin/goupnp/ssdp) SSDP client implementation (simple service discovery protocol) - used to discover UPnP services on a network. -* [soap](https://godoc.org/github.com/huin/goupnp/soap) SOAP client implementation (simple object access protocol) - used to communicate with discovered services. + +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) (goupnp)](https://godoc.org/github.com/huin/goupnp) core library - contains datastructures and utilities typically used by the implemented DCPs. +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) httpu](https://godoc.org/github.com/huin/goupnp/httpu) HTTPU implementation, underlies SSDP. +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) ssdp](https://godoc.org/github.com/huin/goupnp/ssdp) SSDP client implementation (simple service discovery protocol) - used to discover UPnP services on a network. +* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) soap](https://godoc.org/github.com/huin/goupnp/soap) SOAP client implementation (simple object access protocol) - used to communicate with discovered services. Regenerating dcps generated source code: diff --git a/vendor/github.com/huin/goupnp/httpu/httpu.go b/vendor/github.com/huin/goupnp/httpu/httpu.go index 862c3def42f..f52dad68b10 100644 --- a/vendor/github.com/huin/goupnp/httpu/httpu.go +++ b/vendor/github.com/huin/goupnp/httpu/httpu.go @@ -3,6 +3,7 @@ package httpu import ( "bufio" "bytes" + "errors" "fmt" "log" "net" @@ -28,6 +29,20 @@ func NewHTTPUClient() (*HTTPUClient, error) { return &HTTPUClient{conn: conn}, nil } +// NewHTTPUClientAddr creates a new HTTPUClient which will broadcast packets +// from the specified address, opening up a new UDP socket for the purpose +func NewHTTPUClientAddr(addr string) (*HTTPUClient, error) { + ip := net.ParseIP(addr) + if ip == nil { + return nil, errors.New("Invalid listening address") + } + conn, err := net.ListenPacket("udp", ip.String()+":0") + if err != nil { + return nil, err + } + return &HTTPUClient{conn: conn}, nil +} + // Close shuts down the client. The client will no longer be useful following // this. func (httpu *HTTPUClient) Close() error { diff --git a/vendor/github.com/huin/goupnp/ssdp/registry.go b/vendor/github.com/huin/goupnp/ssdp/registry.go index 2f84beaae9f..d3bc114463a 100644 --- a/vendor/github.com/huin/goupnp/ssdp/registry.go +++ b/vendor/github.com/huin/goupnp/ssdp/registry.go @@ -18,7 +18,7 @@ const ( ) var ( - maxAgeRx = regexp.MustCompile("max-age=([0-9]+)") + maxAgeRx = regexp.MustCompile("max-age= *([0-9]+)") ) const ( diff --git a/vendor/github.com/karalabe/gousb/.gitignore b/vendor/github.com/karalabe/gousb/.gitignore deleted file mode 100644 index dbec55fb6f4..00000000000 --- a/vendor/github.com/karalabe/gousb/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.sw[op] diff --git a/vendor/github.com/karalabe/gousb/.travis.yml b/vendor/github.com/karalabe/gousb/.travis.yml deleted file mode 100644 index 2029cc478e6..00000000000 --- a/vendor/github.com/karalabe/gousb/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go - -matrix: - include: - - os: linux - dist: trusty - go: 1.7.4 - - os: osx - go: 1.7.4 - -script: - - go test -v -test.run='BCD|Parse' ./... diff --git a/vendor/github.com/karalabe/gousb/README.md b/vendor/github.com/karalabe/gousb/README.md deleted file mode 100644 index 05f3330031d..00000000000 --- a/vendor/github.com/karalabe/gousb/README.md +++ /dev/null @@ -1,47 +0,0 @@ -Introduction -============ - -[![Travis Build Status][travisimg]][travis] -[![AppVeyor Build Status][appveyorimg]][appveyor] -[![GoDoc][docimg]][doc] - -The gousb package is an attempt at wrapping the `libusb` library into a Go-like binding in a fully self-contained, go-gettable package. Supported platforms include Linux, macOS and Windows as well as the mobile platforms Android and iOS. - -This package is a fork of [`github.com/kylelemons/gousb`](https://github.com/kylelemons/gousb), which at the moment seems to be unmaintained. The current fork is different from the upstream package as it contains code to embed `libusb` directly into the Go package (thus becoming fully self-cotnained and go-gettable), as well as it features a few contributions and bugfixes that never really got addressed in the upstream package, but which address important issues nonetheless. - -*Note, if @kylelemons decides to pick development of the upstream project up again, consider all commits made by me to this repo as ready contributions. I cannot vouch for other commits as the upstream repo needs a signed CLA for Google.* - -[travisimg]: https://travis-ci.org/karalabe/gousb.svg?branch=master -[travis]: https://travis-ci.org/karalabe/gousb -[appveyorimg]: https://ci.appveyor.com/api/projects/status/84k9xse10rl72gn2/branch/master?svg=true -[appveyor]: https://ci.appveyor.com/project/karalabe/gousb -[docimg]: https://godoc.org/github.com/karalabe/gousb?status.svg -[doc]: https://godoc.org/github.com/karalabe/gousb - -Installation -============ - -Example: lsusb --------------- -The gousb project provides a simple but useful example: lsusb. This binary will list the USB devices connected to your system and various interesting tidbits about them, their configurations, endpoints, etc. To install it, run the following command: - - go get -v github.com/karalabe/gousb/lsusb - -gousb ------ -If you installed the lsusb example, both libraries below are already installed. - -Installing the primary gousb package is really easy: - - go get -v github.com/karalabe/gousb/usb - -There is also a `usbid` package that will not be installed by default by this command, but which provides useful information including the human-readable vendor and product codes for detected hardware. It's not installed by default and not linked into the `usb` package by default because it adds ~400kb to the resulting binary. If you want both, they can be installed thus: - - go get -v github.com/karalabe/gousb/usb{,id} - -Documentation -============= -The documentation can be viewed via local godoc or via the excellent [godoc.org](http://godoc.org/): - -- [usb](http://godoc.org/github.com/karalabe/gousb/usb) -- [usbid](http://godoc.org/pkg/github.com/karalabe/gousb/usbid) diff --git a/vendor/github.com/karalabe/gousb/appveyor.yml b/vendor/github.com/karalabe/gousb/appveyor.yml deleted file mode 100644 index b2498620228..00000000000 --- a/vendor/github.com/karalabe/gousb/appveyor.yml +++ /dev/null @@ -1,34 +0,0 @@ -os: Visual Studio 2015 - -# Clone directly into GOPATH. -clone_folder: C:\gopath\src\github.com\karalabe\gousb -clone_depth: 5 -version: "{branch}.{build}" -environment: - global: - GOPATH: C:\gopath - CC: gcc.exe - matrix: - - GOARCH: amd64 - MSYS2_ARCH: x86_64 - MSYS2_BITS: 64 - MSYSTEM: MINGW64 - PATH: C:\msys64\mingw64\bin\;%PATH% - - GOARCH: 386 - MSYS2_ARCH: i686 - MSYS2_BITS: 32 - MSYSTEM: MINGW32 - PATH: C:\msys64\mingw32\bin\;%PATH% - -install: - - rmdir C:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go1.7.4.windows-%GOARCH%.zip - - 7z x go1.7.4.windows-%GOARCH%.zip -y -oC:\ > NUL - - go version - - gcc --version - -build_script: - - go install ./... - -test_script: - - go test -v -test.run="BCD|Parse" ./... diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/AUTHORS b/vendor/github.com/karalabe/gousb/internal/libusb/AUTHORS deleted file mode 100644 index 70d407bd19f..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/AUTHORS +++ /dev/null @@ -1,89 +0,0 @@ -Copyright © 2001 Johannes Erdfelt -Copyright © 2007-2009 Daniel Drake -Copyright © 2010-2012 Peter Stuge -Copyright © 2008-2016 Nathan Hjelm -Copyright © 2009-2013 Pete Batard -Copyright © 2009-2013 Ludovic Rousseau -Copyright © 2010-2012 Michael Plante -Copyright © 2011-2013 Hans de Goede -Copyright © 2012-2013 Martin Pieuchot -Copyright © 2012-2013 Toby Gray -Copyright © 2013-2015 Chris Dickens - -Other contributors: -Akshay Jaggi -Alan Ott -Alan Stern -Alex Vatchenko -Andrew Fernandes -Anthony Clay -Antonio Ospite -Artem Egorkine -Aurelien Jarno -Bastien Nocera -Bei Zhang -Benjamin Dobell -Carl Karsten -Colin Walters -Dave Camarillo -David Engraf -David Moore -Davidlohr Bueso -Federico Manzan -Felipe Balbi -Florian Albrechtskirchinger -Francesco Montorsi -Francisco Facioni -Gaurav Gupta -Graeme Gill -Gustavo Zacarias -Hans Ulrich Niedermann -Hector Martin -Hoi-Ho Chan -Ilya Konstantinov -James Hanko -John Sheu -Joshua Blake -Justin Bischoff -Karsten Koenig -Konrad Rzepecki -Kuangye Guo -Lars Kanis -Lars Wirzenius -Luca Longinotti -Marcus Meissner -Markus Heidelberg -Martin Ettl -Martin Koegler -Matthias Bolte -Mike Frysinger -Mikhail Gusarov -Moritz Fischer -Ларионов Даниил -Nicholas Corgan -Omri Iluz -Orin Eman -Paul Fertser -Pekka Nikander -Rob Walker -Sean McBride -Sebastian Pipping -Simon Haggett -Simon Newton -Thomas Röfer -Tim Hutt -Tim Roberts -Tobias Klauser -Toby Peterson -Tormod Volden -Trygve Laugstøl -Uri Lublin -Vasily Khoruzhick -Vegard Storheil Eriksen -Venkatesh Shukla -Vitali Lovich -Xiaofan Chen -Zoltán Kovács -Роман Донченко -parafin -xantares diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/COPYING b/vendor/github.com/karalabe/gousb/internal/libusb/COPYING deleted file mode 100644 index 5ab7695ab8c..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/config.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/config.h deleted file mode 100644 index e004f03cd46..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/config.h +++ /dev/null @@ -1,3 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/core.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/core.c deleted file mode 100644 index d45bfe177e7..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/core.c +++ /dev/null @@ -1,2523 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * Core functions for libusb - * Copyright © 2012-2013 Nathan Hjelm - * Copyright © 2007-2008 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_SYSLOG_H -#include -#endif - -#ifdef __ANDROID__ -#include -#endif - -#include "libusbi.h" -#include "hotplug.h" - -#if defined(OS_LINUX) -const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend; -#elif defined(OS_DARWIN) -const struct usbi_os_backend * const usbi_backend = &darwin_backend; -#elif defined(OS_OPENBSD) -const struct usbi_os_backend * const usbi_backend = &openbsd_backend; -#elif defined(OS_NETBSD) -const struct usbi_os_backend * const usbi_backend = &netbsd_backend; -#elif defined(OS_WINDOWS) - -#if defined(USE_USBDK) -const struct usbi_os_backend * const usbi_backend = &usbdk_backend; -#else -const struct usbi_os_backend * const usbi_backend = &windows_backend; -#endif - -#elif defined(OS_WINCE) -const struct usbi_os_backend * const usbi_backend = &wince_backend; -#elif defined(OS_HAIKU) -const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend; -#elif defined (OS_SUNOS) -const struct usbi_os_backend * const usbi_backend = &sunos_backend; -#else -#error "Unsupported OS" -#endif - -struct libusb_context *usbi_default_context = NULL; -static const struct libusb_version libusb_version_internal = - { LIBUSB_MAJOR, LIBUSB_MINOR, LIBUSB_MICRO, LIBUSB_NANO, - LIBUSB_RC, "http://libusb.info" }; -static int default_context_refcnt = 0; -static usbi_mutex_static_t default_context_lock = USBI_MUTEX_INITIALIZER; -static struct timespec timestamp_origin = { 0, 0 }; - -usbi_mutex_static_t active_contexts_lock = USBI_MUTEX_INITIALIZER; -struct list_head active_contexts_list; - -/** - * \mainpage libusb-1.0 API Reference - * - * \section intro Introduction - * - * libusb is an open source library that allows you to communicate with USB - * devices from userspace. For more info, see the - * libusb homepage. - * - * This documentation is aimed at application developers wishing to - * communicate with USB peripherals from their own software. After reviewing - * this documentation, feedback and questions can be sent to the - * libusb-devel mailing list. - * - * This documentation assumes knowledge of how to operate USB devices from - * a software standpoint (descriptors, configurations, interfaces, endpoints, - * control/bulk/interrupt/isochronous transfers, etc). Full information - * can be found in the USB 3.0 - * Specification which is available for free download. You can probably - * find less verbose introductions by searching the web. - * - * \section API Application Programming Interface (API) - * - * See the \ref libusb_api page for a complete list of the libusb functions. - * - * \section features Library features - * - * - All transfer types supported (control/bulk/interrupt/isochronous) - * - 2 transfer interfaces: - * -# Synchronous (simple) - * -# Asynchronous (more complicated, but more powerful) - * - Thread safe (although the asynchronous interface means that you - * usually won't need to thread) - * - Lightweight with lean API - * - Compatible with libusb-0.1 through the libusb-compat-0.1 translation layer - * - Hotplug support (on some platforms). See \ref libusb_hotplug. - * - * \section gettingstarted Getting Started - * - * To begin reading the API documentation, start with the Modules page which - * links to the different categories of libusb's functionality. - * - * One decision you will have to make is whether to use the synchronous - * or the asynchronous data transfer interface. The \ref libusb_io documentation - * provides some insight into this topic. - * - * Some example programs can be found in the libusb source distribution under - * the "examples" subdirectory. The libusb homepage includes a list of - * real-life project examples which use libusb. - * - * \section errorhandling Error handling - * - * libusb functions typically return 0 on success or a negative error code - * on failure. These negative error codes relate to LIBUSB_ERROR constants - * which are listed on the \ref libusb_misc "miscellaneous" documentation page. - * - * \section msglog Debug message logging - * - * libusb uses stderr for all logging. By default, logging is set to NONE, - * which means that no output will be produced. However, unless the library - * has been compiled with logging disabled, then any application calls to - * libusb_set_debug(), or the setting of the environmental variable - * LIBUSB_DEBUG outside of the application, can result in logging being - * produced. Your application should therefore not close stderr, but instead - * direct it to the null device if its output is undesirable. - * - * The libusb_set_debug() function can be used to enable logging of certain - * messages. Under standard configuration, libusb doesn't really log much - * so you are advised to use this function to enable all error/warning/ - * informational messages. It will help debug problems with your software. - * - * The logged messages are unstructured. There is no one-to-one correspondence - * between messages being logged and success or failure return codes from - * libusb functions. There is no format to the messages, so you should not - * try to capture or parse them. They are not and will not be localized. - * These messages are not intended to being passed to your application user; - * instead, you should interpret the error codes returned from libusb functions - * and provide appropriate notification to the user. The messages are simply - * there to aid you as a programmer, and if you're confused because you're - * getting a strange error code from a libusb function, enabling message - * logging may give you a suitable explanation. - * - * The LIBUSB_DEBUG environment variable can be used to enable message logging - * at run-time. This environment variable should be set to a log level number, - * which is interpreted the same as the libusb_set_debug() parameter. When this - * environment variable is set, the message logging verbosity level is fixed - * and libusb_set_debug() effectively does nothing. - * - * libusb can be compiled without any logging functions, useful for embedded - * systems. In this case, libusb_set_debug() and the LIBUSB_DEBUG environment - * variable have no effects. - * - * libusb can also be compiled with verbose debugging messages always. When - * the library is compiled in this way, all messages of all verbosities are - * always logged. libusb_set_debug() and the LIBUSB_DEBUG environment variable - * have no effects. - * - * \section remarks Other remarks - * - * libusb does have imperfections. The \ref libusb_caveats "caveats" page attempts - * to document these. - */ - -/** - * \page libusb_caveats Caveats - * - * \section devresets Device resets - * - * The libusb_reset_device() function allows you to reset a device. If your - * program has to call such a function, it should obviously be aware that - * the reset will cause device state to change (e.g. register values may be - * reset). - * - * The problem is that any other program could reset the device your program - * is working with, at any time. libusb does not offer a mechanism to inform - * you when this has happened, so if someone else resets your device it will - * not be clear to your own program why the device state has changed. - * - * Ultimately, this is a limitation of writing drivers in userspace. - * Separation from the USB stack in the underlying kernel makes it difficult - * for the operating system to deliver such notifications to your program. - * The Linux kernel USB stack allows such reset notifications to be delivered - * to in-kernel USB drivers, but it is not clear how such notifications could - * be delivered to second-class drivers that live in userspace. - * - * \section blockonly Blocking-only functionality - * - * The functionality listed below is only available through synchronous, - * blocking functions. There are no asynchronous/non-blocking alternatives, - * and no clear ways of implementing these. - * - * - Configuration activation (libusb_set_configuration()) - * - Interface/alternate setting activation (libusb_set_interface_alt_setting()) - * - Releasing of interfaces (libusb_release_interface()) - * - Clearing of halt/stall condition (libusb_clear_halt()) - * - Device resets (libusb_reset_device()) - * - * \section configsel Configuration selection and handling - * - * When libusb presents a device handle to an application, there is a chance - * that the corresponding device may be in unconfigured state. For devices - * with multiple configurations, there is also a chance that the configuration - * currently selected is not the one that the application wants to use. - * - * The obvious solution is to add a call to libusb_set_configuration() early - * on during your device initialization routines, but there are caveats to - * be aware of: - * -# If the device is already in the desired configuration, calling - * libusb_set_configuration() using the same configuration value will cause - * a lightweight device reset. This may not be desirable behaviour. - * -# In the case where the desired configuration is already active, libusb - * may not even be able to perform a lightweight device reset. For example, - * take my USB keyboard with fingerprint reader: I'm interested in driving - * the fingerprint reader interface through libusb, but the kernel's - * USB-HID driver will almost always have claimed the keyboard interface. - * Because the kernel has claimed an interface, it is not even possible to - * perform the lightweight device reset, so libusb_set_configuration() will - * fail. (Luckily the device in question only has a single configuration.) - * -# libusb will be unable to set a configuration if other programs or - * drivers have claimed interfaces. In particular, this means that kernel - * drivers must be detached from all the interfaces before - * libusb_set_configuration() may succeed. - * - * One solution to some of the above problems is to consider the currently - * active configuration. If the configuration we want is already active, then - * we don't have to select any configuration: -\code -cfg = -1; -libusb_get_configuration(dev, &cfg); -if (cfg != desired) - libusb_set_configuration(dev, desired); -\endcode - * - * This is probably suitable for most scenarios, but is inherently racy: - * another application or driver may change the selected configuration - * after the libusb_get_configuration() call. - * - * Even in cases where libusb_set_configuration() succeeds, consider that other - * applications or drivers may change configuration after your application - * calls libusb_set_configuration(). - * - * One possible way to lock your device into a specific configuration is as - * follows: - * -# Set the desired configuration (or use the logic above to realise that - * it is already in the desired configuration) - * -# Claim the interface that you wish to use - * -# Check that the currently active configuration is the one that you want - * to use. - * - * The above method works because once an interface is claimed, no application - * or driver is able to select another configuration. - * - * \section earlycomp Early transfer completion - * - * NOTE: This section is currently Linux-centric. I am not sure if any of these - * considerations apply to Darwin or other platforms. - * - * When a transfer completes early (i.e. when less data is received/sent in - * any one packet than the transfer buffer allows for) then libusb is designed - * to terminate the transfer immediately, not transferring or receiving any - * more data unless other transfers have been queued by the user. - * - * On legacy platforms, libusb is unable to do this in all situations. After - * the incomplete packet occurs, "surplus" data may be transferred. For recent - * versions of libusb, this information is kept (the data length of the - * transfer is updated) and, for device-to-host transfers, any surplus data was - * added to the buffer. Still, this is not a nice solution because it loses the - * information about the end of the short packet, and the user probably wanted - * that surplus data to arrive in the next logical transfer. - * - * - * \section zlp Zero length packets - * - * - libusb is able to send a packet of zero length to an endpoint simply by - * submitting a transfer of zero length. - * - The \ref libusb_transfer_flags::LIBUSB_TRANSFER_ADD_ZERO_PACKET - * "LIBUSB_TRANSFER_ADD_ZERO_PACKET" flag is currently only supported on Linux. - */ - -/** - * \page libusb_contexts Contexts - * - * It is possible that libusb may be used simultaneously from two independent - * libraries linked into the same executable. For example, if your application - * has a plugin-like system which allows the user to dynamically load a range - * of modules into your program, it is feasible that two independently - * developed modules may both use libusb. - * - * libusb is written to allow for these multiple user scenarios. The two - * "instances" of libusb will not interfere: libusb_set_debug() calls - * from one user will not affect the same settings for other users, other - * users can continue using libusb after one of them calls libusb_exit(), etc. - * - * This is made possible through libusb's context concept. When you - * call libusb_init(), you are (optionally) given a context. You can then pass - * this context pointer back into future libusb functions. - * - * In order to keep things simple for more simplistic applications, it is - * legal to pass NULL to all functions requiring a context pointer (as long as - * you're sure no other code will attempt to use libusb from the same process). - * When you pass NULL, the default context will be used. The default context - * is created the first time a process calls libusb_init() when no other - * context is alive. Contexts are destroyed during libusb_exit(). - * - * The default context is reference-counted and can be shared. That means that - * if libusb_init(NULL) is called twice within the same process, the two - * users end up sharing the same context. The deinitialization and freeing of - * the default context will only happen when the last user calls libusb_exit(). - * In other words, the default context is created and initialized when its - * reference count goes from 0 to 1, and is deinitialized and destroyed when - * its reference count goes from 1 to 0. - * - * You may be wondering why only a subset of libusb functions require a - * context pointer in their function definition. Internally, libusb stores - * context pointers in other objects (e.g. libusb_device instances) and hence - * can infer the context from those objects. - */ - - /** - * \page libusb_api Application Programming Interface - * - * This is the complete list of libusb functions, structures and - * enumerations in alphabetical order. - * - * \section Functions - * - libusb_alloc_streams() - * - libusb_alloc_transfer() - * - libusb_attach_kernel_driver() - * - libusb_bulk_transfer() - * - libusb_cancel_transfer() - * - libusb_claim_interface() - * - libusb_clear_halt() - * - libusb_close() - * - libusb_control_transfer() - * - libusb_control_transfer_get_data() - * - libusb_control_transfer_get_setup() - * - libusb_cpu_to_le16() - * - libusb_detach_kernel_driver() - * - libusb_dev_mem_alloc() - * - libusb_dev_mem_free() - * - libusb_error_name() - * - libusb_event_handler_active() - * - libusb_event_handling_ok() - * - libusb_exit() - * - libusb_fill_bulk_stream_transfer() - * - libusb_fill_bulk_transfer() - * - libusb_fill_control_setup() - * - libusb_fill_control_transfer() - * - libusb_fill_interrupt_transfer() - * - libusb_fill_iso_transfer() - * - libusb_free_bos_descriptor() - * - libusb_free_config_descriptor() - * - libusb_free_container_id_descriptor() - * - libusb_free_device_list() - * - libusb_free_pollfds() - * - libusb_free_ss_endpoint_companion_descriptor() - * - libusb_free_ss_usb_device_capability_descriptor() - * - libusb_free_streams() - * - libusb_free_transfer() - * - libusb_free_usb_2_0_extension_descriptor() - * - libusb_get_active_config_descriptor() - * - libusb_get_bos_descriptor() - * - libusb_get_bus_number() - * - libusb_get_config_descriptor() - * - libusb_get_config_descriptor_by_value() - * - libusb_get_configuration() - * - libusb_get_container_id_descriptor() - * - libusb_get_descriptor() - * - libusb_get_device() - * - libusb_get_device_address() - * - libusb_get_device_descriptor() - * - libusb_get_device_list() - * - libusb_get_device_speed() - * - libusb_get_iso_packet_buffer() - * - libusb_get_iso_packet_buffer_simple() - * - libusb_get_max_iso_packet_size() - * - libusb_get_max_packet_size() - * - libusb_get_next_timeout() - * - libusb_get_parent() - * - libusb_get_pollfds() - * - libusb_get_port_number() - * - libusb_get_port_numbers() - * - libusb_get_port_path() - * - libusb_get_ss_endpoint_companion_descriptor() - * - libusb_get_ss_usb_device_capability_descriptor() - * - libusb_get_string_descriptor() - * - libusb_get_string_descriptor_ascii() - * - libusb_get_usb_2_0_extension_descriptor() - * - libusb_get_version() - * - libusb_handle_events() - * - libusb_handle_events_completed() - * - libusb_handle_events_locked() - * - libusb_handle_events_timeout() - * - libusb_handle_events_timeout_completed() - * - libusb_has_capability() - * - libusb_hotplug_deregister_callback() - * - libusb_hotplug_register_callback() - * - libusb_init() - * - libusb_interrupt_event_handler() - * - libusb_interrupt_transfer() - * - libusb_kernel_driver_active() - * - libusb_lock_events() - * - libusb_lock_event_waiters() - * - libusb_open() - * - libusb_open_device_with_vid_pid() - * - libusb_pollfds_handle_timeouts() - * - libusb_ref_device() - * - libusb_release_interface() - * - libusb_reset_device() - * - libusb_set_auto_detach_kernel_driver() - * - libusb_set_configuration() - * - libusb_set_debug() - * - libusb_set_interface_alt_setting() - * - libusb_set_iso_packet_lengths() - * - libusb_setlocale() - * - libusb_set_pollfd_notifiers() - * - libusb_strerror() - * - libusb_submit_transfer() - * - libusb_transfer_get_stream_id() - * - libusb_transfer_set_stream_id() - * - libusb_try_lock_events() - * - libusb_unlock_events() - * - libusb_unlock_event_waiters() - * - libusb_unref_device() - * - libusb_wait_for_event() - * - * \section Structures - * - libusb_bos_descriptor - * - libusb_bos_dev_capability_descriptor - * - libusb_config_descriptor - * - libusb_container_id_descriptor - * - \ref libusb_context - * - libusb_control_setup - * - \ref libusb_device - * - libusb_device_descriptor - * - \ref libusb_device_handle - * - libusb_endpoint_descriptor - * - libusb_interface - * - libusb_interface_descriptor - * - libusb_iso_packet_descriptor - * - libusb_pollfd - * - libusb_ss_endpoint_companion_descriptor - * - libusb_ss_usb_device_capability_descriptor - * - libusb_transfer - * - libusb_usb_2_0_extension_descriptor - * - libusb_version - * - * \section Enums - * - \ref libusb_bos_type - * - \ref libusb_capability - * - \ref libusb_class_code - * - \ref libusb_descriptor_type - * - \ref libusb_endpoint_direction - * - \ref libusb_error - * - \ref libusb_iso_sync_type - * - \ref libusb_iso_usage_type - * - \ref libusb_log_level - * - \ref libusb_request_recipient - * - \ref libusb_request_type - * - \ref libusb_speed - * - \ref libusb_ss_usb_device_capability_attributes - * - \ref libusb_standard_request - * - \ref libusb_supported_speed - * - \ref libusb_transfer_flags - * - \ref libusb_transfer_status - * - \ref libusb_transfer_type - * - \ref libusb_usb_2_0_extension_attributes - */ - -/** - * @defgroup libusb_lib Library initialization/deinitialization - * This page details how to initialize and deinitialize libusb. Initialization - * must be performed before using any libusb functionality, and similarly you - * must not call any libusb functions after deinitialization. - */ - -/** - * @defgroup libusb_dev Device handling and enumeration - * The functionality documented below is designed to help with the following - * operations: - * - Enumerating the USB devices currently attached to the system - * - Choosing a device to operate from your software - * - Opening and closing the chosen device - * - * \section nutshell In a nutshell... - * - * The description below really makes things sound more complicated than they - * actually are. The following sequence of function calls will be suitable - * for almost all scenarios and does not require you to have such a deep - * understanding of the resource management issues: - * \code -// discover devices -libusb_device **list; -libusb_device *found = NULL; -ssize_t cnt = libusb_get_device_list(NULL, &list); -ssize_t i = 0; -int err = 0; -if (cnt < 0) - error(); - -for (i = 0; i < cnt; i++) { - libusb_device *device = list[i]; - if (is_interesting(device)) { - found = device; - break; - } -} - -if (found) { - libusb_device_handle *handle; - - err = libusb_open(found, &handle); - if (err) - error(); - // etc -} - -libusb_free_device_list(list, 1); -\endcode - * - * The two important points: - * - You asked libusb_free_device_list() to unreference the devices (2nd - * parameter) - * - You opened the device before freeing the list and unreferencing the - * devices - * - * If you ended up with a handle, you can now proceed to perform I/O on the - * device. - * - * \section devshandles Devices and device handles - * libusb has a concept of a USB device, represented by the - * \ref libusb_device opaque type. A device represents a USB device that - * is currently or was previously connected to the system. Using a reference - * to a device, you can determine certain information about the device (e.g. - * you can read the descriptor data). - * - * The libusb_get_device_list() function can be used to obtain a list of - * devices currently connected to the system. This is known as device - * discovery. - * - * Just because you have a reference to a device does not mean it is - * necessarily usable. The device may have been unplugged, you may not have - * permission to operate such device, or another program or driver may be - * using the device. - * - * When you've found a device that you'd like to operate, you must ask - * libusb to open the device using the libusb_open() function. Assuming - * success, libusb then returns you a device handle - * (a \ref libusb_device_handle pointer). All "real" I/O operations then - * operate on the handle rather than the original device pointer. - * - * \section devref Device discovery and reference counting - * - * Device discovery (i.e. calling libusb_get_device_list()) returns a - * freshly-allocated list of devices. The list itself must be freed when - * you are done with it. libusb also needs to know when it is OK to free - * the contents of the list - the devices themselves. - * - * To handle these issues, libusb provides you with two separate items: - * - A function to free the list itself - * - A reference counting system for the devices inside - * - * New devices presented by the libusb_get_device_list() function all have a - * reference count of 1. You can increase and decrease reference count using - * libusb_ref_device() and libusb_unref_device(). A device is destroyed when - * its reference count reaches 0. - * - * With the above information in mind, the process of opening a device can - * be viewed as follows: - * -# Discover devices using libusb_get_device_list(). - * -# Choose the device that you want to operate, and call libusb_open(). - * -# Unref all devices in the discovered device list. - * -# Free the discovered device list. - * - * The order is important - you must not unreference the device before - * attempting to open it, because unreferencing it may destroy the device. - * - * For convenience, the libusb_free_device_list() function includes a - * parameter to optionally unreference all the devices in the list before - * freeing the list itself. This combines steps 3 and 4 above. - * - * As an implementation detail, libusb_open() actually adds a reference to - * the device in question. This is because the device remains available - * through the handle via libusb_get_device(). The reference is deleted during - * libusb_close(). - */ - -/** @defgroup libusb_misc Miscellaneous */ - -/* we traverse usbfs without knowing how many devices we are going to find. - * so we create this discovered_devs model which is similar to a linked-list - * which grows when required. it can be freed once discovery has completed, - * eliminating the need for a list node in the libusb_device structure - * itself. */ -#define DISCOVERED_DEVICES_SIZE_STEP 8 - -static struct discovered_devs *discovered_devs_alloc(void) -{ - struct discovered_devs *ret = - malloc(sizeof(*ret) + (sizeof(void *) * DISCOVERED_DEVICES_SIZE_STEP)); - - if (ret) { - ret->len = 0; - ret->capacity = DISCOVERED_DEVICES_SIZE_STEP; - } - return ret; -} - -static void discovered_devs_free(struct discovered_devs *discdevs) -{ - size_t i; - - for (i = 0; i < discdevs->len; i++) - libusb_unref_device(discdevs->devices[i]); - - free(discdevs); -} - -/* append a device to the discovered devices collection. may realloc itself, - * returning new discdevs. returns NULL on realloc failure. */ -struct discovered_devs *discovered_devs_append( - struct discovered_devs *discdevs, struct libusb_device *dev) -{ - size_t len = discdevs->len; - size_t capacity; - struct discovered_devs *new_discdevs; - - /* if there is space, just append the device */ - if (len < discdevs->capacity) { - discdevs->devices[len] = libusb_ref_device(dev); - discdevs->len++; - return discdevs; - } - - /* exceeded capacity, need to grow */ - usbi_dbg("need to increase capacity"); - capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP; - /* can't use usbi_reallocf here because in failure cases it would - * free the existing discdevs without unreferencing its devices. */ - new_discdevs = realloc(discdevs, - sizeof(*discdevs) + (sizeof(void *) * capacity)); - if (!new_discdevs) { - discovered_devs_free(discdevs); - return NULL; - } - - discdevs = new_discdevs; - discdevs->capacity = capacity; - discdevs->devices[len] = libusb_ref_device(dev); - discdevs->len++; - - return discdevs; -} - -/* Allocate a new device with a specific session ID. The returned device has - * a reference count of 1. */ -struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, - unsigned long session_id) -{ - size_t priv_size = usbi_backend->device_priv_size; - struct libusb_device *dev = calloc(1, sizeof(*dev) + priv_size); - int r; - - if (!dev) - return NULL; - - r = usbi_mutex_init(&dev->lock); - if (r) { - free(dev); - return NULL; - } - - dev->ctx = ctx; - dev->refcnt = 1; - dev->session_data = session_id; - dev->speed = LIBUSB_SPEED_UNKNOWN; - - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - usbi_connect_device (dev); - } - - return dev; -} - -void usbi_connect_device(struct libusb_device *dev) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - - dev->attached = 1; - - usbi_mutex_lock(&dev->ctx->usb_devs_lock); - list_add(&dev->list, &dev->ctx->usb_devs); - usbi_mutex_unlock(&dev->ctx->usb_devs_lock); - - /* Signal that an event has occurred for this device if we support hotplug AND - * the hotplug message list is ready. This prevents an event from getting raised - * during initial enumeration. */ - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) { - usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED); - } -} - -void usbi_disconnect_device(struct libusb_device *dev) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - - usbi_mutex_lock(&dev->lock); - dev->attached = 0; - usbi_mutex_unlock(&dev->lock); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_del(&dev->list); - usbi_mutex_unlock(&ctx->usb_devs_lock); - - /* Signal that an event has occurred for this device if we support hotplug AND - * the hotplug message list is ready. This prevents an event from getting raised - * during initial enumeration. libusb_handle_events will take care of dereferencing - * the device. */ - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG) && dev->ctx->hotplug_msgs.next) { - usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT); - } -} - -/* Perform some final sanity checks on a newly discovered device. If this - * function fails (negative return code), the device should not be added - * to the discovered device list. */ -int usbi_sanitize_device(struct libusb_device *dev) -{ - int r; - uint8_t num_configurations; - - r = usbi_device_cache_descriptor(dev); - if (r < 0) - return r; - - num_configurations = dev->device_descriptor.bNumConfigurations; - if (num_configurations > USB_MAXCONFIG) { - usbi_err(DEVICE_CTX(dev), "too many configurations"); - return LIBUSB_ERROR_IO; - } else if (0 == num_configurations) - usbi_dbg("zero configurations, maybe an unauthorized device"); - - dev->num_configurations = num_configurations; - return 0; -} - -/* Examine libusb's internal list of known devices, looking for one with - * a specific session ID. Returns the matching device if it was found, and - * NULL otherwise. */ -struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, - unsigned long session_id) -{ - struct libusb_device *dev; - struct libusb_device *ret = NULL; - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) - if (dev->session_data == session_id) { - ret = libusb_ref_device(dev); - break; - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - - return ret; -} - -/** @ingroup libusb_dev - * Returns a list of USB devices currently attached to the system. This is - * your entry point into finding a USB device to operate. - * - * You are expected to unreference all the devices when you are done with - * them, and then free the list with libusb_free_device_list(). Note that - * libusb_free_device_list() can unref all the devices for you. Be careful - * not to unreference a device you are about to open until after you have - * opened it. - * - * This return value of this function indicates the number of devices in - * the resultant list. The list is actually one element larger, as it is - * NULL-terminated. - * - * \param ctx the context to operate on, or NULL for the default context - * \param list output location for a list of devices. Must be later freed with - * libusb_free_device_list(). - * \returns the number of devices in the outputted list, or any - * \ref libusb_error according to errors encountered by the backend. - */ -ssize_t API_EXPORTED libusb_get_device_list(libusb_context *ctx, - libusb_device ***list) -{ - struct discovered_devs *discdevs = discovered_devs_alloc(); - struct libusb_device **ret; - int r = 0; - ssize_t i, len; - USBI_GET_CONTEXT(ctx); - usbi_dbg(""); - - if (!discdevs) - return LIBUSB_ERROR_NO_MEM; - - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - /* backend provides hotplug support */ - struct libusb_device *dev; - - if (usbi_backend->hotplug_poll) - usbi_backend->hotplug_poll(); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) { - discdevs = discovered_devs_append(discdevs, dev); - - if (!discdevs) { - r = LIBUSB_ERROR_NO_MEM; - break; - } - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - } else { - /* backend does not provide hotplug support */ - r = usbi_backend->get_device_list(ctx, &discdevs); - } - - if (r < 0) { - len = r; - goto out; - } - - /* convert discovered_devs into a list */ - len = discdevs->len; - ret = calloc(len + 1, sizeof(struct libusb_device *)); - if (!ret) { - len = LIBUSB_ERROR_NO_MEM; - goto out; - } - - ret[len] = NULL; - for (i = 0; i < len; i++) { - struct libusb_device *dev = discdevs->devices[i]; - ret[i] = libusb_ref_device(dev); - } - *list = ret; - -out: - if (discdevs) - discovered_devs_free(discdevs); - return len; -} - -/** \ingroup libusb_dev - * Frees a list of devices previously discovered using - * libusb_get_device_list(). If the unref_devices parameter is set, the - * reference count of each device in the list is decremented by 1. - * \param list the list to free - * \param unref_devices whether to unref the devices in the list - */ -void API_EXPORTED libusb_free_device_list(libusb_device **list, - int unref_devices) -{ - if (!list) - return; - - if (unref_devices) { - int i = 0; - struct libusb_device *dev; - - while ((dev = list[i++]) != NULL) - libusb_unref_device(dev); - } - free(list); -} - -/** \ingroup libusb_dev - * Get the number of the bus that a device is connected to. - * \param dev a device - * \returns the bus number - */ -uint8_t API_EXPORTED libusb_get_bus_number(libusb_device *dev) -{ - return dev->bus_number; -} - -/** \ingroup libusb_dev - * Get the number of the port that a device is connected to. - * Unless the OS does something funky, or you are hot-plugging USB extension cards, - * the port number returned by this call is usually guaranteed to be uniquely tied - * to a physical port, meaning that different devices plugged on the same physical - * port should return the same port number. - * - * But outside of this, there is no guarantee that the port number returned by this - * call will remain the same, or even match the order in which ports have been - * numbered by the HUB/HCD manufacturer. - * - * \param dev a device - * \returns the port number (0 if not available) - */ -uint8_t API_EXPORTED libusb_get_port_number(libusb_device *dev) -{ - return dev->port_number; -} - -/** \ingroup libusb_dev - * Get the list of all port numbers from root for the specified device - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * \param dev a device - * \param port_numbers the array that should contain the port numbers - * \param port_numbers_len the maximum length of the array. As per the USB 3.0 - * specs, the current maximum limit for the depth is 7. - * \returns the number of elements filled - * \returns LIBUSB_ERROR_OVERFLOW if the array is too small - */ -int API_EXPORTED libusb_get_port_numbers(libusb_device *dev, - uint8_t* port_numbers, int port_numbers_len) -{ - int i = port_numbers_len; - struct libusb_context *ctx = DEVICE_CTX(dev); - - if (port_numbers_len <= 0) - return LIBUSB_ERROR_INVALID_PARAM; - - // HCDs can be listed as devices with port #0 - while((dev) && (dev->port_number != 0)) { - if (--i < 0) { - usbi_warn(ctx, "port numbers array is too small"); - return LIBUSB_ERROR_OVERFLOW; - } - port_numbers[i] = dev->port_number; - dev = dev->parent_dev; - } - if (i < port_numbers_len) - memmove(port_numbers, &port_numbers[i], port_numbers_len - i); - return port_numbers_len - i; -} - -/** \ingroup libusb_dev - * Deprecated please use libusb_get_port_numbers instead. - */ -int API_EXPORTED libusb_get_port_path(libusb_context *ctx, libusb_device *dev, - uint8_t* port_numbers, uint8_t port_numbers_len) -{ - UNUSED(ctx); - - return libusb_get_port_numbers(dev, port_numbers, port_numbers_len); -} - -/** \ingroup libusb_dev - * Get the the parent from the specified device. - * \param dev a device - * \returns the device parent or NULL if not available - * You should issue a \ref libusb_get_device_list() before calling this - * function and make sure that you only access the parent before issuing - * \ref libusb_free_device_list(). The reason is that libusb currently does - * not maintain a permanent list of device instances, and therefore can - * only guarantee that parents are fully instantiated within a - * libusb_get_device_list() - libusb_free_device_list() block. - */ -DEFAULT_VISIBILITY -libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev) -{ - return dev->parent_dev; -} - -/** \ingroup libusb_dev - * Get the address of the device on the bus it is connected to. - * \param dev a device - * \returns the device address - */ -uint8_t API_EXPORTED libusb_get_device_address(libusb_device *dev) -{ - return dev->device_address; -} - -/** \ingroup libusb_dev - * Get the negotiated connection speed for a device. - * \param dev a device - * \returns a \ref libusb_speed code, where LIBUSB_SPEED_UNKNOWN means that - * the OS doesn't know or doesn't support returning the negotiated speed. - */ -int API_EXPORTED libusb_get_device_speed(libusb_device *dev) -{ - return dev->speed; -} - -static const struct libusb_endpoint_descriptor *find_endpoint( - struct libusb_config_descriptor *config, unsigned char endpoint) -{ - int iface_idx; - for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { - const struct libusb_interface *iface = &config->interface[iface_idx]; - int altsetting_idx; - - for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; - altsetting_idx++) { - const struct libusb_interface_descriptor *altsetting - = &iface->altsetting[altsetting_idx]; - int ep_idx; - - for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) { - const struct libusb_endpoint_descriptor *ep = - &altsetting->endpoint[ep_idx]; - if (ep->bEndpointAddress == endpoint) - return ep; - } - } - } - return NULL; -} - -/** \ingroup libusb_dev - * Convenience function to retrieve the wMaxPacketSize value for a particular - * endpoint in the active device configuration. - * - * This function was originally intended to be of assistance when setting up - * isochronous transfers, but a design mistake resulted in this function - * instead. It simply returns the wMaxPacketSize value without considering - * its contents. If you're dealing with isochronous transfers, you probably - * want libusb_get_max_iso_packet_size() instead. - * - * \param dev a device - * \param endpoint address of the endpoint in question - * \returns the wMaxPacketSize value - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_OTHER on other failure - */ -int API_EXPORTED libusb_get_max_packet_size(libusb_device *dev, - unsigned char endpoint) -{ - struct libusb_config_descriptor *config; - const struct libusb_endpoint_descriptor *ep; - int r; - - r = libusb_get_active_config_descriptor(dev, &config); - if (r < 0) { - usbi_err(DEVICE_CTX(dev), - "could not retrieve active config descriptor"); - return LIBUSB_ERROR_OTHER; - } - - ep = find_endpoint(config, endpoint); - if (!ep) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - r = ep->wMaxPacketSize; - -out: - libusb_free_config_descriptor(config); - return r; -} - -/** \ingroup libusb_dev - * Calculate the maximum packet size which a specific endpoint is capable is - * sending or receiving in the duration of 1 microframe - * - * Only the active configuration is examined. The calculation is based on the - * wMaxPacketSize field in the endpoint descriptor as described in section - * 9.6.6 in the USB 2.0 specifications. - * - * If acting on an isochronous or interrupt endpoint, this function will - * multiply the value found in bits 0:10 by the number of transactions per - * microframe (determined by bits 11:12). Otherwise, this function just - * returns the numeric value found in bits 0:10. - * - * This function is useful for setting up isochronous transfers, for example - * you might pass the return value from this function to - * libusb_set_iso_packet_lengths() in order to set the length field of every - * isochronous packet in a transfer. - * - * Since v1.0.3. - * - * \param dev a device - * \param endpoint address of the endpoint in question - * \returns the maximum packet size which can be sent/received on this endpoint - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_OTHER on other failure - */ -int API_EXPORTED libusb_get_max_iso_packet_size(libusb_device *dev, - unsigned char endpoint) -{ - struct libusb_config_descriptor *config; - const struct libusb_endpoint_descriptor *ep; - enum libusb_transfer_type ep_type; - uint16_t val; - int r; - - r = libusb_get_active_config_descriptor(dev, &config); - if (r < 0) { - usbi_err(DEVICE_CTX(dev), - "could not retrieve active config descriptor"); - return LIBUSB_ERROR_OTHER; - } - - ep = find_endpoint(config, endpoint); - if (!ep) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - val = ep->wMaxPacketSize; - ep_type = (enum libusb_transfer_type) (ep->bmAttributes & 0x3); - - r = val & 0x07ff; - if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - || ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) - r *= (1 + ((val >> 11) & 3)); - -out: - libusb_free_config_descriptor(config); - return r; -} - -/** \ingroup libusb_dev - * Increment the reference count of a device. - * \param dev the device to reference - * \returns the same device - */ -DEFAULT_VISIBILITY -libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev) -{ - usbi_mutex_lock(&dev->lock); - dev->refcnt++; - usbi_mutex_unlock(&dev->lock); - return dev; -} - -/** \ingroup libusb_dev - * Decrement the reference count of a device. If the decrement operation - * causes the reference count to reach zero, the device shall be destroyed. - * \param dev the device to unreference - */ -void API_EXPORTED libusb_unref_device(libusb_device *dev) -{ - int refcnt; - - if (!dev) - return; - - usbi_mutex_lock(&dev->lock); - refcnt = --dev->refcnt; - usbi_mutex_unlock(&dev->lock); - - if (refcnt == 0) { - usbi_dbg("destroy device %d.%d", dev->bus_number, dev->device_address); - - libusb_unref_device(dev->parent_dev); - - if (usbi_backend->destroy_device) - usbi_backend->destroy_device(dev); - - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - /* backend does not support hotplug */ - usbi_disconnect_device(dev); - } - - usbi_mutex_destroy(&dev->lock); - free(dev); - } -} - -/* - * Signal the event pipe so that the event handling thread will be - * interrupted to process an internal event. - */ -int usbi_signal_event(struct libusb_context *ctx) -{ - unsigned char dummy = 1; - ssize_t r; - - /* write some data on event pipe to interrupt event handlers */ - r = usbi_write(ctx->event_pipe[1], &dummy, sizeof(dummy)); - if (r != sizeof(dummy)) { - usbi_warn(ctx, "internal signalling write failed"); - return LIBUSB_ERROR_IO; - } - - return 0; -} - -/* - * Clear the event pipe so that the event handling will no longer be - * interrupted. - */ -int usbi_clear_event(struct libusb_context *ctx) -{ - unsigned char dummy; - ssize_t r; - - /* read some data on event pipe to clear it */ - r = usbi_read(ctx->event_pipe[0], &dummy, sizeof(dummy)); - if (r != sizeof(dummy)) { - usbi_warn(ctx, "internal signalling read failed"); - return LIBUSB_ERROR_IO; - } - - return 0; -} - -/** \ingroup libusb_dev - * Open a device and obtain a device handle. A handle allows you to perform - * I/O on the device in question. - * - * Internally, this function adds a reference to the device and makes it - * available to you through libusb_get_device(). This reference is removed - * during libusb_close(). - * - * This is a non-blocking function; no requests are sent over the bus. - * - * \param dev the device to open - * \param dev_handle output location for the returned device handle pointer. Only - * populated when the return code is 0. - * \returns 0 on success - * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure - * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_open(libusb_device *dev, - libusb_device_handle **dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct libusb_device_handle *_dev_handle; - size_t priv_size = usbi_backend->device_handle_priv_size; - int r; - usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); - - if (!dev->attached) { - return LIBUSB_ERROR_NO_DEVICE; - } - - _dev_handle = malloc(sizeof(*_dev_handle) + priv_size); - if (!_dev_handle) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_mutex_init(&_dev_handle->lock); - if (r) { - free(_dev_handle); - return LIBUSB_ERROR_OTHER; - } - - _dev_handle->dev = libusb_ref_device(dev); - _dev_handle->auto_detach_kernel_driver = 0; - _dev_handle->claimed_interfaces = 0; - memset(&_dev_handle->os_priv, 0, priv_size); - - r = usbi_backend->open(_dev_handle); - if (r < 0) { - usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r); - libusb_unref_device(dev); - usbi_mutex_destroy(&_dev_handle->lock); - free(_dev_handle); - return r; - } - - usbi_mutex_lock(&ctx->open_devs_lock); - list_add(&_dev_handle->list, &ctx->open_devs); - usbi_mutex_unlock(&ctx->open_devs_lock); - *dev_handle = _dev_handle; - - return 0; -} - -/** \ingroup libusb_dev - * Convenience function for finding a device with a particular - * idVendor/idProduct combination. This function is intended - * for those scenarios where you are using libusb to knock up a quick test - * application - it allows you to avoid calling libusb_get_device_list() and - * worrying about traversing/freeing the list. - * - * This function has limitations and is hence not intended for use in real - * applications: if multiple devices have the same IDs it will only - * give you the first one, etc. - * - * \param ctx the context to operate on, or NULL for the default context - * \param vendor_id the idVendor value to search for - * \param product_id the idProduct value to search for - * \returns a device handle for the first found device, or NULL on error - * or if the device could not be found. */ -DEFAULT_VISIBILITY -libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( - libusb_context *ctx, uint16_t vendor_id, uint16_t product_id) -{ - struct libusb_device **devs; - struct libusb_device *found = NULL; - struct libusb_device *dev; - struct libusb_device_handle *dev_handle = NULL; - size_t i = 0; - int r; - - if (libusb_get_device_list(ctx, &devs) < 0) - return NULL; - - while ((dev = devs[i++]) != NULL) { - struct libusb_device_descriptor desc; - r = libusb_get_device_descriptor(dev, &desc); - if (r < 0) - goto out; - if (desc.idVendor == vendor_id && desc.idProduct == product_id) { - found = dev; - break; - } - } - - if (found) { - r = libusb_open(found, &dev_handle); - if (r < 0) - dev_handle = NULL; - } - -out: - libusb_free_device_list(devs, 1); - return dev_handle; -} - -static void do_close(struct libusb_context *ctx, - struct libusb_device_handle *dev_handle) -{ - struct usbi_transfer *itransfer; - struct usbi_transfer *tmp; - - /* remove any transfers in flight that are for this device */ - usbi_mutex_lock(&ctx->flying_transfers_lock); - - /* safe iteration because transfers may be being deleted */ - list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) { - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - if (transfer->dev_handle != dev_handle) - continue; - - usbi_mutex_lock(&itransfer->lock); - if (!(itransfer->state_flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { - usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); - - if (itransfer->state_flags & USBI_TRANSFER_CANCELLING) - usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle"); - else - usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); - } - usbi_mutex_unlock(&itransfer->lock); - - /* remove from the list of in-flight transfers and make sure - * we don't accidentally use the device handle in the future - * (or that such accesses will be easily caught and identified as a crash) - */ - list_del(&itransfer->list); - transfer->dev_handle = NULL; - - /* it is up to the user to free up the actual transfer struct. this is - * just making sure that we don't attempt to process the transfer after - * the device handle is invalid - */ - usbi_dbg("Removed transfer %p from the in-flight list because device handle %p closed", - transfer, dev_handle); - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - usbi_mutex_lock(&ctx->open_devs_lock); - list_del(&dev_handle->list); - usbi_mutex_unlock(&ctx->open_devs_lock); - - usbi_backend->close(dev_handle); - libusb_unref_device(dev_handle->dev); - usbi_mutex_destroy(&dev_handle->lock); - free(dev_handle); -} - -/** \ingroup libusb_dev - * Close a device handle. Should be called on all open handles before your - * application exits. - * - * Internally, this function destroys the reference that was added by - * libusb_open() on the given device. - * - * This is a non-blocking function; no requests are sent over the bus. - * - * \param dev_handle the device handle to close - */ -void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx; - int handling_events; - int pending_events; - - if (!dev_handle) - return; - usbi_dbg(""); - - ctx = HANDLE_CTX(dev_handle); - handling_events = usbi_handling_events(ctx); - - /* Similarly to libusb_open(), we want to interrupt all event handlers - * at this point. More importantly, we want to perform the actual close of - * the device while holding the event handling lock (preventing any other - * thread from doing event handling) because we will be removing a file - * descriptor from the polling loop. If this is being called by the current - * event handler, we can bypass the interruption code because we already - * hold the event handling lock. */ - - if (!handling_events) { - /* Record that we are closing a device. - * Only signal an event if there are no prior pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - ctx->device_close++; - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - /* take event handling lock */ - libusb_lock_events(ctx); - } - - /* Close the device */ - do_close(ctx, dev_handle); - - if (!handling_events) { - /* We're done with closing this device. - * Clear the event pipe if there are no further pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - ctx->device_close--; - pending_events = usbi_pending_events(ctx); - if (!pending_events) - usbi_clear_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - /* Release event handling lock and wake up event waiters */ - libusb_unlock_events(ctx); - } -} - -/** \ingroup libusb_dev - * Get the underlying device for a device handle. This function does not modify - * the reference count of the returned device, so do not feel compelled to - * unreference it when you are done. - * \param dev_handle a device handle - * \returns the underlying device - */ -DEFAULT_VISIBILITY -libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle) -{ - return dev_handle->dev; -} - -/** \ingroup libusb_dev - * Determine the bConfigurationValue of the currently active configuration. - * - * You could formulate your own control request to obtain this information, - * but this function has the advantage that it may be able to retrieve the - * information from operating system caches (no I/O involved). - * - * If the OS does not cache this information, then this function will block - * while a control transfer is submitted to retrieve the information. - * - * This function will return a value of 0 in the config output - * parameter if the device is in unconfigured state. - * - * \param dev_handle a device handle - * \param config output location for the bConfigurationValue of the active - * configuration (only valid for return code 0) - * \returns 0 on success - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev_handle, - int *config) -{ - int r = LIBUSB_ERROR_NOT_SUPPORTED; - - usbi_dbg(""); - if (usbi_backend->get_configuration) - r = usbi_backend->get_configuration(dev_handle, config); - - if (r == LIBUSB_ERROR_NOT_SUPPORTED) { - uint8_t tmp = 0; - usbi_dbg("falling back to control message"); - r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000); - if (r == 0) { - usbi_err(HANDLE_CTX(dev_handle), "zero bytes returned in ctrl transfer?"); - r = LIBUSB_ERROR_IO; - } else if (r == 1) { - r = 0; - *config = tmp; - } else { - usbi_dbg("control failed, error %d", r); - } - } - - if (r == 0) - usbi_dbg("active config %d", *config); - - return r; -} - -/** \ingroup libusb_dev - * Set the active configuration for a device. - * - * The operating system may or may not have already set an active - * configuration on the device. It is up to your application to ensure the - * correct configuration is selected before you attempt to claim interfaces - * and perform other operations. - * - * If you call this function on a device already configured with the selected - * configuration, then this function will act as a lightweight device reset: - * it will issue a SET_CONFIGURATION request using the current configuration, - * causing most USB-related device state to be reset (altsetting reset to zero, - * endpoint halts cleared, toggles reset). - * - * You cannot change/reset configuration if your application has claimed - * interfaces. It is advised to set the desired configuration before claiming - * interfaces. - * - * Alternatively you can call libusb_release_interface() first. Note if you - * do things this way you must ensure that auto_detach_kernel_driver for - * dev is 0, otherwise the kernel driver will be re-attached when you - * release the interface(s). - * - * You cannot change/reset configuration if other applications or drivers have - * claimed interfaces. - * - * A configuration value of -1 will put the device in unconfigured state. - * The USB specifications state that a configuration value of 0 does this, - * however buggy devices exist which actually have a configuration 0. - * - * You should always use this function rather than formulating your own - * SET_CONFIGURATION control request. This is because the underlying operating - * system needs to know when such changes happen. - * - * This is a blocking function. - * - * \param dev_handle a device handle - * \param configuration the bConfigurationValue of the configuration you - * wish to activate, or -1 if you wish to put the device in an unconfigured - * state - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the requested configuration does not exist - * \returns LIBUSB_ERROR_BUSY if interfaces are currently claimed - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_set_auto_detach_kernel_driver() - */ -int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle, - int configuration) -{ - usbi_dbg("configuration %d", configuration); - return usbi_backend->set_configuration(dev_handle, configuration); -} - -/** \ingroup libusb_dev - * Claim an interface on a given device handle. You must claim the interface - * you wish to use before you can perform I/O on any of its endpoints. - * - * It is legal to attempt to claim an already-claimed interface, in which - * case libusb just returns 0 without doing anything. - * - * If auto_detach_kernel_driver is set to 1 for dev, the kernel driver - * will be detached if necessary, on failure the detach error is returned. - * - * Claiming of interfaces is a purely logical operation; it does not cause - * any requests to be sent over the bus. Interface claiming is used to - * instruct the underlying operating system that your application wishes - * to take ownership of the interface. - * - * This is a non-blocking function. - * - * \param dev_handle a device handle - * \param interface_number the bInterfaceNumber of the interface you - * wish to claim - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the requested interface does not exist - * \returns LIBUSB_ERROR_BUSY if another program or driver has claimed the - * interface - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns a LIBUSB_ERROR code on other failure - * \see libusb_set_auto_detach_kernel_driver() - */ -int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle, - int interface_number) -{ - int r = 0; - - usbi_dbg("interface %d", interface_number); - if (interface_number >= USB_MAXINTERFACES) - return LIBUSB_ERROR_INVALID_PARAM; - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_mutex_lock(&dev_handle->lock); - if (dev_handle->claimed_interfaces & (1 << interface_number)) - goto out; - - r = usbi_backend->claim_interface(dev_handle, interface_number); - if (r == 0) - dev_handle->claimed_interfaces |= 1 << interface_number; - -out: - usbi_mutex_unlock(&dev_handle->lock); - return r; -} - -/** \ingroup libusb_dev - * Release an interface previously claimed with libusb_claim_interface(). You - * should release all claimed interfaces before closing a device handle. - * - * This is a blocking function. A SET_INTERFACE control request will be sent - * to the device, resetting interface state to the first alternate setting. - * - * If auto_detach_kernel_driver is set to 1 for dev, the kernel - * driver will be re-attached after releasing the interface. - * - * \param dev_handle a device handle - * \param interface_number the bInterfaceNumber of the - * previously-claimed interface - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_set_auto_detach_kernel_driver() - */ -int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle, - int interface_number) -{ - int r; - - usbi_dbg("interface %d", interface_number); - if (interface_number >= USB_MAXINTERFACES) - return LIBUSB_ERROR_INVALID_PARAM; - - usbi_mutex_lock(&dev_handle->lock); - if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - r = usbi_backend->release_interface(dev_handle, interface_number); - if (r == 0) - dev_handle->claimed_interfaces &= ~(1 << interface_number); - -out: - usbi_mutex_unlock(&dev_handle->lock); - return r; -} - -/** \ingroup libusb_dev - * Activate an alternate setting for an interface. The interface must have - * been previously claimed with libusb_claim_interface(). - * - * You should always use this function rather than formulating your own - * SET_INTERFACE control request. This is because the underlying operating - * system needs to know when such changes happen. - * - * This is a blocking function. - * - * \param dev_handle a device handle - * \param interface_number the bInterfaceNumber of the - * previously-claimed interface - * \param alternate_setting the bAlternateSetting of the alternate - * setting to activate - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the interface was not claimed, or the - * requested alternate setting does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, - int interface_number, int alternate_setting) -{ - usbi_dbg("interface %d altsetting %d", - interface_number, alternate_setting); - if (interface_number >= USB_MAXINTERFACES) - return LIBUSB_ERROR_INVALID_PARAM; - - usbi_mutex_lock(&dev_handle->lock); - if (!dev_handle->dev->attached) { - usbi_mutex_unlock(&dev_handle->lock); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (!(dev_handle->claimed_interfaces & (1 << interface_number))) { - usbi_mutex_unlock(&dev_handle->lock); - return LIBUSB_ERROR_NOT_FOUND; - } - usbi_mutex_unlock(&dev_handle->lock); - - return usbi_backend->set_interface_altsetting(dev_handle, interface_number, - alternate_setting); -} - -/** \ingroup libusb_dev - * Clear the halt/stall condition for an endpoint. Endpoints with halt status - * are unable to receive or transmit data until the halt condition is stalled. - * - * You should cancel all pending transfers before attempting to clear the halt - * condition. - * - * This is a blocking function. - * - * \param dev_handle a device handle - * \param endpoint the endpoint to clear halt status - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_clear_halt(libusb_device_handle *dev_handle, - unsigned char endpoint) -{ - usbi_dbg("endpoint %x", endpoint); - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - return usbi_backend->clear_halt(dev_handle, endpoint); -} - -/** \ingroup libusb_dev - * Perform a USB port reset to reinitialize a device. The system will attempt - * to restore the previous configuration and alternate settings after the - * reset has completed. - * - * If the reset fails, the descriptors change, or the previous state cannot be - * restored, the device will appear to be disconnected and reconnected. This - * means that the device handle is no longer valid (you should close it) and - * rediscover the device. A return code of LIBUSB_ERROR_NOT_FOUND indicates - * when this is the case. - * - * This is a blocking function which usually incurs a noticeable delay. - * - * \param dev_handle a handle of the device to reset - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the - * device has been disconnected - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle) -{ - usbi_dbg(""); - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - return usbi_backend->reset_device(dev_handle); -} - -/** \ingroup libusb_asyncio - * Allocate up to num_streams usb bulk streams on the specified endpoints. This - * function takes an array of endpoints rather then a single endpoint because - * some protocols require that endpoints are setup with similar stream ids. - * All endpoints passed in must belong to the same interface. - * - * Note this function may return less streams then requested. Also note that the - * same number of streams are allocated for each endpoint in the endpoint array. - * - * Stream id 0 is reserved, and should not be used to communicate with devices. - * If libusb_alloc_streams() returns with a value of N, you may use stream ids - * 1 to N. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param dev_handle a device handle - * \param num_streams number of streams to try to allocate - * \param endpoints array of endpoints to allocate streams on - * \param num_endpoints length of the endpoints array - * \returns number of streams allocated, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints) -{ - usbi_dbg("streams %u eps %d", (unsigned) num_streams, num_endpoints); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend->alloc_streams) - return usbi_backend->alloc_streams(dev_handle, num_streams, endpoints, - num_endpoints); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_asyncio - * Free usb bulk streams allocated with libusb_alloc_streams(). - * - * Note streams are automatically free-ed when releasing an interface. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param dev_handle a device handle - * \param endpoints array of endpoints to free streams on - * \param num_endpoints length of the endpoints array - * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle, - unsigned char *endpoints, int num_endpoints) -{ - usbi_dbg("eps %d", num_endpoints); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend->free_streams) - return usbi_backend->free_streams(dev_handle, endpoints, - num_endpoints); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_asyncio - * Attempts to allocate a block of persistent DMA memory suitable for transfers - * against the given device. If successful, will return a block of memory - * that is suitable for use as "buffer" in \ref libusb_transfer against this - * device. Using this memory instead of regular memory means that the host - * controller can use DMA directly into the buffer to increase performance, and - * also that transfers can no longer fail due to kernel memory fragmentation. - * - * Note that this means you should not modify this memory (or even data on - * the same cache lines) when a transfer is in progress, although it is legal - * to have several transfers going on within the same memory block. - * - * Will return NULL on failure. Many systems do not support such zerocopy - * and will always return NULL. Memory allocated with this function must be - * freed with \ref libusb_dev_mem_free. Specifically, this means that the - * flag \ref LIBUSB_TRANSFER_FREE_BUFFER cannot be used to free memory allocated - * with this function. - * - * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 - * - * \param dev_handle a device handle - * \param length size of desired data buffer - * \returns a pointer to the newly allocated memory, or NULL on failure - */ -DEFAULT_VISIBILITY -unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, - size_t length) -{ - if (!dev_handle->dev->attached) - return NULL; - - if (usbi_backend->dev_mem_alloc) - return usbi_backend->dev_mem_alloc(dev_handle, length); - else - return NULL; -} - -/** \ingroup libusb_asyncio - * Free device memory allocated with libusb_dev_mem_alloc(). - * - * \param dev_handle a device handle - * \param buffer pointer to the previously allocated memory - * \param length size of previously allocated memory - * \returns LIBUSB_SUCCESS, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_dev_mem_free(libusb_device_handle *dev_handle, - unsigned char *buffer, size_t length) -{ - if (usbi_backend->dev_mem_free) - return usbi_backend->dev_mem_free(dev_handle, buffer, length); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Determine if a kernel driver is active on an interface. If a kernel driver - * is active, you cannot claim the interface, and libusb will be unable to - * perform I/O. - * - * This functionality is not available on Windows. - * - * \param dev_handle a device handle - * \param interface_number the interface to check - * \returns 0 if no kernel driver is active - * \returns 1 if a kernel driver is active - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_detach_kernel_driver() - */ -int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle, - int interface_number) -{ - usbi_dbg("interface %d", interface_number); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend->kernel_driver_active) - return usbi_backend->kernel_driver_active(dev_handle, interface_number); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Detach a kernel driver from an interface. If successful, you will then be - * able to claim the interface and perform I/O. - * - * This functionality is not available on Darwin or Windows. - * - * Note that libusb itself also talks to the device through a special kernel - * driver, if this driver is already attached to the device, this call will - * not detach it and return LIBUSB_ERROR_NOT_FOUND. - * - * \param dev_handle a device handle - * \param interface_number the interface to detach the driver from - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_kernel_driver_active() - */ -int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number) -{ - usbi_dbg("interface %d", interface_number); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend->detach_kernel_driver) - return usbi_backend->detach_kernel_driver(dev_handle, interface_number); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Re-attach an interface's kernel driver, which was previously detached - * using libusb_detach_kernel_driver(). This call is only effective on - * Linux and returns LIBUSB_ERROR_NOT_SUPPORTED on all other platforms. - * - * This functionality is not available on Darwin or Windows. - * - * \param dev_handle a device handle - * \param interface_number the interface to attach the driver from - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * \returns LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \returns LIBUSB_ERROR_BUSY if the driver cannot be attached because the - * interface is claimed by a program or driver - * \returns another LIBUSB_ERROR code on other failure - * \see libusb_kernel_driver_active() - */ -int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number) -{ - usbi_dbg("interface %d", interface_number); - - if (!dev_handle->dev->attached) - return LIBUSB_ERROR_NO_DEVICE; - - if (usbi_backend->attach_kernel_driver) - return usbi_backend->attach_kernel_driver(dev_handle, interface_number); - else - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -/** \ingroup libusb_dev - * Enable/disable libusb's automatic kernel driver detachment. When this is - * enabled libusb will automatically detach the kernel driver on an interface - * when claiming the interface, and attach it when releasing the interface. - * - * Automatic kernel driver detachment is disabled on newly opened device - * handles by default. - * - * On platforms which do not have LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER - * this function will return LIBUSB_ERROR_NOT_SUPPORTED, and libusb will - * continue as if this function was never called. - * - * \param dev_handle a device handle - * \param enable whether to enable or disable auto kernel driver detachment - * - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_NOT_SUPPORTED on platforms where the functionality - * is not available - * \see libusb_claim_interface() - * \see libusb_release_interface() - * \see libusb_set_configuration() - */ -int API_EXPORTED libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev_handle, int enable) -{ - if (!(usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER)) - return LIBUSB_ERROR_NOT_SUPPORTED; - - dev_handle->auto_detach_kernel_driver = enable; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_lib - * Set log message verbosity. - * - * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever - * printed. If you choose to increase the message verbosity level, ensure - * that your application does not close the stdout/stderr file descriptors. - * - * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative - * with its message logging and most of the time, will only log messages that - * explain error conditions and other oddities. This will help you debug - * your software. - * - * If the LIBUSB_DEBUG environment variable was set when libusb was - * initialized, this function does nothing: the message verbosity is fixed - * to the value in the environment variable. - * - * If libusb was compiled without any message logging, this function does - * nothing: you'll never get any messages. - * - * If libusb was compiled with verbose debug message logging, this function - * does nothing: you'll always get messages from all levels. - * - * \param ctx the context to operate on, or NULL for the default context - * \param level debug level to set - */ -void API_EXPORTED libusb_set_debug(libusb_context *ctx, int level) -{ - USBI_GET_CONTEXT(ctx); - if (!ctx->debug_fixed) - ctx->debug = level; -} - -/** \ingroup libusb_lib - * Initialize libusb. This function must be called before calling any other - * libusb function. - * - * If you do not provide an output location for a context pointer, a default - * context will be created. If there was already a default context, it will - * be reused (and nothing will be initialized/reinitialized). - * - * \param context Optional output location for context pointer. - * Only valid on return code 0. - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \see libusb_contexts - */ -int API_EXPORTED libusb_init(libusb_context **context) -{ - struct libusb_device *dev, *next; - char *dbg = getenv("LIBUSB_DEBUG"); - struct libusb_context *ctx; - static int first_init = 1; - int r = 0; - - usbi_mutex_static_lock(&default_context_lock); - - if (!timestamp_origin.tv_sec) { - usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, ×tamp_origin); - } - - if (!context && usbi_default_context) { - usbi_dbg("reusing default context"); - default_context_refcnt++; - usbi_mutex_static_unlock(&default_context_lock); - return 0; - } - - ctx = calloc(1, sizeof(*ctx)); - if (!ctx) { - r = LIBUSB_ERROR_NO_MEM; - goto err_unlock; - } - -#ifdef ENABLE_DEBUG_LOGGING - ctx->debug = LIBUSB_LOG_LEVEL_DEBUG; -#endif - - if (dbg) { - ctx->debug = atoi(dbg); - if (ctx->debug) - ctx->debug_fixed = 1; - } - - /* default context should be initialized before calling usbi_dbg */ - if (!usbi_default_context) { - usbi_default_context = ctx; - default_context_refcnt++; - usbi_dbg("created default context"); - } - - usbi_dbg("libusb v%u.%u.%u.%u%s", libusb_version_internal.major, libusb_version_internal.minor, - libusb_version_internal.micro, libusb_version_internal.nano, libusb_version_internal.rc); - - usbi_mutex_init(&ctx->usb_devs_lock); - usbi_mutex_init(&ctx->open_devs_lock); - usbi_mutex_init(&ctx->hotplug_cbs_lock); - list_init(&ctx->usb_devs); - list_init(&ctx->open_devs); - list_init(&ctx->hotplug_cbs); - - usbi_mutex_static_lock(&active_contexts_lock); - if (first_init) { - first_init = 0; - list_init (&active_contexts_list); - } - list_add (&ctx->list, &active_contexts_list); - usbi_mutex_static_unlock(&active_contexts_lock); - - if (usbi_backend->init) { - r = usbi_backend->init(ctx); - if (r) - goto err_free_ctx; - } - - r = usbi_io_init(ctx); - if (r < 0) - goto err_backend_exit; - - usbi_mutex_static_unlock(&default_context_lock); - - if (context) - *context = ctx; - - return 0; - -err_backend_exit: - if (usbi_backend->exit) - usbi_backend->exit(); -err_free_ctx: - if (ctx == usbi_default_context) { - usbi_default_context = NULL; - default_context_refcnt--; - } - - usbi_mutex_static_lock(&active_contexts_lock); - list_del (&ctx->list); - usbi_mutex_static_unlock(&active_contexts_lock); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) { - list_del(&dev->list); - libusb_unref_device(dev); - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - - usbi_mutex_destroy(&ctx->open_devs_lock); - usbi_mutex_destroy(&ctx->usb_devs_lock); - usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - - free(ctx); -err_unlock: - usbi_mutex_static_unlock(&default_context_lock); - return r; -} - -/** \ingroup libusb_lib - * Deinitialize libusb. Should be called after closing all open devices and - * before your application terminates. - * \param ctx the context to deinitialize, or NULL for the default context - */ -void API_EXPORTED libusb_exit(struct libusb_context *ctx) -{ - struct libusb_device *dev, *next; - struct timeval tv = { 0, 0 }; - - usbi_dbg(""); - USBI_GET_CONTEXT(ctx); - - /* if working with default context, only actually do the deinitialization - * if we're the last user */ - usbi_mutex_static_lock(&default_context_lock); - if (ctx == usbi_default_context) { - if (--default_context_refcnt > 0) { - usbi_dbg("not destroying default context"); - usbi_mutex_static_unlock(&default_context_lock); - return; - } - usbi_dbg("destroying default context"); - usbi_default_context = NULL; - } - usbi_mutex_static_unlock(&default_context_lock); - - usbi_mutex_static_lock(&active_contexts_lock); - list_del (&ctx->list); - usbi_mutex_static_unlock(&active_contexts_lock); - - if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - usbi_hotplug_deregister_all(ctx); - - /* - * Ensure any pending unplug events are read from the hotplug - * pipe. The usb_device-s hold in the events are no longer part - * of usb_devs, but the events still hold a reference! - * - * Note we don't do this if the application has left devices - * open (which implies a buggy app) to avoid packet completion - * handlers running when the app does not expect them to run. - */ - if (list_empty(&ctx->open_devs)) - libusb_handle_events_timeout(ctx, &tv); - - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) { - list_del(&dev->list); - libusb_unref_device(dev); - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - } - - /* a few sanity checks. don't bother with locking because unless - * there is an application bug, nobody will be accessing these. */ - if (!list_empty(&ctx->usb_devs)) - usbi_warn(ctx, "some libusb_devices were leaked"); - if (!list_empty(&ctx->open_devs)) - usbi_warn(ctx, "application left some devices open"); - - usbi_io_exit(ctx); - if (usbi_backend->exit) - usbi_backend->exit(); - - usbi_mutex_destroy(&ctx->open_devs_lock); - usbi_mutex_destroy(&ctx->usb_devs_lock); - usbi_mutex_destroy(&ctx->hotplug_cbs_lock); - free(ctx); -} - -/** \ingroup libusb_misc - * Check at runtime if the loaded library has a given capability. - * This call should be performed after \ref libusb_init(), to ensure the - * backend has updated its capability set. - * - * \param capability the \ref libusb_capability to check for - * \returns nonzero if the running library has the capability, 0 otherwise - */ -int API_EXPORTED libusb_has_capability(uint32_t capability) -{ - switch (capability) { - case LIBUSB_CAP_HAS_CAPABILITY: - return 1; - case LIBUSB_CAP_HAS_HOTPLUG: - return !(usbi_backend->get_device_list); - case LIBUSB_CAP_HAS_HID_ACCESS: - return (usbi_backend->caps & USBI_CAP_HAS_HID_ACCESS); - case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: - return (usbi_backend->caps & USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); - } - return 0; -} - -/* this is defined in libusbi.h if needed */ -#ifdef LIBUSB_PRINTF_WIN32 -/* - * Prior to VS2015, Microsoft did not provide the snprintf() function and - * provided a vsnprintf() that did not guarantee NULL-terminated output. - * Microsoft did provide a _snprintf() function, but again it did not - * guarantee NULL-terminated output. - * - * The below implementations guarantee NULL-terminated output and are - * C99 compliant. - */ - -int usbi_snprintf(char *str, size_t size, const char *format, ...) -{ - va_list ap; - int ret; - - va_start(ap, format); - ret = usbi_vsnprintf(str, size, format, ap); - va_end(ap); - - return ret; -} - -int usbi_vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - int ret; - - ret = _vsnprintf(str, size, format, ap); - if (ret < 0 || ret == (int)size) { - /* Output is truncated, ensure buffer is NULL-terminated and - * determine how many characters would have been written. */ - str[size - 1] = '\0'; - if (ret < 0) - ret = _vsnprintf(NULL, 0, format, ap); - } - - return ret; -} -#endif - -static void usbi_log_str(struct libusb_context *ctx, - enum libusb_log_level level, const char * str) -{ -#if defined(USE_SYSTEM_LOGGING_FACILITY) -#if defined(OS_WINDOWS) - OutputDebugString(str); -#elif defined(OS_WINCE) - /* Windows CE only supports the Unicode version of OutputDebugString. */ - WCHAR wbuf[USBI_MAX_LOG_LEN]; - MultiByteToWideChar(CP_UTF8, 0, str, -1, wbuf, sizeof(wbuf)); - OutputDebugStringW(wbuf); -#elif defined(__ANDROID__) - int priority = ANDROID_LOG_UNKNOWN; - switch (level) { - case LIBUSB_LOG_LEVEL_INFO: priority = ANDROID_LOG_INFO; break; - case LIBUSB_LOG_LEVEL_WARNING: priority = ANDROID_LOG_WARN; break; - case LIBUSB_LOG_LEVEL_ERROR: priority = ANDROID_LOG_ERROR; break; - case LIBUSB_LOG_LEVEL_DEBUG: priority = ANDROID_LOG_DEBUG; break; - } - __android_log_write(priority, "libusb", str); -#elif defined(HAVE_SYSLOG_FUNC) - int syslog_level = LOG_INFO; - switch (level) { - case LIBUSB_LOG_LEVEL_INFO: syslog_level = LOG_INFO; break; - case LIBUSB_LOG_LEVEL_WARNING: syslog_level = LOG_WARNING; break; - case LIBUSB_LOG_LEVEL_ERROR: syslog_level = LOG_ERR; break; - case LIBUSB_LOG_LEVEL_DEBUG: syslog_level = LOG_DEBUG; break; - } - syslog(syslog_level, "%s", str); -#else /* All of gcc, Clang, XCode seem to use #warning */ -#warning System logging is not supported on this platform. Logging to stderr will be used instead. - fputs(str, stderr); -#endif -#else - fputs(str, stderr); -#endif /* USE_SYSTEM_LOGGING_FACILITY */ - UNUSED(ctx); - UNUSED(level); -} - -void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, va_list args) -{ - const char *prefix = ""; - char buf[USBI_MAX_LOG_LEN]; - struct timespec now; - int global_debug, header_len, text_len; - static int has_debug_header_been_displayed = 0; - -#ifdef ENABLE_DEBUG_LOGGING - global_debug = 1; - UNUSED(ctx); -#else - int ctx_level = 0; - - USBI_GET_CONTEXT(ctx); - if (ctx) { - ctx_level = ctx->debug; - } else { - char *dbg = getenv("LIBUSB_DEBUG"); - if (dbg) - ctx_level = atoi(dbg); - } - global_debug = (ctx_level == LIBUSB_LOG_LEVEL_DEBUG); - if (!ctx_level) - return; - if (level == LIBUSB_LOG_LEVEL_WARNING && ctx_level < LIBUSB_LOG_LEVEL_WARNING) - return; - if (level == LIBUSB_LOG_LEVEL_INFO && ctx_level < LIBUSB_LOG_LEVEL_INFO) - return; - if (level == LIBUSB_LOG_LEVEL_DEBUG && ctx_level < LIBUSB_LOG_LEVEL_DEBUG) - return; -#endif - - usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &now); - if ((global_debug) && (!has_debug_header_been_displayed)) { - has_debug_header_been_displayed = 1; - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "[timestamp] [threadID] facility level [function call] " USBI_LOG_LINE_END); - usbi_log_str(ctx, LIBUSB_LOG_LEVEL_DEBUG, "--------------------------------------------------------------------------------" USBI_LOG_LINE_END); - } - if (now.tv_nsec < timestamp_origin.tv_nsec) { - now.tv_sec--; - now.tv_nsec += 1000000000L; - } - now.tv_sec -= timestamp_origin.tv_sec; - now.tv_nsec -= timestamp_origin.tv_nsec; - - switch (level) { - case LIBUSB_LOG_LEVEL_INFO: - prefix = "info"; - break; - case LIBUSB_LOG_LEVEL_WARNING: - prefix = "warning"; - break; - case LIBUSB_LOG_LEVEL_ERROR: - prefix = "error"; - break; - case LIBUSB_LOG_LEVEL_DEBUG: - prefix = "debug"; - break; - case LIBUSB_LOG_LEVEL_NONE: - return; - default: - prefix = "unknown"; - break; - } - - if (global_debug) { - header_len = snprintf(buf, sizeof(buf), - "[%2d.%06d] [%08x] libusb: %s [%s] ", - (int)now.tv_sec, (int)(now.tv_nsec / 1000L), usbi_get_tid(), prefix, function); - } else { - header_len = snprintf(buf, sizeof(buf), - "libusb: %s [%s] ", prefix, function); - } - - if (header_len < 0 || header_len >= (int)sizeof(buf)) { - /* Somehow snprintf failed to write to the buffer, - * remove the header so something useful is output. */ - header_len = 0; - } - /* Make sure buffer is NUL terminated */ - buf[header_len] = '\0'; - text_len = vsnprintf(buf + header_len, sizeof(buf) - header_len, - format, args); - if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) { - /* Truncated log output. On some platforms a -1 return value means - * that the output was truncated. */ - text_len = sizeof(buf) - header_len; - } - if (header_len + text_len + sizeof(USBI_LOG_LINE_END) >= sizeof(buf)) { - /* Need to truncate the text slightly to fit on the terminator. */ - text_len -= (header_len + text_len + sizeof(USBI_LOG_LINE_END)) - sizeof(buf); - } - strcpy(buf + header_len + text_len, USBI_LOG_LINE_END); - - usbi_log_str(ctx, level, buf); -} - -void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, ...) -{ - va_list args; - - va_start (args, format); - usbi_log_v(ctx, level, function, format, args); - va_end (args); -} - -/** \ingroup libusb_misc - * Returns a constant NULL-terminated string with the ASCII name of a libusb - * error or transfer status code. The caller must not free() the returned - * string. - * - * \param error_code The \ref libusb_error or libusb_transfer_status code to - * return the name of. - * \returns The error name, or the string **UNKNOWN** if the value of - * error_code is not a known error / status code. - */ -DEFAULT_VISIBILITY const char * LIBUSB_CALL libusb_error_name(int error_code) -{ - switch (error_code) { - case LIBUSB_ERROR_IO: - return "LIBUSB_ERROR_IO"; - case LIBUSB_ERROR_INVALID_PARAM: - return "LIBUSB_ERROR_INVALID_PARAM"; - case LIBUSB_ERROR_ACCESS: - return "LIBUSB_ERROR_ACCESS"; - case LIBUSB_ERROR_NO_DEVICE: - return "LIBUSB_ERROR_NO_DEVICE"; - case LIBUSB_ERROR_NOT_FOUND: - return "LIBUSB_ERROR_NOT_FOUND"; - case LIBUSB_ERROR_BUSY: - return "LIBUSB_ERROR_BUSY"; - case LIBUSB_ERROR_TIMEOUT: - return "LIBUSB_ERROR_TIMEOUT"; - case LIBUSB_ERROR_OVERFLOW: - return "LIBUSB_ERROR_OVERFLOW"; - case LIBUSB_ERROR_PIPE: - return "LIBUSB_ERROR_PIPE"; - case LIBUSB_ERROR_INTERRUPTED: - return "LIBUSB_ERROR_INTERRUPTED"; - case LIBUSB_ERROR_NO_MEM: - return "LIBUSB_ERROR_NO_MEM"; - case LIBUSB_ERROR_NOT_SUPPORTED: - return "LIBUSB_ERROR_NOT_SUPPORTED"; - case LIBUSB_ERROR_OTHER: - return "LIBUSB_ERROR_OTHER"; - - case LIBUSB_TRANSFER_ERROR: - return "LIBUSB_TRANSFER_ERROR"; - case LIBUSB_TRANSFER_TIMED_OUT: - return "LIBUSB_TRANSFER_TIMED_OUT"; - case LIBUSB_TRANSFER_CANCELLED: - return "LIBUSB_TRANSFER_CANCELLED"; - case LIBUSB_TRANSFER_STALL: - return "LIBUSB_TRANSFER_STALL"; - case LIBUSB_TRANSFER_NO_DEVICE: - return "LIBUSB_TRANSFER_NO_DEVICE"; - case LIBUSB_TRANSFER_OVERFLOW: - return "LIBUSB_TRANSFER_OVERFLOW"; - - case 0: - return "LIBUSB_SUCCESS / LIBUSB_TRANSFER_COMPLETED"; - default: - return "**UNKNOWN**"; - } -} - -/** \ingroup libusb_misc - * Returns a pointer to const struct libusb_version with the version - * (major, minor, micro, nano and rc) of the running library. - */ -DEFAULT_VISIBILITY -const struct libusb_version * LIBUSB_CALL libusb_get_version(void) -{ - return &libusb_version_internal; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/descriptor.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/descriptor.c deleted file mode 100644 index 4c9435fffe4..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/descriptor.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * USB descriptor handling functions for libusb - * Copyright © 2007 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include - -#include "libusbi.h" - -#define DESC_HEADER_LENGTH 2 -#define DEVICE_DESC_LENGTH 18 -#define CONFIG_DESC_LENGTH 9 -#define INTERFACE_DESC_LENGTH 9 -#define ENDPOINT_DESC_LENGTH 7 -#define ENDPOINT_AUDIO_DESC_LENGTH 9 - -/** @defgroup libusb_desc USB descriptors - * This page details how to examine the various standard USB descriptors - * for detected devices - */ - -/* set host_endian if the w values are already in host endian format, - * as opposed to bus endian. */ -int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, - void *dest, int host_endian) -{ - const unsigned char *sp = source; - unsigned char *dp = dest; - uint16_t w; - const char *cp; - uint32_t d; - - for (cp = descriptor; *cp; cp++) { - switch (*cp) { - case 'b': /* 8-bit byte */ - *dp++ = *sp++; - break; - case 'w': /* 16-bit word, convert from little endian to CPU */ - dp += ((uintptr_t)dp & 1); /* Align to word boundary */ - - if (host_endian) { - memcpy(dp, sp, 2); - } else { - w = (sp[1] << 8) | sp[0]; - *((uint16_t *)dp) = w; - } - sp += 2; - dp += 2; - break; - case 'd': /* 32-bit word, convert from little endian to CPU */ - dp += ((uintptr_t)dp & 1); /* Align to word boundary */ - - if (host_endian) { - memcpy(dp, sp, 4); - } else { - d = (sp[3] << 24) | (sp[2] << 16) | - (sp[1] << 8) | sp[0]; - *((uint32_t *)dp) = d; - } - sp += 4; - dp += 4; - break; - case 'u': /* 16 byte UUID */ - memcpy(dp, sp, 16); - sp += 16; - dp += 16; - break; - } - } - - return (int) (sp - source); -} - -static void clear_endpoint(struct libusb_endpoint_descriptor *endpoint) -{ - free((void *) endpoint->extra); -} - -static int parse_endpoint(struct libusb_context *ctx, - struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer, - int size, int host_endian) -{ - struct usb_descriptor_header header; - unsigned char *extra; - unsigned char *begin; - int parsed = 0; - int len; - - if (size < DESC_HEADER_LENGTH) { - usbi_err(ctx, "short endpoint descriptor read %d/%d", - size, DESC_HEADER_LENGTH); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - header.bDescriptorType, LIBUSB_DT_ENDPOINT); - return parsed; - } - if (header.bLength > size) { - usbi_warn(ctx, "short endpoint descriptor read %d/%d", - size, header.bLength); - return parsed; - } - if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH) - usbi_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian); - else if (header.bLength >= ENDPOINT_DESC_LENGTH) - usbi_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian); - else { - usbi_err(ctx, "invalid endpoint bLength (%d)", header.bLength); - return LIBUSB_ERROR_IO; - } - - buffer += header.bLength; - size -= header.bLength; - parsed += header.bLength; - - /* Skip over the rest of the Class Specific or Vendor Specific */ - /* descriptors */ - begin = buffer; - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bLength < DESC_HEADER_LENGTH) { - usbi_err(ctx, "invalid extra ep desc len (%d)", - header.bLength); - return LIBUSB_ERROR_IO; - } else if (header.bLength > size) { - usbi_warn(ctx, "short extra ep desc read %d/%d", - size, header.bLength); - return parsed; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) || - (header.bDescriptorType == LIBUSB_DT_INTERFACE) || - (header.bDescriptorType == LIBUSB_DT_CONFIG) || - (header.bDescriptorType == LIBUSB_DT_DEVICE)) - break; - - usbi_dbg("skipping descriptor %x", header.bDescriptorType); - buffer += header.bLength; - size -= header.bLength; - parsed += header.bLength; - } - - /* Copy any unknown descriptors into a storage area for drivers */ - /* to later parse */ - len = (int)(buffer - begin); - if (!len) { - endpoint->extra = NULL; - endpoint->extra_length = 0; - return parsed; - } - - extra = malloc(len); - endpoint->extra = extra; - if (!extra) { - endpoint->extra_length = 0; - return LIBUSB_ERROR_NO_MEM; - } - - memcpy(extra, begin, len); - endpoint->extra_length = len; - - return parsed; -} - -static void clear_interface(struct libusb_interface *usb_interface) -{ - int i; - int j; - - if (usb_interface->altsetting) { - for (i = 0; i < usb_interface->num_altsetting; i++) { - struct libusb_interface_descriptor *ifp = - (struct libusb_interface_descriptor *) - usb_interface->altsetting + i; - free((void *) ifp->extra); - if (ifp->endpoint) { - for (j = 0; j < ifp->bNumEndpoints; j++) - clear_endpoint((struct libusb_endpoint_descriptor *) - ifp->endpoint + j); - } - free((void *) ifp->endpoint); - } - } - free((void *) usb_interface->altsetting); - usb_interface->altsetting = NULL; -} - -static int parse_interface(libusb_context *ctx, - struct libusb_interface *usb_interface, unsigned char *buffer, int size, - int host_endian) -{ - int i; - int len; - int r; - int parsed = 0; - int interface_number = -1; - struct usb_descriptor_header header; - struct libusb_interface_descriptor *ifp; - unsigned char *begin; - - usb_interface->num_altsetting = 0; - - while (size >= INTERFACE_DESC_LENGTH) { - struct libusb_interface_descriptor *altsetting = - (struct libusb_interface_descriptor *) usb_interface->altsetting; - altsetting = usbi_reallocf(altsetting, - sizeof(struct libusb_interface_descriptor) * - (usb_interface->num_altsetting + 1)); - if (!altsetting) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - usb_interface->altsetting = altsetting; - - ifp = altsetting + usb_interface->num_altsetting; - usbi_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0); - if (ifp->bDescriptorType != LIBUSB_DT_INTERFACE) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - ifp->bDescriptorType, LIBUSB_DT_INTERFACE); - return parsed; - } - if (ifp->bLength < INTERFACE_DESC_LENGTH) { - usbi_err(ctx, "invalid interface bLength (%d)", - ifp->bLength); - r = LIBUSB_ERROR_IO; - goto err; - } - if (ifp->bLength > size) { - usbi_warn(ctx, "short intf descriptor read %d/%d", - size, ifp->bLength); - return parsed; - } - if (ifp->bNumEndpoints > USB_MAXENDPOINTS) { - usbi_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints); - r = LIBUSB_ERROR_IO; - goto err; - } - - usb_interface->num_altsetting++; - ifp->extra = NULL; - ifp->extra_length = 0; - ifp->endpoint = NULL; - - if (interface_number == -1) - interface_number = ifp->bInterfaceNumber; - - /* Skip over the interface */ - buffer += ifp->bLength; - parsed += ifp->bLength; - size -= ifp->bLength; - - begin = buffer; - - /* Skip over any interface, class or vendor descriptors */ - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bLength < DESC_HEADER_LENGTH) { - usbi_err(ctx, - "invalid extra intf desc len (%d)", - header.bLength); - r = LIBUSB_ERROR_IO; - goto err; - } else if (header.bLength > size) { - usbi_warn(ctx, - "short extra intf desc read %d/%d", - size, header.bLength); - return parsed; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) || - (header.bDescriptorType == LIBUSB_DT_ENDPOINT) || - (header.bDescriptorType == LIBUSB_DT_CONFIG) || - (header.bDescriptorType == LIBUSB_DT_DEVICE)) - break; - - buffer += header.bLength; - parsed += header.bLength; - size -= header.bLength; - } - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - ifp->extra = malloc(len); - if (!ifp->extra) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - memcpy((unsigned char *) ifp->extra, begin, len); - ifp->extra_length = len; - } - - if (ifp->bNumEndpoints > 0) { - struct libusb_endpoint_descriptor *endpoint; - endpoint = calloc(ifp->bNumEndpoints, sizeof(struct libusb_endpoint_descriptor)); - ifp->endpoint = endpoint; - if (!endpoint) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - - for (i = 0; i < ifp->bNumEndpoints; i++) { - r = parse_endpoint(ctx, endpoint + i, buffer, size, - host_endian); - if (r < 0) - goto err; - if (r == 0) { - ifp->bNumEndpoints = (uint8_t)i; - break;; - } - - buffer += r; - parsed += r; - size -= r; - } - } - - /* We check to see if it's an alternate to this one */ - ifp = (struct libusb_interface_descriptor *) buffer; - if (size < LIBUSB_DT_INTERFACE_SIZE || - ifp->bDescriptorType != LIBUSB_DT_INTERFACE || - ifp->bInterfaceNumber != interface_number) - return parsed; - } - - return parsed; -err: - clear_interface(usb_interface); - return r; -} - -static void clear_configuration(struct libusb_config_descriptor *config) -{ - int i; - if (config->interface) { - for (i = 0; i < config->bNumInterfaces; i++) - clear_interface((struct libusb_interface *) - config->interface + i); - } - free((void *) config->interface); - free((void *) config->extra); -} - -static int parse_configuration(struct libusb_context *ctx, - struct libusb_config_descriptor *config, unsigned char *buffer, - int size, int host_endian) -{ - int i; - int r; - struct usb_descriptor_header header; - struct libusb_interface *usb_interface; - - if (size < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "short config descriptor read %d/%d", - size, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian); - if (config->bDescriptorType != LIBUSB_DT_CONFIG) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - config->bDescriptorType, LIBUSB_DT_CONFIG); - return LIBUSB_ERROR_IO; - } - if (config->bLength < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "invalid config bLength (%d)", config->bLength); - return LIBUSB_ERROR_IO; - } - if (config->bLength > size) { - usbi_err(ctx, "short config descriptor read %d/%d", - size, config->bLength); - return LIBUSB_ERROR_IO; - } - if (config->bNumInterfaces > USB_MAXINTERFACES) { - usbi_err(ctx, "too many interfaces (%d)", config->bNumInterfaces); - return LIBUSB_ERROR_IO; - } - - usb_interface = calloc(config->bNumInterfaces, sizeof(struct libusb_interface)); - config->interface = usb_interface; - if (!usb_interface) - return LIBUSB_ERROR_NO_MEM; - - buffer += config->bLength; - size -= config->bLength; - - config->extra = NULL; - config->extra_length = 0; - - for (i = 0; i < config->bNumInterfaces; i++) { - int len; - unsigned char *begin; - - /* Skip over the rest of the Class Specific or Vendor */ - /* Specific descriptors */ - begin = buffer; - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - - if (header.bLength < DESC_HEADER_LENGTH) { - usbi_err(ctx, - "invalid extra config desc len (%d)", - header.bLength); - r = LIBUSB_ERROR_IO; - goto err; - } else if (header.bLength > size) { - usbi_warn(ctx, - "short extra config desc read %d/%d", - size, header.bLength); - config->bNumInterfaces = (uint8_t)i; - return size; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) || - (header.bDescriptorType == LIBUSB_DT_INTERFACE) || - (header.bDescriptorType == LIBUSB_DT_CONFIG) || - (header.bDescriptorType == LIBUSB_DT_DEVICE)) - break; - - usbi_dbg("skipping descriptor 0x%x", header.bDescriptorType); - buffer += header.bLength; - size -= header.bLength; - } - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - /* FIXME: We should realloc and append here */ - if (!config->extra_length) { - config->extra = malloc(len); - if (!config->extra) { - r = LIBUSB_ERROR_NO_MEM; - goto err; - } - - memcpy((unsigned char *) config->extra, begin, len); - config->extra_length = len; - } - } - - r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian); - if (r < 0) - goto err; - if (r == 0) { - config->bNumInterfaces = (uint8_t)i; - break; - } - - buffer += r; - size -= r; - } - - return size; - -err: - clear_configuration(config); - return r; -} - -static int raw_desc_to_config(struct libusb_context *ctx, - unsigned char *buf, int size, int host_endian, - struct libusb_config_descriptor **config) -{ - struct libusb_config_descriptor *_config = malloc(sizeof(*_config)); - int r; - - if (!_config) - return LIBUSB_ERROR_NO_MEM; - - r = parse_configuration(ctx, _config, buf, size, host_endian); - if (r < 0) { - usbi_err(ctx, "parse_configuration failed with error %d", r); - free(_config); - return r; - } else if (r > 0) { - usbi_warn(ctx, "still %d bytes of descriptor data left", r); - } - - *config = _config; - return LIBUSB_SUCCESS; -} - -int usbi_device_cache_descriptor(libusb_device *dev) -{ - int r, host_endian = 0; - - r = usbi_backend->get_device_descriptor(dev, (unsigned char *) &dev->device_descriptor, - &host_endian); - if (r < 0) - return r; - - if (!host_endian) { - dev->device_descriptor.bcdUSB = libusb_le16_to_cpu(dev->device_descriptor.bcdUSB); - dev->device_descriptor.idVendor = libusb_le16_to_cpu(dev->device_descriptor.idVendor); - dev->device_descriptor.idProduct = libusb_le16_to_cpu(dev->device_descriptor.idProduct); - dev->device_descriptor.bcdDevice = libusb_le16_to_cpu(dev->device_descriptor.bcdDevice); - } - - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Get the USB device descriptor for a given device. - * - * This is a non-blocking function; the device descriptor is cached in memory. - * - * Note since libusb-1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, this - * function always succeeds. - * - * \param dev the device - * \param desc output location for the descriptor data - * \returns 0 on success or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev, - struct libusb_device_descriptor *desc) -{ - usbi_dbg(""); - memcpy((unsigned char *) desc, (unsigned char *) &dev->device_descriptor, - sizeof (dev->device_descriptor)); - return 0; -} - -/** \ingroup libusb_desc - * Get the USB configuration descriptor for the currently active configuration. - * This is a non-blocking function which does not involve any requests being - * sent to the device. - * - * \param dev a device - * \param config output location for the USB configuration descriptor. Only - * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() - * after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state - * \returns another LIBUSB_ERROR code on error - * \see libusb_get_config_descriptor - */ -int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, - struct libusb_config_descriptor **config) -{ - struct libusb_config_descriptor _config; - unsigned char tmp[LIBUSB_DT_CONFIG_SIZE]; - unsigned char *buf = NULL; - int host_endian = 0; - int r; - - r = usbi_backend->get_active_config_descriptor(dev, tmp, - LIBUSB_DT_CONFIG_SIZE, &host_endian); - if (r < 0) - return r; - if (r < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(dev->ctx, "short config descriptor read %d/%d", - r, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(tmp, "bbw", &_config, host_endian); - buf = malloc(_config.wTotalLength); - if (!buf) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_backend->get_active_config_descriptor(dev, buf, - _config.wTotalLength, &host_endian); - if (r >= 0) - r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); - - free(buf); - return r; -} - -/** \ingroup libusb_desc - * Get a USB configuration descriptor based on its index. - * This is a non-blocking function which does not involve any requests being - * sent to the device. - * - * \param dev a device - * \param config_index the index of the configuration you wish to retrieve - * \param config output location for the USB configuration descriptor. Only - * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() - * after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * \returns another LIBUSB_ERROR code on error - * \see libusb_get_active_config_descriptor() - * \see libusb_get_config_descriptor_by_value() - */ -int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev, - uint8_t config_index, struct libusb_config_descriptor **config) -{ - struct libusb_config_descriptor _config; - unsigned char tmp[LIBUSB_DT_CONFIG_SIZE]; - unsigned char *buf = NULL; - int host_endian = 0; - int r; - - usbi_dbg("index %d", config_index); - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_NOT_FOUND; - - r = usbi_backend->get_config_descriptor(dev, config_index, tmp, - LIBUSB_DT_CONFIG_SIZE, &host_endian); - if (r < 0) - return r; - if (r < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(dev->ctx, "short config descriptor read %d/%d", - r, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(tmp, "bbw", &_config, host_endian); - buf = malloc(_config.wTotalLength); - if (!buf) - return LIBUSB_ERROR_NO_MEM; - - r = usbi_backend->get_config_descriptor(dev, config_index, buf, - _config.wTotalLength, &host_endian); - if (r >= 0) - r = raw_desc_to_config(dev->ctx, buf, r, host_endian, config); - - free(buf); - return r; -} - -/* iterate through all configurations, returning the index of the configuration - * matching a specific bConfigurationValue in the idx output parameter, or -1 - * if the config was not found. - * returns 0 on success or a LIBUSB_ERROR code - */ -int usbi_get_config_index_by_value(struct libusb_device *dev, - uint8_t bConfigurationValue, int *idx) -{ - uint8_t i; - - usbi_dbg("value %d", bConfigurationValue); - for (i = 0; i < dev->num_configurations; i++) { - unsigned char tmp[6]; - int host_endian; - int r = usbi_backend->get_config_descriptor(dev, i, tmp, sizeof(tmp), - &host_endian); - if (r < 0) { - *idx = -1; - return r; - } - if (tmp[5] == bConfigurationValue) { - *idx = i; - return 0; - } - } - - *idx = -1; - return 0; -} - -/** \ingroup libusb_desc - * Get a USB configuration descriptor with a specific bConfigurationValue. - * This is a non-blocking function which does not involve any requests being - * sent to the device. - * - * \param dev a device - * \param bConfigurationValue the bConfigurationValue of the configuration you - * wish to retrieve - * \param config output location for the USB configuration descriptor. Only - * valid if 0 was returned. Must be freed with libusb_free_config_descriptor() - * after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * \returns another LIBUSB_ERROR code on error - * \see libusb_get_active_config_descriptor() - * \see libusb_get_config_descriptor() - */ -int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, - uint8_t bConfigurationValue, struct libusb_config_descriptor **config) -{ - int r, idx, host_endian; - unsigned char *buf = NULL; - - if (usbi_backend->get_config_descriptor_by_value) { - r = usbi_backend->get_config_descriptor_by_value(dev, - bConfigurationValue, &buf, &host_endian); - if (r < 0) - return r; - return raw_desc_to_config(dev->ctx, buf, r, host_endian, config); - } - - r = usbi_get_config_index_by_value(dev, bConfigurationValue, &idx); - if (r < 0) - return r; - else if (idx == -1) - return LIBUSB_ERROR_NOT_FOUND; - else - return libusb_get_config_descriptor(dev, (uint8_t) idx, config); -} - -/** \ingroup libusb_desc - * Free a configuration descriptor obtained from - * libusb_get_active_config_descriptor() or libusb_get_config_descriptor(). - * It is safe to call this function with a NULL config parameter, in which - * case the function simply returns. - * - * \param config the configuration descriptor to free - */ -void API_EXPORTED libusb_free_config_descriptor( - struct libusb_config_descriptor *config) -{ - if (!config) - return; - - clear_configuration(config); - free(config); -} - -/** \ingroup libusb_desc - * Get an endpoints superspeed endpoint companion descriptor (if any) - * - * \param ctx the context to operate on, or NULL for the default context - * \param endpoint endpoint descriptor from which to get the superspeed - * endpoint companion descriptor - * \param ep_comp output location for the superspeed endpoint companion - * descriptor. Only valid if 0 was returned. Must be freed with - * libusb_free_ss_endpoint_companion_descriptor() after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * \returns another LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_ss_endpoint_companion_descriptor( - struct libusb_context *ctx, - const struct libusb_endpoint_descriptor *endpoint, - struct libusb_ss_endpoint_companion_descriptor **ep_comp) -{ - struct usb_descriptor_header header; - int size = endpoint->extra_length; - const unsigned char *buffer = endpoint->extra; - - *ep_comp = NULL; - - while (size >= DESC_HEADER_LENGTH) { - usbi_parse_descriptor(buffer, "bb", &header, 0); - if (header.bLength < 2 || header.bLength > size) { - usbi_err(ctx, "invalid descriptor length %d", - header.bLength); - return LIBUSB_ERROR_IO; - } - if (header.bDescriptorType != LIBUSB_DT_SS_ENDPOINT_COMPANION) { - buffer += header.bLength; - size -= header.bLength; - continue; - } - if (header.bLength < LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE) { - usbi_err(ctx, "invalid ss-ep-comp-desc length %d", - header.bLength); - return LIBUSB_ERROR_IO; - } - *ep_comp = malloc(sizeof(**ep_comp)); - if (*ep_comp == NULL) - return LIBUSB_ERROR_NO_MEM; - usbi_parse_descriptor(buffer, "bbbbw", *ep_comp, 0); - return LIBUSB_SUCCESS; - } - return LIBUSB_ERROR_NOT_FOUND; -} - -/** \ingroup libusb_desc - * Free a superspeed endpoint companion descriptor obtained from - * libusb_get_ss_endpoint_companion_descriptor(). - * It is safe to call this function with a NULL ep_comp parameter, in which - * case the function simply returns. - * - * \param ep_comp the superspeed endpoint companion descriptor to free - */ -void API_EXPORTED libusb_free_ss_endpoint_companion_descriptor( - struct libusb_ss_endpoint_companion_descriptor *ep_comp) -{ - free(ep_comp); -} - -static int parse_bos(struct libusb_context *ctx, - struct libusb_bos_descriptor **bos, - unsigned char *buffer, int size, int host_endian) -{ - struct libusb_bos_descriptor bos_header, *_bos; - struct libusb_bos_dev_capability_descriptor dev_cap; - int i; - - if (size < LIBUSB_DT_BOS_SIZE) { - usbi_err(ctx, "short bos descriptor read %d/%d", - size, LIBUSB_DT_BOS_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bbwb", &bos_header, host_endian); - if (bos_header.bDescriptorType != LIBUSB_DT_BOS) { - usbi_err(ctx, "unexpected descriptor %x (expected %x)", - bos_header.bDescriptorType, LIBUSB_DT_BOS); - return LIBUSB_ERROR_IO; - } - if (bos_header.bLength < LIBUSB_DT_BOS_SIZE) { - usbi_err(ctx, "invalid bos bLength (%d)", bos_header.bLength); - return LIBUSB_ERROR_IO; - } - if (bos_header.bLength > size) { - usbi_err(ctx, "short bos descriptor read %d/%d", - size, bos_header.bLength); - return LIBUSB_ERROR_IO; - } - - _bos = calloc (1, - sizeof(*_bos) + bos_header.bNumDeviceCaps * sizeof(void *)); - if (!_bos) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor(buffer, "bbwb", _bos, host_endian); - buffer += bos_header.bLength; - size -= bos_header.bLength; - - /* Get the device capability descriptors */ - for (i = 0; i < bos_header.bNumDeviceCaps; i++) { - if (size < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) { - usbi_warn(ctx, "short dev-cap descriptor read %d/%d", - size, LIBUSB_DT_DEVICE_CAPABILITY_SIZE); - break; - } - usbi_parse_descriptor(buffer, "bbb", &dev_cap, host_endian); - if (dev_cap.bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) { - usbi_warn(ctx, "unexpected descriptor %x (expected %x)", - dev_cap.bDescriptorType, LIBUSB_DT_DEVICE_CAPABILITY); - break; - } - if (dev_cap.bLength < LIBUSB_DT_DEVICE_CAPABILITY_SIZE) { - usbi_err(ctx, "invalid dev-cap bLength (%d)", - dev_cap.bLength); - libusb_free_bos_descriptor(_bos); - return LIBUSB_ERROR_IO; - } - if (dev_cap.bLength > size) { - usbi_warn(ctx, "short dev-cap descriptor read %d/%d", - size, dev_cap.bLength); - break; - } - - _bos->dev_capability[i] = malloc(dev_cap.bLength); - if (!_bos->dev_capability[i]) { - libusb_free_bos_descriptor(_bos); - return LIBUSB_ERROR_NO_MEM; - } - memcpy(_bos->dev_capability[i], buffer, dev_cap.bLength); - buffer += dev_cap.bLength; - size -= dev_cap.bLength; - } - _bos->bNumDeviceCaps = (uint8_t)i; - *bos = _bos; - - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Get a Binary Object Store (BOS) descriptor - * This is a BLOCKING function, which will send requests to the device. - * - * \param dev_handle the handle of an open libusb device - * \param bos output location for the BOS descriptor. Only valid if 0 was returned. - * Must be freed with \ref libusb_free_bos_descriptor() after use. - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the device doesn't have a BOS descriptor - * \returns another LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_bos_descriptor(libusb_device_handle *dev_handle, - struct libusb_bos_descriptor **bos) -{ - struct libusb_bos_descriptor _bos; - uint8_t bos_header[LIBUSB_DT_BOS_SIZE] = {0}; - unsigned char *bos_data = NULL; - const int host_endian = 0; - int r; - - /* Read the BOS. This generates 2 requests on the bus, - * one for the header, and one for the full BOS */ - r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_header, - LIBUSB_DT_BOS_SIZE); - if (r < 0) { - if (r != LIBUSB_ERROR_PIPE) - usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); - return r; - } - if (r < LIBUSB_DT_BOS_SIZE) { - usbi_err(HANDLE_CTX(dev_handle), "short BOS read %d/%d", - r, LIBUSB_DT_BOS_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(bos_header, "bbwb", &_bos, host_endian); - usbi_dbg("found BOS descriptor: size %d bytes, %d capabilities", - _bos.wTotalLength, _bos.bNumDeviceCaps); - bos_data = calloc(_bos.wTotalLength, 1); - if (bos_data == NULL) - return LIBUSB_ERROR_NO_MEM; - - r = libusb_get_descriptor(dev_handle, LIBUSB_DT_BOS, 0, bos_data, - _bos.wTotalLength); - if (r >= 0) - r = parse_bos(HANDLE_CTX(dev_handle), bos, bos_data, r, host_endian); - else - usbi_err(HANDLE_CTX(dev_handle), "failed to read BOS (%d)", r); - - free(bos_data); - return r; -} - -/** \ingroup libusb_desc - * Free a BOS descriptor obtained from libusb_get_bos_descriptor(). - * It is safe to call this function with a NULL bos parameter, in which - * case the function simply returns. - * - * \param bos the BOS descriptor to free - */ -void API_EXPORTED libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) -{ - int i; - - if (!bos) - return; - - for (i = 0; i < bos->bNumDeviceCaps; i++) - free(bos->dev_capability[i]); - free(bos); -} - -/** \ingroup libusb_desc - * Get an USB 2.0 Extension descriptor - * - * \param ctx the context to operate on, or NULL for the default context - * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION - * LIBUSB_BT_USB_2_0_EXTENSION - * \param usb_2_0_extension output location for the USB 2.0 Extension - * descriptor. Only valid if 0 was returned. Must be freed with - * libusb_free_usb_2_0_extension_descriptor() after use. - * \returns 0 on success - * \returns a LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_usb_2_0_extension_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension) -{ - struct libusb_usb_2_0_extension_descriptor *_usb_2_0_extension; - const int host_endian = 0; - - if (dev_cap->bDevCapabilityType != LIBUSB_BT_USB_2_0_EXTENSION) { - usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", - dev_cap->bDevCapabilityType, - LIBUSB_BT_USB_2_0_EXTENSION); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (dev_cap->bLength < LIBUSB_BT_USB_2_0_EXTENSION_SIZE) { - usbi_err(ctx, "short dev-cap descriptor read %d/%d", - dev_cap->bLength, LIBUSB_BT_USB_2_0_EXTENSION_SIZE); - return LIBUSB_ERROR_IO; - } - - _usb_2_0_extension = malloc(sizeof(*_usb_2_0_extension)); - if (!_usb_2_0_extension) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor((unsigned char *)dev_cap, "bbbd", - _usb_2_0_extension, host_endian); - - *usb_2_0_extension = _usb_2_0_extension; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Free a USB 2.0 Extension descriptor obtained from - * libusb_get_usb_2_0_extension_descriptor(). - * It is safe to call this function with a NULL usb_2_0_extension parameter, - * in which case the function simply returns. - * - * \param usb_2_0_extension the USB 2.0 Extension descriptor to free - */ -void API_EXPORTED libusb_free_usb_2_0_extension_descriptor( - struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension) -{ - free(usb_2_0_extension); -} - -/** \ingroup libusb_desc - * Get a SuperSpeed USB Device Capability descriptor - * - * \param ctx the context to operate on, or NULL for the default context - * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - * \param ss_usb_device_cap output location for the SuperSpeed USB Device - * Capability descriptor. Only valid if 0 was returned. Must be freed with - * libusb_free_ss_usb_device_capability_descriptor() after use. - * \returns 0 on success - * \returns a LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_ss_usb_device_capability_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap) -{ - struct libusb_ss_usb_device_capability_descriptor *_ss_usb_device_cap; - const int host_endian = 0; - - if (dev_cap->bDevCapabilityType != LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) { - usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", - dev_cap->bDevCapabilityType, - LIBUSB_BT_SS_USB_DEVICE_CAPABILITY); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (dev_cap->bLength < LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) { - usbi_err(ctx, "short dev-cap descriptor read %d/%d", - dev_cap->bLength, LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE); - return LIBUSB_ERROR_IO; - } - - _ss_usb_device_cap = malloc(sizeof(*_ss_usb_device_cap)); - if (!_ss_usb_device_cap) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbwbbw", - _ss_usb_device_cap, host_endian); - - *ss_usb_device_cap = _ss_usb_device_cap; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Free a SuperSpeed USB Device Capability descriptor obtained from - * libusb_get_ss_usb_device_capability_descriptor(). - * It is safe to call this function with a NULL ss_usb_device_cap - * parameter, in which case the function simply returns. - * - * \param ss_usb_device_cap the USB 2.0 Extension descriptor to free - */ -void API_EXPORTED libusb_free_ss_usb_device_capability_descriptor( - struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap) -{ - free(ss_usb_device_cap); -} - -/** \ingroup libusb_desc - * Get a Container ID descriptor - * - * \param ctx the context to operate on, or NULL for the default context - * \param dev_cap Device Capability descriptor with a bDevCapabilityType of - * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID - * LIBUSB_BT_CONTAINER_ID - * \param container_id output location for the Container ID descriptor. - * Only valid if 0 was returned. Must be freed with - * libusb_free_container_id_descriptor() after use. - * \returns 0 on success - * \returns a LIBUSB_ERROR code on error - */ -int API_EXPORTED libusb_get_container_id_descriptor(struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_container_id_descriptor **container_id) -{ - struct libusb_container_id_descriptor *_container_id; - const int host_endian = 0; - - if (dev_cap->bDevCapabilityType != LIBUSB_BT_CONTAINER_ID) { - usbi_err(ctx, "unexpected bDevCapabilityType %x (expected %x)", - dev_cap->bDevCapabilityType, - LIBUSB_BT_CONTAINER_ID); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (dev_cap->bLength < LIBUSB_BT_CONTAINER_ID_SIZE) { - usbi_err(ctx, "short dev-cap descriptor read %d/%d", - dev_cap->bLength, LIBUSB_BT_CONTAINER_ID_SIZE); - return LIBUSB_ERROR_IO; - } - - _container_id = malloc(sizeof(*_container_id)); - if (!_container_id) - return LIBUSB_ERROR_NO_MEM; - - usbi_parse_descriptor((unsigned char *)dev_cap, "bbbbu", - _container_id, host_endian); - - *container_id = _container_id; - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_desc - * Free a Container ID descriptor obtained from - * libusb_get_container_id_descriptor(). - * It is safe to call this function with a NULL container_id parameter, - * in which case the function simply returns. - * - * \param container_id the USB 2.0 Extension descriptor to free - */ -void API_EXPORTED libusb_free_container_id_descriptor( - struct libusb_container_id_descriptor *container_id) -{ - free(container_id); -} - -/** \ingroup libusb_desc - * Retrieve a string descriptor in C style ASCII. - * - * Wrapper around libusb_get_string_descriptor(). Uses the first language - * supported by the device. - * - * \param dev_handle a device handle - * \param desc_index the index of the descriptor to retrieve - * \param data output buffer for ASCII string descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, - uint8_t desc_index, unsigned char *data, int length) -{ - unsigned char tbuf[255]; /* Some devices choke on size > 255 */ - int r, si, di; - uint16_t langid; - - /* Asking for the zero'th index is special - it returns a string - * descriptor that contains all the language IDs supported by the - * device. Typically there aren't many - often only one. Language - * IDs are 16 bit numbers, and they start at the third byte in the - * descriptor. There's also no point in trying to read descriptor 0 - * with this function. See USB 2.0 specification section 9.6.7 for - * more information. - */ - - if (desc_index == 0) - return LIBUSB_ERROR_INVALID_PARAM; - - r = libusb_get_string_descriptor(dev_handle, 0, 0, tbuf, sizeof(tbuf)); - if (r < 0) - return r; - - if (r < 4) - return LIBUSB_ERROR_IO; - - langid = tbuf[2] | (tbuf[3] << 8); - - r = libusb_get_string_descriptor(dev_handle, desc_index, langid, tbuf, - sizeof(tbuf)); - if (r < 0) - return r; - - if (tbuf[1] != LIBUSB_DT_STRING) - return LIBUSB_ERROR_IO; - - if (tbuf[0] > r) - return LIBUSB_ERROR_IO; - - for (di = 0, si = 2; si < tbuf[0]; si += 2) { - if (di >= (length - 1)) - break; - - if ((tbuf[si] & 0x80) || (tbuf[si + 1])) /* non-ASCII */ - data[di++] = '?'; - else - data[di++] = tbuf[si]; - } - - data[di] = 0; - return di; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/hotplug.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/hotplug.c deleted file mode 100644 index bbfd6e79a1a..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/hotplug.c +++ /dev/null @@ -1,350 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * Hotplug functions for libusb - * Copyright © 2012-2013 Nathan Hjelm - * Copyright © 2012-2013 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include - -#include "libusbi.h" -#include "hotplug.h" - -/** - * @defgroup libusb_hotplug Device hotplug event notification - * This page details how to use the libusb hotplug interface, where available. - * - * Be mindful that not all platforms currently implement hotplug notification and - * that you should first call on \ref libusb_has_capability() with parameter - * \ref LIBUSB_CAP_HAS_HOTPLUG to confirm that hotplug support is available. - * - * \page libusb_hotplug Device hotplug event notification - * - * \section hotplug_intro Introduction - * - * Version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102, has added support - * for hotplug events on some platforms (you should test if your platform - * supports hotplug notification by calling \ref libusb_has_capability() with - * parameter \ref LIBUSB_CAP_HAS_HOTPLUG). - * - * This interface allows you to request notification for the arrival and departure - * of matching USB devices. - * - * To receive hotplug notification you register a callback by calling - * \ref libusb_hotplug_register_callback(). This function will optionally return - * a callback handle that can be passed to \ref libusb_hotplug_deregister_callback(). - * - * A callback function must return an int (0 or 1) indicating whether the callback is - * expecting additional events. Returning 0 will rearm the callback and 1 will cause - * the callback to be deregistered. Note that when callbacks are called from - * libusb_hotplug_register_callback() because of the \ref LIBUSB_HOTPLUG_ENUMERATE - * flag, the callback return value is ignored, iow you cannot cause a callback - * to be deregistered by returning 1 when it is called from - * libusb_hotplug_register_callback(). - * - * Callbacks for a particular context are automatically deregistered by libusb_exit(). - * - * As of 1.0.16 there are two supported hotplug events: - * - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: A device has arrived and is ready to use - * - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: A device has left and is no longer available - * - * A hotplug event can listen for either or both of these events. - * - * Note: If you receive notification that a device has left and you have any - * a libusb_device_handles for the device it is up to you to call libusb_close() - * on each device handle to free up any remaining resources associated with the device. - * Once a device has left any libusb_device_handle associated with the device - * are invalid and will remain so even if the device comes back. - * - * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED event it is considered - * safe to call any libusb function that takes a libusb_device. It also safe to - * open a device and submit asynchronous transfers. However, most other functions - * that take a libusb_device_handle are not safe to call. Examples of such - * functions are any of the \ref libusb_syncio "synchronous API" functions or the blocking - * functions that retrieve various \ref libusb_desc "USB descriptors". These functions must - * be used outside of the context of the hotplug callback. - * - * When handling a LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT event the only safe function - * is libusb_get_device_descriptor(). - * - * The following code provides an example of the usage of the hotplug interface: -\code -#include -#include -#include -#include - -static int count = 0; - -int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event, void *user_data) { - static libusb_device_handle *dev_handle = NULL; - struct libusb_device_descriptor desc; - int rc; - - (void)libusb_get_device_descriptor(dev, &desc); - - if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { - rc = libusb_open(dev, &dev_handle); - if (LIBUSB_SUCCESS != rc) { - printf("Could not open USB device\n"); - } - } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { - if (dev_handle) { - libusb_close(dev_handle); - dev_handle = NULL; - } - } else { - printf("Unhandled event %d\n", event); - } - count++; - - return 0; -} - -int main (void) { - libusb_hotplug_callback_handle callback_handle; - int rc; - - libusb_init(NULL); - - rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, 0x045a, 0x5005, - LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, - &callback_handle); - if (LIBUSB_SUCCESS != rc) { - printf("Error creating a hotplug callback\n"); - libusb_exit(NULL); - return EXIT_FAILURE; - } - - while (count < 2) { - libusb_handle_events_completed(NULL, NULL); - nanosleep(&(struct timespec){0, 10000000UL}, NULL); - } - - libusb_hotplug_deregister_callback(NULL, callback_handle); - libusb_exit(NULL); - - return 0; -} -\endcode - */ - -static int usbi_hotplug_match_cb (struct libusb_context *ctx, - struct libusb_device *dev, libusb_hotplug_event event, - struct libusb_hotplug_callback *hotplug_cb) -{ - /* Handle lazy deregistration of callback */ - if (hotplug_cb->needs_free) { - /* Free callback */ - return 1; - } - - if (!(hotplug_cb->events & event)) { - return 0; - } - - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->vendor_id && - hotplug_cb->vendor_id != dev->device_descriptor.idVendor) { - return 0; - } - - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->product_id && - hotplug_cb->product_id != dev->device_descriptor.idProduct) { - return 0; - } - - if (LIBUSB_HOTPLUG_MATCH_ANY != hotplug_cb->dev_class && - hotplug_cb->dev_class != dev->device_descriptor.bDeviceClass) { - return 0; - } - - return hotplug_cb->cb (ctx, dev, event, hotplug_cb->user_data); -} - -void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event) -{ - struct libusb_hotplug_callback *hotplug_cb, *next; - int ret; - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - - list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) { - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - ret = usbi_hotplug_match_cb (ctx, dev, event, hotplug_cb); - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - - if (ret) { - list_del(&hotplug_cb->list); - free(hotplug_cb); - } - } - - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - /* the backend is expected to call the callback for each active transfer */ -} - -void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event) -{ - int pending_events; - libusb_hotplug_message *message = calloc(1, sizeof(*message)); - - if (!message) { - usbi_err(ctx, "error allocating hotplug message"); - return; - } - - message->event = event; - message->device = dev; - - /* Take the event data lock and add this message to the list. - * Only signal an event if there are no prior pending events. */ - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - list_add_tail(&message->list, &ctx->hotplug_msgs); - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); -} - -int API_EXPORTED libusb_hotplug_register_callback(libusb_context *ctx, - libusb_hotplug_event events, libusb_hotplug_flag flags, - int vendor_id, int product_id, int dev_class, - libusb_hotplug_callback_fn cb_fn, void *user_data, - libusb_hotplug_callback_handle *callback_handle) -{ - libusb_hotplug_callback *new_callback; - static int handle_id = 1; - - /* check for hotplug support */ - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - /* check for sane values */ - if ((LIBUSB_HOTPLUG_MATCH_ANY != vendor_id && (~0xffff & vendor_id)) || - (LIBUSB_HOTPLUG_MATCH_ANY != product_id && (~0xffff & product_id)) || - (LIBUSB_HOTPLUG_MATCH_ANY != dev_class && (~0xff & dev_class)) || - !cb_fn) { - return LIBUSB_ERROR_INVALID_PARAM; - } - - USBI_GET_CONTEXT(ctx); - - new_callback = (libusb_hotplug_callback *)calloc(1, sizeof (*new_callback)); - if (!new_callback) { - return LIBUSB_ERROR_NO_MEM; - } - - new_callback->ctx = ctx; - new_callback->vendor_id = vendor_id; - new_callback->product_id = product_id; - new_callback->dev_class = dev_class; - new_callback->flags = flags; - new_callback->events = events; - new_callback->cb = cb_fn; - new_callback->user_data = user_data; - new_callback->needs_free = 0; - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - - /* protect the handle by the context hotplug lock. it doesn't matter if the same handle - * is used for different contexts only that the handle is unique for this context */ - new_callback->handle = handle_id++; - - list_add(&new_callback->list, &ctx->hotplug_cbs); - - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - - if (flags & LIBUSB_HOTPLUG_ENUMERATE) { - int i, len; - struct libusb_device **devs; - - len = (int) libusb_get_device_list(ctx, &devs); - if (len < 0) { - libusb_hotplug_deregister_callback(ctx, - new_callback->handle); - return len; - } - - for (i = 0; i < len; i++) { - usbi_hotplug_match_cb(ctx, devs[i], - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, - new_callback); - } - - libusb_free_device_list(devs, 1); - } - - - if (callback_handle) - *callback_handle = new_callback->handle; - - return LIBUSB_SUCCESS; -} - -void API_EXPORTED libusb_hotplug_deregister_callback (struct libusb_context *ctx, - libusb_hotplug_callback_handle callback_handle) -{ - struct libusb_hotplug_callback *hotplug_cb; - - /* check for hotplug support */ - if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { - return; - } - - USBI_GET_CONTEXT(ctx); - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, - struct libusb_hotplug_callback) { - if (callback_handle == hotplug_cb->handle) { - /* Mark this callback for deregistration */ - hotplug_cb->needs_free = 1; - } - } - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); - - usbi_hotplug_notification(ctx, NULL, 0); -} - -void usbi_hotplug_deregister_all(struct libusb_context *ctx) { - struct libusb_hotplug_callback *hotplug_cb, *next; - - usbi_mutex_lock(&ctx->hotplug_cbs_lock); - list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, - struct libusb_hotplug_callback) { - list_del(&hotplug_cb->list); - free(hotplug_cb); - } - - usbi_mutex_unlock(&ctx->hotplug_cbs_lock); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/hotplug.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/hotplug.h deleted file mode 100644 index 2bec81b06c4..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/hotplug.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * Hotplug support for libusb - * Copyright © 2012-2013 Nathan Hjelm - * Copyright © 2012-2013 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined(USBI_HOTPLUG_H) -#define USBI_HOTPLUG_H - -#ifndef LIBUSBI_H -#include "libusbi.h" -#endif - -/** \ingroup hotplug - * The hotplug callback structure. The user populates this structure with - * libusb_hotplug_prepare_callback() and then calls libusb_hotplug_register_callback() - * to receive notification of hotplug events. - */ -struct libusb_hotplug_callback { - /** Context this callback is associated with */ - struct libusb_context *ctx; - - /** Vendor ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int vendor_id; - - /** Product ID to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int product_id; - - /** Device class to match or LIBUSB_HOTPLUG_MATCH_ANY */ - int dev_class; - - /** Hotplug callback flags */ - libusb_hotplug_flag flags; - - /** Event(s) that will trigger this callback */ - libusb_hotplug_event events; - - /** Callback function to invoke for matching event/device */ - libusb_hotplug_callback_fn cb; - - /** Handle for this callback (used to match on deregister) */ - libusb_hotplug_callback_handle handle; - - /** User data that will be passed to the callback function */ - void *user_data; - - /** Callback is marked for deletion */ - int needs_free; - - /** List this callback is registered in (ctx->hotplug_cbs) */ - struct list_head list; -}; - -typedef struct libusb_hotplug_callback libusb_hotplug_callback; - -struct libusb_hotplug_message { - /** The hotplug event that occurred */ - libusb_hotplug_event event; - - /** The device for which this hotplug event occurred */ - struct libusb_device *device; - - /** List this message is contained in (ctx->hotplug_msgs) */ - struct list_head list; -}; - -typedef struct libusb_hotplug_message libusb_hotplug_message; - -void usbi_hotplug_deregister_all(struct libusb_context *ctx); -void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event); -void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, - libusb_hotplug_event event); - -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/io.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/io.c deleted file mode 100644 index eb1eabf1cb7..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/io.c +++ /dev/null @@ -1,2819 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:t ; c-basic-offset:8 -*- */ -/* - * I/O functions for libusb - * Copyright © 2007-2009 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef USBI_TIMERFD_AVAILABLE -#include -#endif - -#include "libusbi.h" -#include "hotplug.h" - -/** - * \page libusb_io Synchronous and asynchronous device I/O - * - * \section io_intro Introduction - * - * If you're using libusb in your application, you're probably wanting to - * perform I/O with devices - you want to perform USB data transfers. - * - * libusb offers two separate interfaces for device I/O. This page aims to - * introduce the two in order to help you decide which one is more suitable - * for your application. You can also choose to use both interfaces in your - * application by considering each transfer on a case-by-case basis. - * - * Once you have read through the following discussion, you should consult the - * detailed API documentation pages for the details: - * - \ref libusb_syncio - * - \ref libusb_asyncio - * - * \section theory Transfers at a logical level - * - * At a logical level, USB transfers typically happen in two parts. For - * example, when reading data from a endpoint: - * -# A request for data is sent to the device - * -# Some time later, the incoming data is received by the host - * - * or when writing data to an endpoint: - * - * -# The data is sent to the device - * -# Some time later, the host receives acknowledgement from the device that - * the data has been transferred. - * - * There may be an indefinite delay between the two steps. Consider a - * fictional USB input device with a button that the user can press. In order - * to determine when the button is pressed, you would likely submit a request - * to read data on a bulk or interrupt endpoint and wait for data to arrive. - * Data will arrive when the button is pressed by the user, which is - * potentially hours later. - * - * libusb offers both a synchronous and an asynchronous interface to performing - * USB transfers. The main difference is that the synchronous interface - * combines both steps indicated above into a single function call, whereas - * the asynchronous interface separates them. - * - * \section sync The synchronous interface - * - * The synchronous I/O interface allows you to perform a USB transfer with - * a single function call. When the function call returns, the transfer has - * completed and you can parse the results. - * - * If you have used the libusb-0.1 before, this I/O style will seem familar to - * you. libusb-0.1 only offered a synchronous interface. - * - * In our input device example, to read button presses you might write code - * in the following style: -\code -unsigned char data[4]; -int actual_length; -int r = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN, data, sizeof(data), &actual_length, 0); -if (r == 0 && actual_length == sizeof(data)) { - // results of the transaction can now be found in the data buffer - // parse them here and report button press -} else { - error(); -} -\endcode - * - * The main advantage of this model is simplicity: you did everything with - * a single simple function call. - * - * However, this interface has its limitations. Your application will sleep - * inside libusb_bulk_transfer() until the transaction has completed. If it - * takes the user 3 hours to press the button, your application will be - * sleeping for that long. Execution will be tied up inside the library - - * the entire thread will be useless for that duration. - * - * Another issue is that by tieing up the thread with that single transaction - * there is no possibility of performing I/O with multiple endpoints and/or - * multiple devices simultaneously, unless you resort to creating one thread - * per transaction. - * - * Additionally, there is no opportunity to cancel the transfer after the - * request has been submitted. - * - * For details on how to use the synchronous API, see the - * \ref libusb_syncio "synchronous I/O API documentation" pages. - * - * \section async The asynchronous interface - * - * Asynchronous I/O is the most significant new feature in libusb-1.0. - * Although it is a more complex interface, it solves all the issues detailed - * above. - * - * Instead of providing which functions that block until the I/O has complete, - * libusb's asynchronous interface presents non-blocking functions which - * begin a transfer and then return immediately. Your application passes a - * callback function pointer to this non-blocking function, which libusb will - * call with the results of the transaction when it has completed. - * - * Transfers which have been submitted through the non-blocking functions - * can be cancelled with a separate function call. - * - * The non-blocking nature of this interface allows you to be simultaneously - * performing I/O to multiple endpoints on multiple devices, without having - * to use threads. - * - * This added flexibility does come with some complications though: - * - In the interest of being a lightweight library, libusb does not create - * threads and can only operate when your application is calling into it. Your - * application must call into libusb from it's main loop when events are ready - * to be handled, or you must use some other scheme to allow libusb to - * undertake whatever work needs to be done. - * - libusb also needs to be called into at certain fixed points in time in - * order to accurately handle transfer timeouts. - * - Memory handling becomes more complex. You cannot use stack memory unless - * the function with that stack is guaranteed not to return until the transfer - * callback has finished executing. - * - You generally lose some linearity from your code flow because submitting - * the transfer request is done in a separate function from where the transfer - * results are handled. This becomes particularly obvious when you want to - * submit a second transfer based on the results of an earlier transfer. - * - * Internally, libusb's synchronous interface is expressed in terms of function - * calls to the asynchronous interface. - * - * For details on how to use the asynchronous API, see the - * \ref libusb_asyncio "asynchronous I/O API" documentation pages. - */ - - -/** - * \page libusb_packetoverflow Packets and overflows - * - * \section packets Packet abstraction - * - * The USB specifications describe how data is transmitted in packets, with - * constraints on packet size defined by endpoint descriptors. The host must - * not send data payloads larger than the endpoint's maximum packet size. - * - * libusb and the underlying OS abstract out the packet concept, allowing you - * to request transfers of any size. Internally, the request will be divided - * up into correctly-sized packets. You do not have to be concerned with - * packet sizes, but there is one exception when considering overflows. - * - * \section overflow Bulk/interrupt transfer overflows - * - * When requesting data on a bulk endpoint, libusb requires you to supply a - * buffer and the maximum number of bytes of data that libusb can put in that - * buffer. However, the size of the buffer is not communicated to the device - - * the device is just asked to send any amount of data. - * - * There is no problem if the device sends an amount of data that is less than - * or equal to the buffer size. libusb reports this condition to you through - * the \ref libusb_transfer::actual_length "libusb_transfer.actual_length" - * field. - * - * Problems may occur if the device attempts to send more data than can fit in - * the buffer. libusb reports LIBUSB_TRANSFER_OVERFLOW for this condition but - * other behaviour is largely undefined: actual_length may or may not be - * accurate, the chunk of data that can fit in the buffer (before overflow) - * may or may not have been transferred. - * - * Overflows are nasty, but can be avoided. Even though you were told to - * ignore packets above, think about the lower level details: each transfer is - * split into packets (typically small, with a maximum size of 512 bytes). - * Overflows can only happen if the final packet in an incoming data transfer - * is smaller than the actual packet that the device wants to transfer. - * Therefore, you will never see an overflow if your transfer buffer size is a - * multiple of the endpoint's packet size: the final packet will either - * fill up completely or will be only partially filled. - */ - -/** - * @defgroup libusb_asyncio Asynchronous device I/O - * - * This page details libusb's asynchronous (non-blocking) API for USB device - * I/O. This interface is very powerful but is also quite complex - you will - * need to read this page carefully to understand the necessary considerations - * and issues surrounding use of this interface. Simplistic applications - * may wish to consider the \ref libusb_syncio "synchronous I/O API" instead. - * - * The asynchronous interface is built around the idea of separating transfer - * submission and handling of transfer completion (the synchronous model - * combines both of these into one). There may be a long delay between - * submission and completion, however the asynchronous submission function - * is non-blocking so will return control to your application during that - * potentially long delay. - * - * \section asyncabstraction Transfer abstraction - * - * For the asynchronous I/O, libusb implements the concept of a generic - * transfer entity for all types of I/O (control, bulk, interrupt, - * isochronous). The generic transfer object must be treated slightly - * differently depending on which type of I/O you are performing with it. - * - * This is represented by the public libusb_transfer structure type. - * - * \section asynctrf Asynchronous transfers - * - * We can view asynchronous I/O as a 5 step process: - * -# Allocation: allocate a libusb_transfer - * -# Filling: populate the libusb_transfer instance with information - * about the transfer you wish to perform - * -# Submission: ask libusb to submit the transfer - * -# Completion handling: examine transfer results in the - * libusb_transfer structure - * -# Deallocation: clean up resources - * - * - * \subsection asyncalloc Allocation - * - * This step involves allocating memory for a USB transfer. This is the - * generic transfer object mentioned above. At this stage, the transfer - * is "blank" with no details about what type of I/O it will be used for. - * - * Allocation is done with the libusb_alloc_transfer() function. You must use - * this function rather than allocating your own transfers. - * - * \subsection asyncfill Filling - * - * This step is where you take a previously allocated transfer and fill it - * with information to determine the message type and direction, data buffer, - * callback function, etc. - * - * You can either fill the required fields yourself or you can use the - * helper functions: libusb_fill_control_transfer(), libusb_fill_bulk_transfer() - * and libusb_fill_interrupt_transfer(). - * - * \subsection asyncsubmit Submission - * - * When you have allocated a transfer and filled it, you can submit it using - * libusb_submit_transfer(). This function returns immediately but can be - * regarded as firing off the I/O request in the background. - * - * \subsection asynccomplete Completion handling - * - * After a transfer has been submitted, one of four things can happen to it: - * - * - The transfer completes (i.e. some data was transferred) - * - The transfer has a timeout and the timeout expires before all data is - * transferred - * - The transfer fails due to an error - * - The transfer is cancelled - * - * Each of these will cause the user-specified transfer callback function to - * be invoked. It is up to the callback function to determine which of the - * above actually happened and to act accordingly. - * - * The user-specified callback is passed a pointer to the libusb_transfer - * structure which was used to setup and submit the transfer. At completion - * time, libusb has populated this structure with results of the transfer: - * success or failure reason, number of bytes of data transferred, etc. See - * the libusb_transfer structure documentation for more information. - * - * Important Note: The user-specified callback is called from an event - * handling context. It is therefore important that no calls are made into - * libusb that will attempt to perform any event handling. Examples of such - * functions are any listed in the \ref libusb_syncio "synchronous API" and any of - * the blocking functions that retrieve \ref libusb_desc "USB descriptors". - * - * \subsection Deallocation - * - * When a transfer has completed (i.e. the callback function has been invoked), - * you are advised to free the transfer (unless you wish to resubmit it, see - * below). Transfers are deallocated with libusb_free_transfer(). - * - * It is undefined behaviour to free a transfer which has not completed. - * - * \section asyncresubmit Resubmission - * - * You may be wondering why allocation, filling, and submission are all - * separated above where they could reasonably be combined into a single - * operation. - * - * The reason for separation is to allow you to resubmit transfers without - * having to allocate new ones every time. This is especially useful for - * common situations dealing with interrupt endpoints - you allocate one - * transfer, fill and submit it, and when it returns with results you just - * resubmit it for the next interrupt. - * - * \section asynccancel Cancellation - * - * Another advantage of using the asynchronous interface is that you have - * the ability to cancel transfers which have not yet completed. This is - * done by calling the libusb_cancel_transfer() function. - * - * libusb_cancel_transfer() is asynchronous/non-blocking in itself. When the - * cancellation actually completes, the transfer's callback function will - * be invoked, and the callback function should check the transfer status to - * determine that it was cancelled. - * - * Freeing the transfer after it has been cancelled but before cancellation - * has completed will result in undefined behaviour. - * - * When a transfer is cancelled, some of the data may have been transferred. - * libusb will communicate this to you in the transfer callback. Do not assume - * that no data was transferred. - * - * \section bulk_overflows Overflows on device-to-host bulk/interrupt endpoints - * - * If your device does not have predictable transfer sizes (or it misbehaves), - * your application may submit a request for data on an IN endpoint which is - * smaller than the data that the device wishes to send. In some circumstances - * this will cause an overflow, which is a nasty condition to deal with. See - * the \ref libusb_packetoverflow page for discussion. - * - * \section asyncctrl Considerations for control transfers - * - * The libusb_transfer structure is generic and hence does not - * include specific fields for the control-specific setup packet structure. - * - * In order to perform a control transfer, you must place the 8-byte setup - * packet at the start of the data buffer. To simplify this, you could - * cast the buffer pointer to type struct libusb_control_setup, or you can - * use the helper function libusb_fill_control_setup(). - * - * The wLength field placed in the setup packet must be the length you would - * expect to be sent in the setup packet: the length of the payload that - * follows (or the expected maximum number of bytes to receive). However, - * the length field of the libusb_transfer object must be the length of - * the data buffer - i.e. it should be wLength plus the size of - * the setup packet (LIBUSB_CONTROL_SETUP_SIZE). - * - * If you use the helper functions, this is simplified for you: - * -# Allocate a buffer of size LIBUSB_CONTROL_SETUP_SIZE plus the size of the - * data you are sending/requesting. - * -# Call libusb_fill_control_setup() on the data buffer, using the transfer - * request size as the wLength value (i.e. do not include the extra space you - * allocated for the control setup). - * -# If this is a host-to-device transfer, place the data to be transferred - * in the data buffer, starting at offset LIBUSB_CONTROL_SETUP_SIZE. - * -# Call libusb_fill_control_transfer() to associate the data buffer with - * the transfer (and to set the remaining details such as callback and timeout). - * - Note that there is no parameter to set the length field of the transfer. - * The length is automatically inferred from the wLength field of the setup - * packet. - * -# Submit the transfer. - * - * The multi-byte control setup fields (wValue, wIndex and wLength) must - * be given in little-endian byte order (the endianness of the USB bus). - * Endianness conversion is transparently handled by - * libusb_fill_control_setup() which is documented to accept host-endian - * values. - * - * Further considerations are needed when handling transfer completion in - * your callback function: - * - As you might expect, the setup packet will still be sitting at the start - * of the data buffer. - * - If this was a device-to-host transfer, the received data will be sitting - * at offset LIBUSB_CONTROL_SETUP_SIZE into the buffer. - * - The actual_length field of the transfer structure is relative to the - * wLength of the setup packet, rather than the size of the data buffer. So, - * if your wLength was 4, your transfer's length was 12, then you - * should expect an actual_length of 4 to indicate that the data was - * transferred in entirity. - * - * To simplify parsing of setup packets and obtaining the data from the - * correct offset, you may wish to use the libusb_control_transfer_get_data() - * and libusb_control_transfer_get_setup() functions within your transfer - * callback. - * - * Even though control endpoints do not halt, a completed control transfer - * may have a LIBUSB_TRANSFER_STALL status code. This indicates the control - * request was not supported. - * - * \section asyncintr Considerations for interrupt transfers - * - * All interrupt transfers are performed using the polling interval presented - * by the bInterval value of the endpoint descriptor. - * - * \section asynciso Considerations for isochronous transfers - * - * Isochronous transfers are more complicated than transfers to - * non-isochronous endpoints. - * - * To perform I/O to an isochronous endpoint, allocate the transfer by calling - * libusb_alloc_transfer() with an appropriate number of isochronous packets. - * - * During filling, set \ref libusb_transfer::type "type" to - * \ref libusb_transfer_type::LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - * "LIBUSB_TRANSFER_TYPE_ISOCHRONOUS", and set - * \ref libusb_transfer::num_iso_packets "num_iso_packets" to a value less than - * or equal to the number of packets you requested during allocation. - * libusb_alloc_transfer() does not set either of these fields for you, given - * that you might not even use the transfer on an isochronous endpoint. - * - * Next, populate the length field for the first num_iso_packets entries in - * the \ref libusb_transfer::iso_packet_desc "iso_packet_desc" array. Section - * 5.6.3 of the USB2 specifications describe how the maximum isochronous - * packet length is determined by the wMaxPacketSize field in the endpoint - * descriptor. - * Two functions can help you here: - * - * - libusb_get_max_iso_packet_size() is an easy way to determine the max - * packet size for an isochronous endpoint. Note that the maximum packet - * size is actually the maximum number of bytes that can be transmitted in - * a single microframe, therefore this function multiplies the maximum number - * of bytes per transaction by the number of transaction opportunities per - * microframe. - * - libusb_set_iso_packet_lengths() assigns the same length to all packets - * within a transfer, which is usually what you want. - * - * For outgoing transfers, you'll obviously fill the buffer and populate the - * packet descriptors in hope that all the data gets transferred. For incoming - * transfers, you must ensure the buffer has sufficient capacity for - * the situation where all packets transfer the full amount of requested data. - * - * Completion handling requires some extra consideration. The - * \ref libusb_transfer::actual_length "actual_length" field of the transfer - * is meaningless and should not be examined; instead you must refer to the - * \ref libusb_iso_packet_descriptor::actual_length "actual_length" field of - * each individual packet. - * - * The \ref libusb_transfer::status "status" field of the transfer is also a - * little misleading: - * - If the packets were submitted and the isochronous data microframes - * completed normally, status will have value - * \ref libusb_transfer_status::LIBUSB_TRANSFER_COMPLETED - * "LIBUSB_TRANSFER_COMPLETED". Note that bus errors and software-incurred - * delays are not counted as transfer errors; the transfer.status field may - * indicate COMPLETED even if some or all of the packets failed. Refer to - * the \ref libusb_iso_packet_descriptor::status "status" field of each - * individual packet to determine packet failures. - * - The status field will have value - * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR - * "LIBUSB_TRANSFER_ERROR" only when serious errors were encountered. - * - Other transfer status codes occur with normal behaviour. - * - * The data for each packet will be found at an offset into the buffer that - * can be calculated as if each prior packet completed in full. The - * libusb_get_iso_packet_buffer() and libusb_get_iso_packet_buffer_simple() - * functions may help you here. - * - * Note: Some operating systems (e.g. Linux) may impose limits on the - * length of individual isochronous packets and/or the total length of the - * isochronous transfer. Such limits can be difficult for libusb to detect, - * so the library will simply try and submit the transfer as set up by you. - * If the transfer fails to submit because it is too large, - * libusb_submit_transfer() will return - * \ref libusb_error::LIBUSB_ERROR_INVALID_PARAM "LIBUSB_ERROR_INVALID_PARAM". - * - * \section asyncmem Memory caveats - * - * In most circumstances, it is not safe to use stack memory for transfer - * buffers. This is because the function that fired off the asynchronous - * transfer may return before libusb has finished using the buffer, and when - * the function returns it's stack gets destroyed. This is true for both - * host-to-device and device-to-host transfers. - * - * The only case in which it is safe to use stack memory is where you can - * guarantee that the function owning the stack space for the buffer does not - * return until after the transfer's callback function has completed. In every - * other case, you need to use heap memory instead. - * - * \section asyncflags Fine control - * - * Through using this asynchronous interface, you may find yourself repeating - * a few simple operations many times. You can apply a bitwise OR of certain - * flags to a transfer to simplify certain things: - * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_SHORT_NOT_OK - * "LIBUSB_TRANSFER_SHORT_NOT_OK" results in transfers which transferred - * less than the requested amount of data being marked with status - * \ref libusb_transfer_status::LIBUSB_TRANSFER_ERROR "LIBUSB_TRANSFER_ERROR" - * (they would normally be regarded as COMPLETED) - * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER - * "LIBUSB_TRANSFER_FREE_BUFFER" allows you to ask libusb to free the transfer - * buffer when freeing the transfer. - * - \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_TRANSFER - * "LIBUSB_TRANSFER_FREE_TRANSFER" causes libusb to automatically free the - * transfer after the transfer callback returns. - * - * \section asyncevent Event handling - * - * An asynchronous model requires that libusb perform work at various - * points in time - namely processing the results of previously-submitted - * transfers and invoking the user-supplied callback function. - * - * This gives rise to the libusb_handle_events() function which your - * application must call into when libusb has work do to. This gives libusb - * the opportunity to reap pending transfers, invoke callbacks, etc. - * - * There are 2 different approaches to dealing with libusb_handle_events: - * - * -# Repeatedly call libusb_handle_events() in blocking mode from a dedicated - * thread. - * -# Integrate libusb with your application's main event loop. libusb - * exposes a set of file descriptors which allow you to do this. - * - * The first approach has the big advantage that it will also work on Windows - * were libusb' poll API for select / poll integration is not available. So - * if you want to support Windows and use the async API, you must use this - * approach, see the \ref eventthread "Using an event handling thread" section - * below for details. - * - * If you prefer a single threaded approach with a single central event loop, - * see the \ref libusb_poll "polling and timing" section for how to integrate libusb - * into your application's main event loop. - * - * \section eventthread Using an event handling thread - * - * Lets begin with stating the obvious: If you're going to use a separate - * thread for libusb event handling, your callback functions MUST be - * threadsafe. - * - * Other then that doing event handling from a separate thread, is mostly - * simple. You can use an event thread function as follows: -\code -void *event_thread_func(void *ctx) -{ - while (event_thread_run) - libusb_handle_events(ctx); - - return NULL; -} -\endcode - * - * There is one caveat though, stopping this thread requires setting the - * event_thread_run variable to 0, and after that libusb_handle_events() needs - * to return control to event_thread_func. But unless some event happens, - * libusb_handle_events() will not return. - * - * There are 2 different ways of dealing with this, depending on if your - * application uses libusb' \ref libusb_hotplug "hotplug" support or not. - * - * Applications which do not use hotplug support, should not start the event - * thread until after their first call to libusb_open(), and should stop the - * thread when closing the last open device as follows: -\code -void my_close_handle(libusb_device_handle *dev_handle) -{ - if (open_devs == 1) - event_thread_run = 0; - - libusb_close(dev_handle); // This wakes up libusb_handle_events() - - if (open_devs == 1) - pthread_join(event_thread); - - open_devs--; -} -\endcode - * - * Applications using hotplug support should start the thread at program init, - * after having successfully called libusb_hotplug_register_callback(), and - * should stop the thread at program exit as follows: -\code -void my_libusb_exit(void) -{ - event_thread_run = 0; - libusb_hotplug_deregister_callback(ctx, hotplug_cb_handle); // This wakes up libusb_handle_events() - pthread_join(event_thread); - libusb_exit(ctx); -} -\endcode - */ - -/** - * @defgroup libusb_poll Polling and timing - * - * This page documents libusb's functions for polling events and timing. - * These functions are only necessary for users of the - * \ref libusb_asyncio "asynchronous API". If you are only using the simpler - * \ref libusb_syncio "synchronous API" then you do not need to ever call these - * functions. - * - * The justification for the functionality described here has already been - * discussed in the \ref asyncevent "event handling" section of the - * asynchronous API documentation. In summary, libusb does not create internal - * threads for event processing and hence relies on your application calling - * into libusb at certain points in time so that pending events can be handled. - * - * Your main loop is probably already calling poll() or select() or a - * variant on a set of file descriptors for other event sources (e.g. keyboard - * button presses, mouse movements, network sockets, etc). You then add - * libusb's file descriptors to your poll()/select() calls, and when activity - * is detected on such descriptors you know it is time to call - * libusb_handle_events(). - * - * There is one final event handling complication. libusb supports - * asynchronous transfers which time out after a specified time period. - * - * On some platforms a timerfd is used, so the timeout handling is just another - * fd, on other platforms this requires that libusb is called into at or after - * the timeout to handle it. So, in addition to considering libusb's file - * descriptors in your main event loop, you must also consider that libusb - * sometimes needs to be called into at fixed points in time even when there - * is no file descriptor activity, see \ref polltime details. - * - * In order to know precisely when libusb needs to be called into, libusb - * offers you a set of pollable file descriptors and information about when - * the next timeout expires. - * - * If you are using the asynchronous I/O API, you must take one of the two - * following options, otherwise your I/O will not complete. - * - * \section pollsimple The simple option - * - * If your application revolves solely around libusb and does not need to - * handle other event sources, you can have a program structure as follows: -\code -// initialize libusb -// find and open device -// maybe fire off some initial async I/O - -while (user_has_not_requested_exit) - libusb_handle_events(ctx); - -// clean up and exit -\endcode - * - * With such a simple main loop, you do not have to worry about managing - * sets of file descriptors or handling timeouts. libusb_handle_events() will - * handle those details internally. - * - * \section libusb_pollmain The more advanced option - * - * \note This functionality is currently only available on Unix-like platforms. - * On Windows, libusb_get_pollfds() simply returns NULL. Applications which - * want to support Windows are advised to use an \ref eventthread - * "event handling thread" instead. - * - * In more advanced applications, you will already have a main loop which - * is monitoring other event sources: network sockets, X11 events, mouse - * movements, etc. Through exposing a set of file descriptors, libusb is - * designed to cleanly integrate into such main loops. - * - * In addition to polling file descriptors for the other event sources, you - * take a set of file descriptors from libusb and monitor those too. When you - * detect activity on libusb's file descriptors, you call - * libusb_handle_events_timeout() in non-blocking mode. - * - * What's more, libusb may also need to handle events at specific moments in - * time. No file descriptor activity is generated at these times, so your - * own application needs to be continually aware of when the next one of these - * moments occurs (through calling libusb_get_next_timeout()), and then it - * needs to call libusb_handle_events_timeout() in non-blocking mode when - * these moments occur. This means that you need to adjust your - * poll()/select() timeout accordingly. - * - * libusb provides you with a set of file descriptors to poll and expects you - * to poll all of them, treating them as a single entity. The meaning of each - * file descriptor in the set is an internal implementation detail, - * platform-dependent and may vary from release to release. Don't try and - * interpret the meaning of the file descriptors, just do as libusb indicates, - * polling all of them at once. - * - * In pseudo-code, you want something that looks like: -\code -// initialise libusb - -libusb_get_pollfds(ctx) -while (user has not requested application exit) { - libusb_get_next_timeout(ctx); - poll(on libusb file descriptors plus any other event sources of interest, - using a timeout no larger than the value libusb just suggested) - if (poll() indicated activity on libusb file descriptors) - libusb_handle_events_timeout(ctx, &zero_tv); - if (time has elapsed to or beyond the libusb timeout) - libusb_handle_events_timeout(ctx, &zero_tv); - // handle events from other sources here -} - -// clean up and exit -\endcode - * - * \subsection polltime Notes on time-based events - * - * The above complication with having to track time and call into libusb at - * specific moments is a bit of a headache. For maximum compatibility, you do - * need to write your main loop as above, but you may decide that you can - * restrict the supported platforms of your application and get away with - * a more simplistic scheme. - * - * These time-based event complications are \b not required on the following - * platforms: - * - Darwin - * - Linux, provided that the following version requirements are satisfied: - * - Linux v2.6.27 or newer, compiled with timerfd support - * - glibc v2.9 or newer - * - libusb v1.0.5 or newer - * - * Under these configurations, libusb_get_next_timeout() will \em always return - * 0, so your main loop can be simplified to: -\code -// initialise libusb - -libusb_get_pollfds(ctx) -while (user has not requested application exit) { - poll(on libusb file descriptors plus any other event sources of interest, - using any timeout that you like) - if (poll() indicated activity on libusb file descriptors) - libusb_handle_events_timeout(ctx, &zero_tv); - // handle events from other sources here -} - -// clean up and exit -\endcode - * - * Do remember that if you simplify your main loop to the above, you will - * lose compatibility with some platforms (including legacy Linux platforms, - * and any future platforms supported by libusb which may have time-based - * event requirements). The resultant problems will likely appear as - * strange bugs in your application. - * - * You can use the libusb_pollfds_handle_timeouts() function to do a runtime - * check to see if it is safe to ignore the time-based event complications. - * If your application has taken the shortcut of ignoring libusb's next timeout - * in your main loop, then you are advised to check the return value of - * libusb_pollfds_handle_timeouts() during application startup, and to abort - * if the platform does suffer from these timing complications. - * - * \subsection fdsetchange Changes in the file descriptor set - * - * The set of file descriptors that libusb uses as event sources may change - * during the life of your application. Rather than having to repeatedly - * call libusb_get_pollfds(), you can set up notification functions for when - * the file descriptor set changes using libusb_set_pollfd_notifiers(). - * - * \subsection mtissues Multi-threaded considerations - * - * Unfortunately, the situation is complicated further when multiple threads - * come into play. If two threads are monitoring the same file descriptors, - * the fact that only one thread will be woken up when an event occurs causes - * some headaches. - * - * The events lock, event waiters lock, and libusb_handle_events_locked() - * entities are added to solve these problems. You do not need to be concerned - * with these entities otherwise. - * - * See the extra documentation: \ref libusb_mtasync - */ - -/** \page libusb_mtasync Multi-threaded applications and asynchronous I/O - * - * libusb is a thread-safe library, but extra considerations must be applied - * to applications which interact with libusb from multiple threads. - * - * The underlying issue that must be addressed is that all libusb I/O - * revolves around monitoring file descriptors through the poll()/select() - * system calls. This is directly exposed at the - * \ref libusb_asyncio "asynchronous interface" but it is important to note that the - * \ref libusb_syncio "synchronous interface" is implemented on top of the - * asynchonrous interface, therefore the same considerations apply. - * - * The issue is that if two or more threads are concurrently calling poll() - * or select() on libusb's file descriptors then only one of those threads - * will be woken up when an event arrives. The others will be completely - * oblivious that anything has happened. - * - * Consider the following pseudo-code, which submits an asynchronous transfer - * then waits for its completion. This style is one way you could implement a - * synchronous interface on top of the asynchronous interface (and libusb - * does something similar, albeit more advanced due to the complications - * explained on this page). - * -\code -void cb(struct libusb_transfer *transfer) -{ - int *completed = transfer->user_data; - *completed = 1; -} - -void myfunc() { - struct libusb_transfer *transfer; - unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned (2))); - int completed = 0; - - transfer = libusb_alloc_transfer(0); - libusb_fill_control_setup(buffer, - LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 0x04, 0x01, 0, 0); - libusb_fill_control_transfer(transfer, dev, buffer, cb, &completed, 1000); - libusb_submit_transfer(transfer); - - while (!completed) { - poll(libusb file descriptors, 120*1000); - if (poll indicates activity) - libusb_handle_events_timeout(ctx, &zero_tv); - } - printf("completed!"); - // other code here -} -\endcode - * - * Here we are serializing completion of an asynchronous event - * against a condition - the condition being completion of a specific transfer. - * The poll() loop has a long timeout to minimize CPU usage during situations - * when nothing is happening (it could reasonably be unlimited). - * - * If this is the only thread that is polling libusb's file descriptors, there - * is no problem: there is no danger that another thread will swallow up the - * event that we are interested in. On the other hand, if there is another - * thread polling the same descriptors, there is a chance that it will receive - * the event that we were interested in. In this situation, myfunc() - * will only realise that the transfer has completed on the next iteration of - * the loop, up to 120 seconds later. Clearly a two-minute delay is - * undesirable, and don't even think about using short timeouts to circumvent - * this issue! - * - * The solution here is to ensure that no two threads are ever polling the - * file descriptors at the same time. A naive implementation of this would - * impact the capabilities of the library, so libusb offers the scheme - * documented below to ensure no loss of functionality. - * - * Before we go any further, it is worth mentioning that all libusb-wrapped - * event handling procedures fully adhere to the scheme documented below. - * This includes libusb_handle_events() and its variants, and all the - * synchronous I/O functions - libusb hides this headache from you. - * - * \section Using libusb_handle_events() from multiple threads - * - * Even when only using libusb_handle_events() and synchronous I/O functions, - * you can still have a race condition. You might be tempted to solve the - * above with libusb_handle_events() like so: - * -\code - libusb_submit_transfer(transfer); - - while (!completed) { - libusb_handle_events(ctx); - } - printf("completed!"); -\endcode - * - * This however has a race between the checking of completed and - * libusb_handle_events() acquiring the events lock, so another thread - * could have completed the transfer, resulting in this thread hanging - * until either a timeout or another event occurs. See also commit - * 6696512aade99bb15d6792af90ae329af270eba6 which fixes this in the - * synchronous API implementation of libusb. - * - * Fixing this race requires checking the variable completed only after - * taking the event lock, which defeats the concept of just calling - * libusb_handle_events() without worrying about locking. This is why - * libusb-1.0.9 introduces the new libusb_handle_events_timeout_completed() - * and libusb_handle_events_completed() functions, which handles doing the - * completion check for you after they have acquired the lock: - * -\code - libusb_submit_transfer(transfer); - - while (!completed) { - libusb_handle_events_completed(ctx, &completed); - } - printf("completed!"); -\endcode - * - * This nicely fixes the race in our example. Note that if all you want to - * do is submit a single transfer and wait for its completion, then using - * one of the synchronous I/O functions is much easier. - * - * \section eventlock The events lock - * - * The problem is when we consider the fact that libusb exposes file - * descriptors to allow for you to integrate asynchronous USB I/O into - * existing main loops, effectively allowing you to do some work behind - * libusb's back. If you do take libusb's file descriptors and pass them to - * poll()/select() yourself, you need to be aware of the associated issues. - * - * The first concept to be introduced is the events lock. The events lock - * is used to serialize threads that want to handle events, such that only - * one thread is handling events at any one time. - * - * You must take the events lock before polling libusb file descriptors, - * using libusb_lock_events(). You must release the lock as soon as you have - * aborted your poll()/select() loop, using libusb_unlock_events(). - * - * \section threadwait Letting other threads do the work for you - * - * Although the events lock is a critical part of the solution, it is not - * enough on it's own. You might wonder if the following is sufficient... -\code - libusb_lock_events(ctx); - while (!completed) { - poll(libusb file descriptors, 120*1000); - if (poll indicates activity) - libusb_handle_events_timeout(ctx, &zero_tv); - } - libusb_unlock_events(ctx); -\endcode - * ...and the answer is that it is not. This is because the transfer in the - * code shown above may take a long time (say 30 seconds) to complete, and - * the lock is not released until the transfer is completed. - * - * Another thread with similar code that wants to do event handling may be - * working with a transfer that completes after a few milliseconds. Despite - * having such a quick completion time, the other thread cannot check that - * status of its transfer until the code above has finished (30 seconds later) - * due to contention on the lock. - * - * To solve this, libusb offers you a mechanism to determine when another - * thread is handling events. It also offers a mechanism to block your thread - * until the event handling thread has completed an event (and this mechanism - * does not involve polling of file descriptors). - * - * After determining that another thread is currently handling events, you - * obtain the event waiters lock using libusb_lock_event_waiters(). - * You then re-check that some other thread is still handling events, and if - * so, you call libusb_wait_for_event(). - * - * libusb_wait_for_event() puts your application to sleep until an event - * occurs, or until a thread releases the events lock. When either of these - * things happen, your thread is woken up, and should re-check the condition - * it was waiting on. It should also re-check that another thread is handling - * events, and if not, it should start handling events itself. - * - * This looks like the following, as pseudo-code: -\code -retry: -if (libusb_try_lock_events(ctx) == 0) { - // we obtained the event lock: do our own event handling - while (!completed) { - if (!libusb_event_handling_ok(ctx)) { - libusb_unlock_events(ctx); - goto retry; - } - poll(libusb file descriptors, 120*1000); - if (poll indicates activity) - libusb_handle_events_locked(ctx, 0); - } - libusb_unlock_events(ctx); -} else { - // another thread is doing event handling. wait for it to signal us that - // an event has completed - libusb_lock_event_waiters(ctx); - - while (!completed) { - // now that we have the event waiters lock, double check that another - // thread is still handling events for us. (it may have ceased handling - // events in the time it took us to reach this point) - if (!libusb_event_handler_active(ctx)) { - // whoever was handling events is no longer doing so, try again - libusb_unlock_event_waiters(ctx); - goto retry; - } - - libusb_wait_for_event(ctx, NULL); - } - libusb_unlock_event_waiters(ctx); -} -printf("completed!\n"); -\endcode - * - * A naive look at the above code may suggest that this can only support - * one event waiter (hence a total of 2 competing threads, the other doing - * event handling), because the event waiter seems to have taken the event - * waiters lock while waiting for an event. However, the system does support - * multiple event waiters, because libusb_wait_for_event() actually drops - * the lock while waiting, and reaquires it before continuing. - * - * We have now implemented code which can dynamically handle situations where - * nobody is handling events (so we should do it ourselves), and it can also - * handle situations where another thread is doing event handling (so we can - * piggyback onto them). It is also equipped to handle a combination of - * the two, for example, another thread is doing event handling, but for - * whatever reason it stops doing so before our condition is met, so we take - * over the event handling. - * - * Four functions were introduced in the above pseudo-code. Their importance - * should be apparent from the code shown above. - * -# libusb_try_lock_events() is a non-blocking function which attempts - * to acquire the events lock but returns a failure code if it is contended. - * -# libusb_event_handling_ok() checks that libusb is still happy for your - * thread to be performing event handling. Sometimes, libusb needs to - * interrupt the event handler, and this is how you can check if you have - * been interrupted. If this function returns 0, the correct behaviour is - * for you to give up the event handling lock, and then to repeat the cycle. - * The following libusb_try_lock_events() will fail, so you will become an - * events waiter. For more information on this, read \ref fullstory below. - * -# libusb_handle_events_locked() is a variant of - * libusb_handle_events_timeout() that you can call while holding the - * events lock. libusb_handle_events_timeout() itself implements similar - * logic to the above, so be sure not to call it when you are - * "working behind libusb's back", as is the case here. - * -# libusb_event_handler_active() determines if someone is currently - * holding the events lock - * - * You might be wondering why there is no function to wake up all threads - * blocked on libusb_wait_for_event(). This is because libusb can do this - * internally: it will wake up all such threads when someone calls - * libusb_unlock_events() or when a transfer completes (at the point after its - * callback has returned). - * - * \subsection fullstory The full story - * - * The above explanation should be enough to get you going, but if you're - * really thinking through the issues then you may be left with some more - * questions regarding libusb's internals. If you're curious, read on, and if - * not, skip to the next section to avoid confusing yourself! - * - * The immediate question that may spring to mind is: what if one thread - * modifies the set of file descriptors that need to be polled while another - * thread is doing event handling? - * - * There are 2 situations in which this may happen. - * -# libusb_open() will add another file descriptor to the poll set, - * therefore it is desirable to interrupt the event handler so that it - * restarts, picking up the new descriptor. - * -# libusb_close() will remove a file descriptor from the poll set. There - * are all kinds of race conditions that could arise here, so it is - * important that nobody is doing event handling at this time. - * - * libusb handles these issues internally, so application developers do not - * have to stop their event handlers while opening/closing devices. Here's how - * it works, focusing on the libusb_close() situation first: - * - * -# During initialization, libusb opens an internal pipe, and it adds the read - * end of this pipe to the set of file descriptors to be polled. - * -# During libusb_close(), libusb writes some dummy data on this event pipe. - * This immediately interrupts the event handler. libusb also records - * internally that it is trying to interrupt event handlers for this - * high-priority event. - * -# At this point, some of the functions described above start behaving - * differently: - * - libusb_event_handling_ok() starts returning 1, indicating that it is NOT - * OK for event handling to continue. - * - libusb_try_lock_events() starts returning 1, indicating that another - * thread holds the event handling lock, even if the lock is uncontended. - * - libusb_event_handler_active() starts returning 1, indicating that - * another thread is doing event handling, even if that is not true. - * -# The above changes in behaviour result in the event handler stopping and - * giving up the events lock very quickly, giving the high-priority - * libusb_close() operation a "free ride" to acquire the events lock. All - * threads that are competing to do event handling become event waiters. - * -# With the events lock held inside libusb_close(), libusb can safely remove - * a file descriptor from the poll set, in the safety of knowledge that - * nobody is polling those descriptors or trying to access the poll set. - * -# After obtaining the events lock, the close operation completes very - * quickly (usually a matter of milliseconds) and then immediately releases - * the events lock. - * -# At the same time, the behaviour of libusb_event_handling_ok() and friends - * reverts to the original, documented behaviour. - * -# The release of the events lock causes the threads that are waiting for - * events to be woken up and to start competing to become event handlers - * again. One of them will succeed; it will then re-obtain the list of poll - * descriptors, and USB I/O will then continue as normal. - * - * libusb_open() is similar, and is actually a more simplistic case. Upon a - * call to libusb_open(): - * - * -# The device is opened and a file descriptor is added to the poll set. - * -# libusb sends some dummy data on the event pipe, and records that it - * is trying to modify the poll descriptor set. - * -# The event handler is interrupted, and the same behaviour change as for - * libusb_close() takes effect, causing all event handling threads to become - * event waiters. - * -# The libusb_open() implementation takes its free ride to the events lock. - * -# Happy that it has successfully paused the events handler, libusb_open() - * releases the events lock. - * -# The event waiter threads are all woken up and compete to become event - * handlers again. The one that succeeds will obtain the list of poll - * descriptors again, which will include the addition of the new device. - * - * \subsection concl Closing remarks - * - * The above may seem a little complicated, but hopefully I have made it clear - * why such complications are necessary. Also, do not forget that this only - * applies to applications that take libusb's file descriptors and integrate - * them into their own polling loops. - * - * You may decide that it is OK for your multi-threaded application to ignore - * some of the rules and locks detailed above, because you don't think that - * two threads can ever be polling the descriptors at the same time. If that - * is the case, then that's good news for you because you don't have to worry. - * But be careful here; remember that the synchronous I/O functions do event - * handling internally. If you have one thread doing event handling in a loop - * (without implementing the rules and locking semantics documented above) - * and another trying to send a synchronous USB transfer, you will end up with - * two threads monitoring the same descriptors, and the above-described - * undesirable behaviour occurring. The solution is for your polling thread to - * play by the rules; the synchronous I/O functions do so, and this will result - * in them getting along in perfect harmony. - * - * If you do have a dedicated thread doing event handling, it is perfectly - * legal for it to take the event handling lock for long periods of time. Any - * synchronous I/O functions you call from other threads will transparently - * fall back to the "event waiters" mechanism detailed above. The only - * consideration that your event handling thread must apply is the one related - * to libusb_event_handling_ok(): you must call this before every poll(), and - * give up the events lock if instructed. - */ - -int usbi_io_init(struct libusb_context *ctx) -{ - int r; - - usbi_mutex_init(&ctx->flying_transfers_lock); - usbi_mutex_init(&ctx->events_lock); - usbi_mutex_init(&ctx->event_waiters_lock); - usbi_cond_init(&ctx->event_waiters_cond); - usbi_mutex_init(&ctx->event_data_lock); - usbi_tls_key_create(&ctx->event_handling_key); - list_init(&ctx->flying_transfers); - list_init(&ctx->ipollfds); - list_init(&ctx->hotplug_msgs); - list_init(&ctx->completed_transfers); - - /* FIXME should use an eventfd on kernels that support it */ - r = usbi_pipe(ctx->event_pipe); - if (r < 0) { - r = LIBUSB_ERROR_OTHER; - goto err; - } - - r = usbi_add_pollfd(ctx, ctx->event_pipe[0], POLLIN); - if (r < 0) - goto err_close_pipe; - -#ifdef USBI_TIMERFD_AVAILABLE - ctx->timerfd = timerfd_create(usbi_backend->get_timerfd_clockid(), - TFD_NONBLOCK); - if (ctx->timerfd >= 0) { - usbi_dbg("using timerfd for timeouts"); - r = usbi_add_pollfd(ctx, ctx->timerfd, POLLIN); - if (r < 0) - goto err_close_timerfd; - } else { - usbi_dbg("timerfd not available (code %d error %d)", ctx->timerfd, errno); - ctx->timerfd = -1; - } -#endif - - return 0; - -#ifdef USBI_TIMERFD_AVAILABLE -err_close_timerfd: - close(ctx->timerfd); - usbi_remove_pollfd(ctx, ctx->event_pipe[0]); -#endif -err_close_pipe: - usbi_close(ctx->event_pipe[0]); - usbi_close(ctx->event_pipe[1]); -err: - usbi_mutex_destroy(&ctx->flying_transfers_lock); - usbi_mutex_destroy(&ctx->events_lock); - usbi_mutex_destroy(&ctx->event_waiters_lock); - usbi_cond_destroy(&ctx->event_waiters_cond); - usbi_mutex_destroy(&ctx->event_data_lock); - usbi_tls_key_delete(ctx->event_handling_key); - return r; -} - -void usbi_io_exit(struct libusb_context *ctx) -{ - usbi_remove_pollfd(ctx, ctx->event_pipe[0]); - usbi_close(ctx->event_pipe[0]); - usbi_close(ctx->event_pipe[1]); -#ifdef USBI_TIMERFD_AVAILABLE - if (usbi_using_timerfd(ctx)) { - usbi_remove_pollfd(ctx, ctx->timerfd); - close(ctx->timerfd); - } -#endif - usbi_mutex_destroy(&ctx->flying_transfers_lock); - usbi_mutex_destroy(&ctx->events_lock); - usbi_mutex_destroy(&ctx->event_waiters_lock); - usbi_cond_destroy(&ctx->event_waiters_cond); - usbi_mutex_destroy(&ctx->event_data_lock); - usbi_tls_key_delete(ctx->event_handling_key); - if (ctx->pollfds) - free(ctx->pollfds); -} - -static int calculate_timeout(struct usbi_transfer *transfer) -{ - int r; - struct timespec current_time; - unsigned int timeout = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout; - - if (!timeout) - return 0; - - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, ¤t_time); - if (r < 0) { - usbi_err(ITRANSFER_CTX(transfer), - "failed to read monotonic clock, errno=%d", errno); - return r; - } - - current_time.tv_sec += timeout / 1000; - current_time.tv_nsec += (timeout % 1000) * 1000000; - - while (current_time.tv_nsec >= 1000000000) { - current_time.tv_nsec -= 1000000000; - current_time.tv_sec++; - } - - TIMESPEC_TO_TIMEVAL(&transfer->timeout, ¤t_time); - return 0; -} - -/** \ingroup libusb_asyncio - * Allocate a libusb transfer with a specified number of isochronous packet - * descriptors. The returned transfer is pre-initialized for you. When the new - * transfer is no longer needed, it should be freed with - * libusb_free_transfer(). - * - * Transfers intended for non-isochronous endpoints (e.g. control, bulk, - * interrupt) should specify an iso_packets count of zero. - * - * For transfers intended for isochronous endpoints, specify an appropriate - * number of packet descriptors to be allocated as part of the transfer. - * The returned transfer is not specially initialized for isochronous I/O; - * you are still required to set the - * \ref libusb_transfer::num_iso_packets "num_iso_packets" and - * \ref libusb_transfer::type "type" fields accordingly. - * - * It is safe to allocate a transfer with some isochronous packets and then - * use it on a non-isochronous endpoint. If you do this, ensure that at time - * of submission, num_iso_packets is 0 and that type is set appropriately. - * - * \param iso_packets number of isochronous packet descriptors to allocate - * \returns a newly allocated transfer, or NULL on error - */ -DEFAULT_VISIBILITY -struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer( - int iso_packets) -{ - struct libusb_transfer *transfer; - size_t os_alloc_size = usbi_backend->transfer_priv_size; - size_t alloc_size = sizeof(struct usbi_transfer) - + sizeof(struct libusb_transfer) - + (sizeof(struct libusb_iso_packet_descriptor) * iso_packets) - + os_alloc_size; - struct usbi_transfer *itransfer = calloc(1, alloc_size); - if (!itransfer) - return NULL; - - itransfer->num_iso_packets = iso_packets; - usbi_mutex_init(&itransfer->lock); - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - usbi_dbg("transfer %p", transfer); - return transfer; -} - -/** \ingroup libusb_asyncio - * Free a transfer structure. This should be called for all transfers - * allocated with libusb_alloc_transfer(). - * - * If the \ref libusb_transfer_flags::LIBUSB_TRANSFER_FREE_BUFFER - * "LIBUSB_TRANSFER_FREE_BUFFER" flag is set and the transfer buffer is - * non-NULL, this function will also free the transfer buffer using the - * standard system memory allocator (e.g. free()). - * - * It is legal to call this function with a NULL transfer. In this case, - * the function will simply return safely. - * - * It is not legal to free an active transfer (one which has been submitted - * and has not yet completed). - * - * \param transfer the transfer to free - */ -void API_EXPORTED libusb_free_transfer(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer; - if (!transfer) - return; - - usbi_dbg("transfer %p", transfer); - if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER && transfer->buffer) - free(transfer->buffer); - - itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - usbi_mutex_destroy(&itransfer->lock); - free(itransfer); -} - -#ifdef USBI_TIMERFD_AVAILABLE -static int disarm_timerfd(struct libusb_context *ctx) -{ - const struct itimerspec disarm_timer = { { 0, 0 }, { 0, 0 } }; - int r; - - usbi_dbg(""); - r = timerfd_settime(ctx->timerfd, 0, &disarm_timer, NULL); - if (r < 0) - return LIBUSB_ERROR_OTHER; - else - return 0; -} - -/* iterates through the flying transfers, and rearms the timerfd based on the - * next upcoming timeout. - * must be called with flying_list locked. - * returns 0 on success or a LIBUSB_ERROR code on failure. - */ -static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) -{ - struct usbi_transfer *transfer; - - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - struct timeval *cur_tv = &transfer->timeout; - - /* if we've reached transfers of infinite timeout, then we have no - * arming to do */ - if (!timerisset(cur_tv)) - goto disarm; - - /* act on first transfer that has not already been handled */ - if (!(transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))) { - int r; - const struct itimerspec it = { {0, 0}, - { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } }; - usbi_dbg("next timeout originally %dms", USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); - r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); - if (r < 0) - return LIBUSB_ERROR_OTHER; - return 0; - } - } - -disarm: - return disarm_timerfd(ctx); -} -#else -static int arm_timerfd_for_next_timeout(struct libusb_context *ctx) -{ - UNUSED(ctx); - return 0; -} -#endif - -/* add a transfer to the (timeout-sorted) active transfers list. - * This function will return non 0 if fails to update the timer, - * in which case the transfer is *not* on the flying_transfers list. */ -static int add_to_flying_list(struct usbi_transfer *transfer) -{ - struct usbi_transfer *cur; - struct timeval *timeout = &transfer->timeout; - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int r; - int first = 1; - - r = calculate_timeout(transfer); - if (r) - return r; - - /* if we have no other flying transfers, start the list with this one */ - if (list_empty(&ctx->flying_transfers)) { - list_add(&transfer->list, &ctx->flying_transfers); - goto out; - } - - /* if we have infinite timeout, append to end of list */ - if (!timerisset(timeout)) { - list_add_tail(&transfer->list, &ctx->flying_transfers); - /* first is irrelevant in this case */ - goto out; - } - - /* otherwise, find appropriate place in list */ - list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) { - /* find first timeout that occurs after the transfer in question */ - struct timeval *cur_tv = &cur->timeout; - - if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) || - (cur_tv->tv_sec == timeout->tv_sec && - cur_tv->tv_usec > timeout->tv_usec)) { - list_add_tail(&transfer->list, &cur->list); - goto out; - } - first = 0; - } - /* first is 0 at this stage (list not empty) */ - - /* otherwise we need to be inserted at the end */ - list_add_tail(&transfer->list, &ctx->flying_transfers); -out: -#ifdef USBI_TIMERFD_AVAILABLE - if (first && usbi_using_timerfd(ctx) && timerisset(timeout)) { - /* if this transfer has the lowest timeout of all active transfers, - * rearm the timerfd with this transfer's timeout */ - const struct itimerspec it = { {0, 0}, - { timeout->tv_sec, timeout->tv_usec * 1000 } }; - usbi_dbg("arm timerfd for timeout in %dms (first in line)", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)->timeout); - r = timerfd_settime(ctx->timerfd, TFD_TIMER_ABSTIME, &it, NULL); - if (r < 0) { - usbi_warn(ctx, "failed to arm first timerfd (errno %d)", errno); - r = LIBUSB_ERROR_OTHER; - } - } -#else - UNUSED(first); -#endif - - if (r) - list_del(&transfer->list); - - return r; -} - -/* remove a transfer from the active transfers list. - * This function will *always* remove the transfer from the - * flying_transfers list. It will return a LIBUSB_ERROR code - * if it fails to update the timer for the next timeout. */ -static int remove_from_flying_list(struct usbi_transfer *transfer) -{ - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int rearm_timerfd; - int r = 0; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - rearm_timerfd = (timerisset(&transfer->timeout) && - list_first_entry(&ctx->flying_transfers, struct usbi_transfer, list) == transfer); - list_del(&transfer->list); - if (usbi_using_timerfd(ctx) && rearm_timerfd) - r = arm_timerfd_for_next_timeout(ctx); - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - return r; -} - -/** \ingroup libusb_asyncio - * Submit a transfer. This function will fire off the USB transfer and then - * return immediately. - * - * \param transfer the transfer to submit - * \returns 0 on success - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if the transfer has already been submitted. - * \returns LIBUSB_ERROR_NOT_SUPPORTED if the transfer flags are not supported - * by the operating system. - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than - * the operating system and/or hardware can support - * \returns another LIBUSB_ERROR code on other failure - */ -int API_EXPORTED libusb_submit_transfer(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - struct libusb_context *ctx = TRANSFER_CTX(transfer); - int r; - - usbi_dbg("transfer %p", transfer); - - /* - * Important note on locking, this function takes / releases locks - * in the following order: - * take flying_transfers_lock - * take itransfer->lock - * clear transfer - * add to flying_transfers list - * release flying_transfers_lock - * submit transfer - * release itransfer->lock - * if submit failed: - * take flying_transfers_lock - * remove from flying_transfers list - * release flying_transfers_lock - * - * Note that it takes locks in the order a-b and then releases them - * in the same order a-b. This is somewhat unusual but not wrong, - * release order is not important as long as *all* locks are released - * before re-acquiring any locks. - * - * This means that the ordering of first releasing itransfer->lock - * and then re-acquiring the flying_transfers_list on error is - * important and must not be changed! - * - * This is done this way because when we take both locks we must always - * take flying_transfers_lock first to avoid ab-ba style deadlocks with - * the timeout handling and usbi_handle_disconnect paths. - * - * And we cannot release itransfer->lock before the submission is - * complete otherwise timeout handling for transfers with short - * timeouts may run before submission. - */ - usbi_mutex_lock(&ctx->flying_transfers_lock); - usbi_mutex_lock(&itransfer->lock); - if (itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_mutex_unlock(&itransfer->lock); - return LIBUSB_ERROR_BUSY; - } - itransfer->transferred = 0; - itransfer->state_flags = 0; - itransfer->timeout_flags = 0; - r = add_to_flying_list(itransfer); - if (r) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_mutex_unlock(&itransfer->lock); - return r; - } - /* - * We must release the flying transfers lock here, because with - * some backends the submit_transfer method is synchroneous. - */ - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - r = usbi_backend->submit_transfer(itransfer); - if (r == LIBUSB_SUCCESS) { - itransfer->state_flags |= USBI_TRANSFER_IN_FLIGHT; - /* keep a reference to this device */ - libusb_ref_device(transfer->dev_handle->dev); - } - usbi_mutex_unlock(&itransfer->lock); - - if (r != LIBUSB_SUCCESS) - remove_from_flying_list(itransfer); - - return r; -} - -/** \ingroup libusb_asyncio - * Asynchronously cancel a previously submitted transfer. - * This function returns immediately, but this does not indicate cancellation - * is complete. Your callback function will be invoked at some later time - * with a transfer status of - * \ref libusb_transfer_status::LIBUSB_TRANSFER_CANCELLED - * "LIBUSB_TRANSFER_CANCELLED." - * - * \param transfer the transfer to cancel - * \returns 0 on success - * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress, - * already complete, or already cancelled. - * \returns a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - int r; - - usbi_dbg("transfer %p", transfer ); - usbi_mutex_lock(&itransfer->lock); - if (!(itransfer->state_flags & USBI_TRANSFER_IN_FLIGHT) - || (itransfer->state_flags & USBI_TRANSFER_CANCELLING)) { - r = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - r = usbi_backend->cancel_transfer(itransfer); - if (r < 0) { - if (r != LIBUSB_ERROR_NOT_FOUND && - r != LIBUSB_ERROR_NO_DEVICE) - usbi_err(TRANSFER_CTX(transfer), - "cancel transfer failed error %d", r); - else - usbi_dbg("cancel transfer failed error %d", r); - - if (r == LIBUSB_ERROR_NO_DEVICE) - itransfer->state_flags |= USBI_TRANSFER_DEVICE_DISAPPEARED; - } - - itransfer->state_flags |= USBI_TRANSFER_CANCELLING; - -out: - usbi_mutex_unlock(&itransfer->lock); - return r; -} - -/** \ingroup libusb_asyncio - * Set a transfers bulk stream id. Note users are advised to use - * libusb_fill_bulk_stream_transfer() instead of calling this function - * directly. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param transfer the transfer to set the stream id for - * \param stream_id the stream id to set - * \see libusb_alloc_streams() - */ -void API_EXPORTED libusb_transfer_set_stream_id( - struct libusb_transfer *transfer, uint32_t stream_id) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - - itransfer->stream_id = stream_id; -} - -/** \ingroup libusb_asyncio - * Get a transfers bulk stream id. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param transfer the transfer to get the stream id for - * \returns the stream id for the transfer - */ -uint32_t API_EXPORTED libusb_transfer_get_stream_id( - struct libusb_transfer *transfer) -{ - struct usbi_transfer *itransfer = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); - - return itransfer->stream_id; -} - -/* Handle completion of a transfer (completion might be an error condition). - * This will invoke the user-supplied callback function, which may end up - * freeing the transfer. Therefore you cannot use the transfer structure - * after calling this function, and you should free all backend-specific - * data before calling it. - * Do not call this function with the usbi_transfer lock held. User-specified - * callback functions may attempt to directly resubmit the transfer, which - * will attempt to take the lock. */ -int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, - enum libusb_transfer_status status) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_device_handle *dev_handle = transfer->dev_handle; - uint8_t flags; - int r; - - r = remove_from_flying_list(itransfer); - if (r < 0) - usbi_err(ITRANSFER_CTX(itransfer), "failed to set timer for next timeout, errno=%d", errno); - - usbi_mutex_lock(&itransfer->lock); - itransfer->state_flags &= ~USBI_TRANSFER_IN_FLIGHT; - usbi_mutex_unlock(&itransfer->lock); - - if (status == LIBUSB_TRANSFER_COMPLETED - && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) { - int rqlen = transfer->length; - if (transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL) - rqlen -= LIBUSB_CONTROL_SETUP_SIZE; - if (rqlen != itransfer->transferred) { - usbi_dbg("interpreting short transfer as error"); - status = LIBUSB_TRANSFER_ERROR; - } - } - - flags = transfer->flags; - transfer->status = status; - transfer->actual_length = itransfer->transferred; - usbi_dbg("transfer %p has callback %p", transfer, transfer->callback); - if (transfer->callback) - transfer->callback(transfer); - /* transfer might have been freed by the above call, do not use from - * this point. */ - if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) - libusb_free_transfer(transfer); - libusb_unref_device(dev_handle->dev); - return r; -} - -/* Similar to usbi_handle_transfer_completion() but exclusively for transfers - * that were asynchronously cancelled. The same concerns w.r.t. freeing of - * transfers exist here. - * Do not call this function with the usbi_transfer lock held. User-specified - * callback functions may attempt to directly resubmit the transfer, which - * will attempt to take the lock. */ -int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer) -{ - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - uint8_t timed_out; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - timed_out = transfer->timeout_flags & USBI_TRANSFER_TIMED_OUT; - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - /* if the URB was cancelled due to timeout, report timeout to the user */ - if (timed_out) { - usbi_dbg("detected timeout cancellation"); - return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT); - } - - /* otherwise its a normal async cancel */ - return usbi_handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED); -} - -/* Add a completed transfer to the completed_transfers list of the - * context and signal the event. The backend's handle_transfer_completion() - * function will be called the next time an event handler runs. */ -void usbi_signal_transfer_completion(struct usbi_transfer *transfer) -{ - struct libusb_context *ctx = ITRANSFER_CTX(transfer); - int pending_events; - - usbi_mutex_lock(&ctx->event_data_lock); - pending_events = usbi_pending_events(ctx); - list_add_tail(&transfer->completed_list, &ctx->completed_transfers); - if (!pending_events) - usbi_signal_event(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); -} - -/** \ingroup libusb_poll - * Attempt to acquire the event handling lock. This lock is used to ensure that - * only one thread is monitoring libusb event sources at any one time. - * - * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly. - * If you stick to libusb's event handling loop functions (e.g. - * libusb_handle_events()) then you do not need to be concerned with this - * locking. - * - * While holding this lock, you are trusted to actually be handling events. - * If you are no longer handling events, you must call libusb_unlock_events() - * as soon as possible. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 0 if the lock was obtained successfully - * \returns 1 if the lock was not obtained (i.e. another thread holds the lock) - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) -{ - int r; - unsigned int ru; - USBI_GET_CONTEXT(ctx); - - /* is someone else waiting to close a device? if so, don't let this thread - * start event handling */ - usbi_mutex_lock(&ctx->event_data_lock); - ru = ctx->device_close; - usbi_mutex_unlock(&ctx->event_data_lock); - if (ru) { - usbi_dbg("someone else is closing a device"); - return 1; - } - - r = usbi_mutex_trylock(&ctx->events_lock); - if (r) - return 1; - - ctx->event_handler_active = 1; - return 0; -} - -/** \ingroup libusb_poll - * Acquire the event handling lock, blocking until successful acquisition if - * it is contended. This lock is used to ensure that only one thread is - * monitoring libusb event sources at any one time. - * - * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly. - * If you stick to libusb's event handling loop functions (e.g. - * libusb_handle_events()) then you do not need to be concerned with this - * locking. - * - * While holding this lock, you are trusted to actually be handling events. - * If you are no longer handling events, you must call libusb_unlock_events() - * as soon as possible. - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_lock_events(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - usbi_mutex_lock(&ctx->events_lock); - ctx->event_handler_active = 1; -} - -/** \ingroup libusb_poll - * Release the lock previously acquired with libusb_try_lock_events() or - * libusb_lock_events(). Releasing this lock will wake up any threads blocked - * on libusb_wait_for_event(). - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_unlock_events(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - ctx->event_handler_active = 0; - usbi_mutex_unlock(&ctx->events_lock); - - /* FIXME: perhaps we should be a bit more efficient by not broadcasting - * the availability of the events lock when we are modifying pollfds - * (check ctx->device_close)? */ - usbi_mutex_lock(&ctx->event_waiters_lock); - usbi_cond_broadcast(&ctx->event_waiters_cond); - usbi_mutex_unlock(&ctx->event_waiters_lock); -} - -/** \ingroup libusb_poll - * Determine if it is still OK for this thread to be doing event handling. - * - * Sometimes, libusb needs to temporarily pause all event handlers, and this - * is the function you should use before polling file descriptors to see if - * this is the case. - * - * If this function instructs your thread to give up the events lock, you - * should just continue the usual logic that is documented in \ref libusb_mtasync. - * On the next iteration, your thread will fail to obtain the events lock, - * and will hence become an event waiter. - * - * This function should be called while the events lock is held: you don't - * need to worry about the results of this function if your thread is not - * the current event handler. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 1 if event handling can start or continue - * \returns 0 if this thread must give up the events lock - * \ref fullstory "Multi-threaded I/O: the full story" - */ -int API_EXPORTED libusb_event_handling_ok(libusb_context *ctx) -{ - unsigned int r; - USBI_GET_CONTEXT(ctx); - - /* is someone else waiting to close a device? if so, don't let this thread - * continue event handling */ - usbi_mutex_lock(&ctx->event_data_lock); - r = ctx->device_close; - usbi_mutex_unlock(&ctx->event_data_lock); - if (r) { - usbi_dbg("someone else is closing a device"); - return 0; - } - - return 1; -} - - -/** \ingroup libusb_poll - * Determine if an active thread is handling events (i.e. if anyone is holding - * the event handling lock). - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 1 if a thread is handling events - * \returns 0 if there are no threads currently handling events - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_event_handler_active(libusb_context *ctx) -{ - unsigned int r; - USBI_GET_CONTEXT(ctx); - - /* is someone else waiting to close a device? if so, don't let this thread - * start event handling -- indicate that event handling is happening */ - usbi_mutex_lock(&ctx->event_data_lock); - r = ctx->device_close; - usbi_mutex_unlock(&ctx->event_data_lock); - if (r) { - usbi_dbg("someone else is closing a device"); - return 1; - } - - return ctx->event_handler_active; -} - -/** \ingroup libusb_poll - * Interrupt any active thread that is handling events. This is mainly useful - * for interrupting a dedicated event handling thread when an application - * wishes to call libusb_exit(). - * - * Since version 1.0.21, \ref LIBUSB_API_VERSION >= 0x01000105 - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_interrupt_event_handler(libusb_context *ctx) -{ - int pending_events; - USBI_GET_CONTEXT(ctx); - - usbi_dbg(""); - usbi_mutex_lock(&ctx->event_data_lock); - - pending_events = usbi_pending_events(ctx); - ctx->event_flags |= USBI_EVENT_USER_INTERRUPT; - if (!pending_events) - usbi_signal_event(ctx); - - usbi_mutex_unlock(&ctx->event_data_lock); -} - -/** \ingroup libusb_poll - * Acquire the event waiters lock. This lock is designed to be obtained under - * the situation where you want to be aware when events are completed, but - * some other thread is event handling so calling libusb_handle_events() is not - * allowed. - * - * You then obtain this lock, re-check that another thread is still handling - * events, then call libusb_wait_for_event(). - * - * You only need to use this lock if you are developing an application - * which calls poll() or select() on libusb's file descriptors directly, - * and may potentially be handling events from 2 threads simultaenously. - * If you stick to libusb's event handling loop functions (e.g. - * libusb_handle_events()) then you do not need to be concerned with this - * locking. - * - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_lock_event_waiters(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - usbi_mutex_lock(&ctx->event_waiters_lock); -} - -/** \ingroup libusb_poll - * Release the event waiters lock. - * \param ctx the context to operate on, or NULL for the default context - * \ref libusb_mtasync - */ -void API_EXPORTED libusb_unlock_event_waiters(libusb_context *ctx) -{ - USBI_GET_CONTEXT(ctx); - usbi_mutex_unlock(&ctx->event_waiters_lock); -} - -/** \ingroup libusb_poll - * Wait for another thread to signal completion of an event. Must be called - * with the event waiters lock held, see libusb_lock_event_waiters(). - * - * This function will block until any of the following conditions are met: - * -# The timeout expires - * -# A transfer completes - * -# A thread releases the event handling lock through libusb_unlock_events() - * - * Condition 1 is obvious. Condition 2 unblocks your thread after - * the callback for the transfer has completed. Condition 3 is important - * because it means that the thread that was previously handling events is no - * longer doing so, so if any events are to complete, another thread needs to - * step up and start event handling. - * - * This function releases the event waiters lock before putting your thread - * to sleep, and reacquires the lock as it is being woken up. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv maximum timeout for this blocking function. A NULL value - * indicates unlimited timeout. - * \returns 0 after a transfer completes or another thread stops event handling - * \returns 1 if the timeout expired - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) -{ - int r; - - USBI_GET_CONTEXT(ctx); - if (tv == NULL) { - usbi_cond_wait(&ctx->event_waiters_cond, &ctx->event_waiters_lock); - return 0; - } - - r = usbi_cond_timedwait(&ctx->event_waiters_cond, - &ctx->event_waiters_lock, tv); - - if (r < 0) - return r; - else - return (r == ETIMEDOUT); -} - -static void handle_timeout(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int r; - - itransfer->timeout_flags |= USBI_TRANSFER_TIMEOUT_HANDLED; - r = libusb_cancel_transfer(transfer); - if (r == LIBUSB_SUCCESS) - itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; - else - usbi_warn(TRANSFER_CTX(transfer), - "async cancel failed %d errno=%d", r, errno); -} - -static int handle_timeouts_locked(struct libusb_context *ctx) -{ - int r; - struct timespec systime_ts; - struct timeval systime; - struct usbi_transfer *transfer; - - if (list_empty(&ctx->flying_transfers)) - return 0; - - /* get current time */ - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &systime_ts); - if (r < 0) - return r; - - TIMESPEC_TO_TIMEVAL(&systime, &systime_ts); - - /* iterate through flying transfers list, finding all transfers that - * have expired timeouts */ - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - struct timeval *cur_tv = &transfer->timeout; - - /* if we've reached transfers of infinite timeout, we're all done */ - if (!timerisset(cur_tv)) - return 0; - - /* ignore timeouts we've already handled */ - if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) - continue; - - /* if transfer has non-expired timeout, nothing more to do */ - if ((cur_tv->tv_sec > systime.tv_sec) || - (cur_tv->tv_sec == systime.tv_sec && - cur_tv->tv_usec > systime.tv_usec)) - return 0; - - /* otherwise, we've got an expired timeout to handle */ - handle_timeout(transfer); - } - return 0; -} - -static int handle_timeouts(struct libusb_context *ctx) -{ - int r; - USBI_GET_CONTEXT(ctx); - usbi_mutex_lock(&ctx->flying_transfers_lock); - r = handle_timeouts_locked(ctx); - usbi_mutex_unlock(&ctx->flying_transfers_lock); - return r; -} - -#ifdef USBI_TIMERFD_AVAILABLE -static int handle_timerfd_trigger(struct libusb_context *ctx) -{ - int r; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - - /* process the timeout that just happened */ - r = handle_timeouts_locked(ctx); - if (r < 0) - goto out; - - /* arm for next timeout*/ - r = arm_timerfd_for_next_timeout(ctx); - -out: - usbi_mutex_unlock(&ctx->flying_transfers_lock); - return r; -} -#endif - -/* do the actual event handling. assumes that no other thread is concurrently - * doing the same thing. */ -static int handle_events(struct libusb_context *ctx, struct timeval *tv) -{ - int r; - struct usbi_pollfd *ipollfd; - POLL_NFDS_TYPE nfds = 0; - POLL_NFDS_TYPE internal_nfds; - struct pollfd *fds = NULL; - int i = -1; - int timeout_ms; - int special_event; - - /* prevent attempts to recursively handle events (e.g. calling into - * libusb_handle_events() from within a hotplug or transfer callback) */ - if (usbi_handling_events(ctx)) - return LIBUSB_ERROR_BUSY; - usbi_start_event_handling(ctx); - - /* there are certain fds that libusb uses internally, currently: - * - * 1) event pipe - * 2) timerfd - * - * the backend will never need to attempt to handle events on these fds, so - * we determine how many fds are in use internally for this context and when - * handle_events() is called in the backend, the pollfd list and count will - * be adjusted to skip over these internal fds */ - if (usbi_using_timerfd(ctx)) - internal_nfds = 2; - else - internal_nfds = 1; - - /* only reallocate the poll fds when the list of poll fds has been modified - * since the last poll, otherwise reuse them to save the additional overhead */ - usbi_mutex_lock(&ctx->event_data_lock); - if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) { - usbi_dbg("poll fds modified, reallocating"); - - if (ctx->pollfds) { - free(ctx->pollfds); - ctx->pollfds = NULL; - } - - /* sanity check - it is invalid for a context to have fewer than the - * required internal fds (memory corruption?) */ - assert(ctx->pollfds_cnt >= internal_nfds); - - ctx->pollfds = calloc(ctx->pollfds_cnt, sizeof(*ctx->pollfds)); - if (!ctx->pollfds) { - usbi_mutex_unlock(&ctx->event_data_lock); - r = LIBUSB_ERROR_NO_MEM; - goto done; - } - - list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) { - struct libusb_pollfd *pollfd = &ipollfd->pollfd; - i++; - ctx->pollfds[i].fd = pollfd->fd; - ctx->pollfds[i].events = pollfd->events; - } - - /* reset the flag now that we have the updated list */ - ctx->event_flags &= ~USBI_EVENT_POLLFDS_MODIFIED; - - /* if no further pending events, clear the event pipe so that we do - * not immediately return from poll */ - if (!usbi_pending_events(ctx)) - usbi_clear_event(ctx); - } - fds = ctx->pollfds; - nfds = ctx->pollfds_cnt; - usbi_mutex_unlock(&ctx->event_data_lock); - - timeout_ms = (int)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); - - /* round up to next millisecond */ - if (tv->tv_usec % 1000) - timeout_ms++; - -redo_poll: - usbi_dbg("poll() %d fds with timeout in %dms", nfds, timeout_ms); - r = usbi_poll(fds, nfds, timeout_ms); - usbi_dbg("poll() returned %d", r); - if (r == 0) { - r = handle_timeouts(ctx); - goto done; - } - else if (r == -1 && errno == EINTR) { - r = LIBUSB_ERROR_INTERRUPTED; - goto done; - } - else if (r < 0) { - usbi_err(ctx, "poll failed %d err=%d", r, errno); - r = LIBUSB_ERROR_IO; - goto done; - } - - special_event = 0; - - /* fds[0] is always the event pipe */ - if (fds[0].revents) { - libusb_hotplug_message *message = NULL; - struct usbi_transfer *itransfer; - int ret = 0; - - usbi_dbg("caught a fish on the event pipe"); - - /* take the the event data lock while processing events */ - usbi_mutex_lock(&ctx->event_data_lock); - - /* check if someone added a new poll fd */ - if (ctx->event_flags & USBI_EVENT_POLLFDS_MODIFIED) - usbi_dbg("someone updated the poll fds"); - - if (ctx->event_flags & USBI_EVENT_USER_INTERRUPT) { - usbi_dbg("someone purposely interrupted"); - ctx->event_flags &= ~USBI_EVENT_USER_INTERRUPT; - } - - /* check if someone is closing a device */ - if (ctx->device_close) - usbi_dbg("someone is closing a device"); - - /* check for any pending hotplug messages */ - if (!list_empty(&ctx->hotplug_msgs)) { - usbi_dbg("hotplug message received"); - special_event = 1; - message = list_first_entry(&ctx->hotplug_msgs, libusb_hotplug_message, list); - list_del(&message->list); - } - - /* complete any pending transfers */ - while (ret == 0 && !list_empty(&ctx->completed_transfers)) { - itransfer = list_first_entry(&ctx->completed_transfers, struct usbi_transfer, completed_list); - list_del(&itransfer->completed_list); - usbi_mutex_unlock(&ctx->event_data_lock); - ret = usbi_backend->handle_transfer_completion(itransfer); - if (ret) - usbi_err(ctx, "backend handle_transfer_completion failed with error %d", ret); - usbi_mutex_lock(&ctx->event_data_lock); - } - - /* if no further pending events, clear the event pipe */ - if (!usbi_pending_events(ctx)) - usbi_clear_event(ctx); - - usbi_mutex_unlock(&ctx->event_data_lock); - - /* process the hotplug message, if any */ - if (message) { - usbi_hotplug_match(ctx, message->device, message->event); - - /* the device left, dereference the device */ - if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == message->event) - libusb_unref_device(message->device); - - free(message); - } - - if (ret) { - /* return error code */ - r = ret; - goto done; - } - - if (0 == --r) - goto handled; - } - -#ifdef USBI_TIMERFD_AVAILABLE - /* on timerfd configurations, fds[1] is the timerfd */ - if (usbi_using_timerfd(ctx) && fds[1].revents) { - /* timerfd indicates that a timeout has expired */ - int ret; - usbi_dbg("timerfd triggered"); - special_event = 1; - - ret = handle_timerfd_trigger(ctx); - if (ret < 0) { - /* return error code */ - r = ret; - goto done; - } - - if (0 == --r) - goto handled; - } -#endif - - r = usbi_backend->handle_events(ctx, fds + internal_nfds, nfds - internal_nfds, r); - if (r) - usbi_err(ctx, "backend handle_events failed with error %d", r); - -handled: - if (r == 0 && special_event) { - timeout_ms = 0; - goto redo_poll; - } - -done: - usbi_end_event_handling(ctx); - return r; -} - -/* returns the smallest of: - * 1. timeout of next URB - * 2. user-supplied timeout - * returns 1 if there is an already-expired timeout, otherwise returns 0 - * and populates out - */ -static int get_next_timeout(libusb_context *ctx, struct timeval *tv, - struct timeval *out) -{ - struct timeval timeout; - int r = libusb_get_next_timeout(ctx, &timeout); - if (r) { - /* timeout already expired? */ - if (!timerisset(&timeout)) - return 1; - - /* choose the smallest of next URB timeout or user specified timeout */ - if (timercmp(&timeout, tv, <)) - *out = timeout; - else - *out = *tv; - } else { - *out = *tv; - } - return 0; -} - -/** \ingroup libusb_poll - * Handle any pending events. - * - * libusb determines "pending events" by checking if any timeouts have expired - * and by checking the set of file descriptors for activity. - * - * If a zero timeval is passed, this function will handle any already-pending - * events and then immediately return in non-blocking style. - * - * If a non-zero timeval is passed and no events are currently pending, this - * function will block waiting for events to handle up until the specified - * timeout. If an event arrives or a signal is raised, this function will - * return early. - * - * If the parameter completed is not NULL then after obtaining the event - * handling lock this function will return immediately if the integer - * pointed to is not 0. This allows for race free waiting for the completion - * of a specific transfer. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or an all zero - * timeval struct for non-blocking mode - * \param completed pointer to completion integer to check, or NULL - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_handle_events_timeout_completed(libusb_context *ctx, - struct timeval *tv, int *completed) -{ - int r; - struct timeval poll_timeout; - - USBI_GET_CONTEXT(ctx); - r = get_next_timeout(ctx, tv, &poll_timeout); - if (r) { - /* timeout already expired */ - return handle_timeouts(ctx); - } - -retry: - if (libusb_try_lock_events(ctx) == 0) { - if (completed == NULL || !*completed) { - /* we obtained the event lock: do our own event handling */ - usbi_dbg("doing our own event handling"); - r = handle_events(ctx, &poll_timeout); - } - libusb_unlock_events(ctx); - return r; - } - - /* another thread is doing event handling. wait for thread events that - * notify event completion. */ - libusb_lock_event_waiters(ctx); - - if (completed && *completed) - goto already_done; - - if (!libusb_event_handler_active(ctx)) { - /* we hit a race: whoever was event handling earlier finished in the - * time it took us to reach this point. try the cycle again. */ - libusb_unlock_event_waiters(ctx); - usbi_dbg("event handler was active but went away, retrying"); - goto retry; - } - - usbi_dbg("another thread is doing event handling"); - r = libusb_wait_for_event(ctx, &poll_timeout); - -already_done: - libusb_unlock_event_waiters(ctx); - - if (r < 0) - return r; - else if (r == 1) - return handle_timeouts(ctx); - else - return 0; -} - -/** \ingroup libusb_poll - * Handle any pending events - * - * Like libusb_handle_events_timeout_completed(), but without the completed - * parameter, calling this function is equivalent to calling - * libusb_handle_events_timeout_completed() with a NULL completed parameter. - * - * This function is kept primarily for backwards compatibility. - * All new code should call libusb_handle_events_completed() or - * libusb_handle_events_timeout_completed() to avoid race conditions. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or an all zero - * timeval struct for non-blocking mode - * \returns 0 on success, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv) -{ - return libusb_handle_events_timeout_completed(ctx, tv, NULL); -} - -/** \ingroup libusb_poll - * Handle any pending events in blocking mode. There is currently a timeout - * hardcoded at 60 seconds but we plan to make it unlimited in future. For - * finer control over whether this function is blocking or non-blocking, or - * for control over the timeout, use libusb_handle_events_timeout_completed() - * instead. - * - * This function is kept primarily for backwards compatibility. - * All new code should call libusb_handle_events_completed() or - * libusb_handle_events_timeout_completed() to avoid race conditions. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 0 on success, or a LIBUSB_ERROR code on failure - */ -int API_EXPORTED libusb_handle_events(libusb_context *ctx) -{ - struct timeval tv; - tv.tv_sec = 60; - tv.tv_usec = 0; - return libusb_handle_events_timeout_completed(ctx, &tv, NULL); -} - -/** \ingroup libusb_poll - * Handle any pending events in blocking mode. - * - * Like libusb_handle_events(), with the addition of a completed parameter - * to allow for race free waiting for the completion of a specific transfer. - * - * See libusb_handle_events_timeout_completed() for details on the completed - * parameter. - * - * \param ctx the context to operate on, or NULL for the default context - * \param completed pointer to completion integer to check, or NULL - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_handle_events_completed(libusb_context *ctx, - int *completed) -{ - struct timeval tv; - tv.tv_sec = 60; - tv.tv_usec = 0; - return libusb_handle_events_timeout_completed(ctx, &tv, completed); -} - -/** \ingroup libusb_poll - * Handle any pending events by polling file descriptors, without checking if - * any other threads are already doing so. Must be called with the event lock - * held, see libusb_lock_events(). - * - * This function is designed to be called under the situation where you have - * taken the event lock and are calling poll()/select() directly on libusb's - * file descriptors (as opposed to using libusb_handle_events() or similar). - * You detect events on libusb's descriptors, so you then call this function - * with a zero timeout value (while still holding the event lock). - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv the maximum time to block waiting for events, or zero for - * non-blocking mode - * \returns 0 on success, or a LIBUSB_ERROR code on failure - * \ref libusb_mtasync - */ -int API_EXPORTED libusb_handle_events_locked(libusb_context *ctx, - struct timeval *tv) -{ - int r; - struct timeval poll_timeout; - - USBI_GET_CONTEXT(ctx); - r = get_next_timeout(ctx, tv, &poll_timeout); - if (r) { - /* timeout already expired */ - return handle_timeouts(ctx); - } - - return handle_events(ctx, &poll_timeout); -} - -/** \ingroup libusb_poll - * Determines whether your application must apply special timing considerations - * when monitoring libusb's file descriptors. - * - * This function is only useful for applications which retrieve and poll - * libusb's file descriptors in their own main loop (\ref libusb_pollmain). - * - * Ordinarily, libusb's event handler needs to be called into at specific - * moments in time (in addition to times when there is activity on the file - * descriptor set). The usual approach is to use libusb_get_next_timeout() - * to learn about when the next timeout occurs, and to adjust your - * poll()/select() timeout accordingly so that you can make a call into the - * library at that time. - * - * Some platforms supported by libusb do not come with this baggage - any - * events relevant to timing will be represented by activity on the file - * descriptor set, and libusb_get_next_timeout() will always return 0. - * This function allows you to detect whether you are running on such a - * platform. - * - * Since v1.0.5. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns 0 if you must call into libusb at times determined by - * libusb_get_next_timeout(), or 1 if all timeout events are handled internally - * or through regular activity on the file descriptors. - * \ref libusb_pollmain "Polling libusb file descriptors for event handling" - */ -int API_EXPORTED libusb_pollfds_handle_timeouts(libusb_context *ctx) -{ -#if defined(USBI_TIMERFD_AVAILABLE) - USBI_GET_CONTEXT(ctx); - return usbi_using_timerfd(ctx); -#else - UNUSED(ctx); - return 0; -#endif -} - -/** \ingroup libusb_poll - * Determine the next internal timeout that libusb needs to handle. You only - * need to use this function if you are calling poll() or select() or similar - * on libusb's file descriptors yourself - you do not need to use it if you - * are calling libusb_handle_events() or a variant directly. - * - * You should call this function in your main loop in order to determine how - * long to wait for select() or poll() to return results. libusb needs to be - * called into at this timeout, so you should use it as an upper bound on - * your select() or poll() call. - * - * When the timeout has expired, call into libusb_handle_events_timeout() - * (perhaps in non-blocking mode) so that libusb can handle the timeout. - * - * This function may return 1 (success) and an all-zero timeval. If this is - * the case, it indicates that libusb has a timeout that has already expired - * so you should call libusb_handle_events_timeout() or similar immediately. - * A return code of 0 indicates that there are no pending timeouts. - * - * On some platforms, this function will always returns 0 (no pending - * timeouts). See \ref polltime. - * - * \param ctx the context to operate on, or NULL for the default context - * \param tv output location for a relative time against the current - * clock in which libusb must be called into in order to process timeout events - * \returns 0 if there are no pending timeouts, 1 if a timeout was returned, - * or LIBUSB_ERROR_OTHER on failure - */ -int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx, - struct timeval *tv) -{ - struct usbi_transfer *transfer; - struct timespec cur_ts; - struct timeval cur_tv; - struct timeval next_timeout = { 0, 0 }; - int r; - - USBI_GET_CONTEXT(ctx); - if (usbi_using_timerfd(ctx)) - return 0; - - usbi_mutex_lock(&ctx->flying_transfers_lock); - if (list_empty(&ctx->flying_transfers)) { - usbi_mutex_unlock(&ctx->flying_transfers_lock); - usbi_dbg("no URBs, no timeout!"); - return 0; - } - - /* find next transfer which hasn't already been processed as timed out */ - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - if (transfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT)) - continue; - - /* if we've reached transfers of infinte timeout, we're done looking */ - if (!timerisset(&transfer->timeout)) - break; - - next_timeout = transfer->timeout; - break; - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (!timerisset(&next_timeout)) { - usbi_dbg("no URB with timeout or all handled by OS; no timeout!"); - return 0; - } - - r = usbi_backend->clock_gettime(USBI_CLOCK_MONOTONIC, &cur_ts); - if (r < 0) { - usbi_err(ctx, "failed to read monotonic clock, errno=%d", errno); - return 0; - } - TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts); - - if (!timercmp(&cur_tv, &next_timeout, <)) { - usbi_dbg("first timeout already expired"); - timerclear(tv); - } else { - timersub(&next_timeout, &cur_tv, tv); - usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec); - } - - return 1; -} - -/** \ingroup libusb_poll - * Register notification functions for file descriptor additions/removals. - * These functions will be invoked for every new or removed file descriptor - * that libusb uses as an event source. - * - * To remove notifiers, pass NULL values for the function pointers. - * - * Note that file descriptors may have been added even before you register - * these notifiers (e.g. at libusb_init() time). - * - * Additionally, note that the removal notifier may be called during - * libusb_exit() (e.g. when it is closing file descriptors that were opened - * and added to the poll set at libusb_init() time). If you don't want this, - * remove the notifiers immediately before calling libusb_exit(). - * - * \param ctx the context to operate on, or NULL for the default context - * \param added_cb pointer to function for addition notifications - * \param removed_cb pointer to function for removal notifications - * \param user_data User data to be passed back to callbacks (useful for - * passing context information) - */ -void API_EXPORTED libusb_set_pollfd_notifiers(libusb_context *ctx, - libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, - void *user_data) -{ - USBI_GET_CONTEXT(ctx); - ctx->fd_added_cb = added_cb; - ctx->fd_removed_cb = removed_cb; - ctx->fd_cb_user_data = user_data; -} - -/* - * Interrupt the iteration of the event handling thread, so that it picks - * up the fd change. Callers of this function must hold the event_data_lock. - */ -static void usbi_fd_notification(struct libusb_context *ctx) -{ - int pending_events; - - /* Record that there is a new poll fd. - * Only signal an event if there are no prior pending events. */ - pending_events = usbi_pending_events(ctx); - ctx->event_flags |= USBI_EVENT_POLLFDS_MODIFIED; - if (!pending_events) - usbi_signal_event(ctx); -} - -/* Add a file descriptor to the list of file descriptors to be monitored. - * events should be specified as a bitmask of events passed to poll(), e.g. - * POLLIN and/or POLLOUT. */ -int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events) -{ - struct usbi_pollfd *ipollfd = malloc(sizeof(*ipollfd)); - if (!ipollfd) - return LIBUSB_ERROR_NO_MEM; - - usbi_dbg("add fd %d events %d", fd, events); - ipollfd->pollfd.fd = fd; - ipollfd->pollfd.events = events; - usbi_mutex_lock(&ctx->event_data_lock); - list_add_tail(&ipollfd->list, &ctx->ipollfds); - ctx->pollfds_cnt++; - usbi_fd_notification(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - - if (ctx->fd_added_cb) - ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data); - return 0; -} - -/* Remove a file descriptor from the list of file descriptors to be polled. */ -void usbi_remove_pollfd(struct libusb_context *ctx, int fd) -{ - struct usbi_pollfd *ipollfd; - int found = 0; - - usbi_dbg("remove fd %d", fd); - usbi_mutex_lock(&ctx->event_data_lock); - list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) - if (ipollfd->pollfd.fd == fd) { - found = 1; - break; - } - - if (!found) { - usbi_dbg("couldn't find fd %d to remove", fd); - usbi_mutex_unlock(&ctx->event_data_lock); - return; - } - - list_del(&ipollfd->list); - ctx->pollfds_cnt--; - usbi_fd_notification(ctx); - usbi_mutex_unlock(&ctx->event_data_lock); - free(ipollfd); - if (ctx->fd_removed_cb) - ctx->fd_removed_cb(fd, ctx->fd_cb_user_data); -} - -/** \ingroup libusb_poll - * Retrieve a list of file descriptors that should be polled by your main loop - * as libusb event sources. - * - * The returned list is NULL-terminated and should be freed with libusb_free_pollfds() - * when done. The actual list contents must not be touched. - * - * As file descriptors are a Unix-specific concept, this function is not - * available on Windows and will always return NULL. - * - * \param ctx the context to operate on, or NULL for the default context - * \returns a NULL-terminated list of libusb_pollfd structures - * \returns NULL on error - * \returns NULL on platforms where the functionality is not available - */ -DEFAULT_VISIBILITY -const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( - libusb_context *ctx) -{ -#ifndef OS_WINDOWS - struct libusb_pollfd **ret = NULL; - struct usbi_pollfd *ipollfd; - size_t i = 0; - USBI_GET_CONTEXT(ctx); - - usbi_mutex_lock(&ctx->event_data_lock); - - ret = calloc(ctx->pollfds_cnt + 1, sizeof(struct libusb_pollfd *)); - if (!ret) - goto out; - - list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) - ret[i++] = (struct libusb_pollfd *) ipollfd; - ret[ctx->pollfds_cnt] = NULL; - -out: - usbi_mutex_unlock(&ctx->event_data_lock); - return (const struct libusb_pollfd **) ret; -#else - usbi_err(ctx, "external polling of libusb's internal descriptors "\ - "is not yet supported on Windows platforms"); - return NULL; -#endif -} - -/** \ingroup libusb_poll - * Free a list of libusb_pollfd structures. This should be called for all - * pollfd lists allocated with libusb_get_pollfds(). - * - * Since version 1.0.20, \ref LIBUSB_API_VERSION >= 0x01000104 - * - * It is legal to call this function with a NULL pollfd list. In this case, - * the function will simply return safely. - * - * \param pollfds the list of libusb_pollfd structures to free - */ -void API_EXPORTED libusb_free_pollfds(const struct libusb_pollfd **pollfds) -{ - if (!pollfds) - return; - - free((void *)pollfds); -} - -/* Backends may call this from handle_events to report disconnection of a - * device. This function ensures transfers get cancelled appropriately. - * Callers of this function must hold the events_lock. - */ -void usbi_handle_disconnect(struct libusb_device_handle *dev_handle) -{ - struct usbi_transfer *cur; - struct usbi_transfer *to_cancel; - - usbi_dbg("device %d.%d", - dev_handle->dev->bus_number, dev_handle->dev->device_address); - - /* terminate all pending transfers with the LIBUSB_TRANSFER_NO_DEVICE - * status code. - * - * when we find a transfer for this device on the list, there are two - * possible scenarios: - * 1. the transfer is currently in-flight, in which case we terminate the - * transfer here - * 2. the transfer has been added to the flying transfer list by - * libusb_submit_transfer, has failed to submit and - * libusb_submit_transfer is waiting for us to release the - * flying_transfers_lock to remove it, so we ignore it - */ - - while (1) { - to_cancel = NULL; - usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); - list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer) - if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) { - usbi_mutex_lock(&cur->lock); - if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT) - to_cancel = cur; - usbi_mutex_unlock(&cur->lock); - - if (to_cancel) - break; - } - usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock); - - if (!to_cancel) - break; - - usbi_dbg("cancelling transfer %p from disconnect", - USBI_TRANSFER_TO_LIBUSB_TRANSFER(to_cancel)); - - usbi_mutex_lock(&to_cancel->lock); - usbi_backend->clear_transfer_priv(to_cancel); - usbi_mutex_unlock(&to_cancel->lock); - usbi_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE); - } - -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/libusb.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/libusb.h deleted file mode 100644 index c562690f9af..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/libusb.h +++ /dev/null @@ -1,2008 +0,0 @@ -/* - * Public libusb header file - * Copyright © 2001 Johannes Erdfelt - * Copyright © 2007-2008 Daniel Drake - * Copyright © 2012 Pete Batard - * Copyright © 2012 Nathan Hjelm - * For more information, please visit: http://libusb.info - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_H -#define LIBUSB_H - -#ifdef _MSC_VER -/* on MS environments, the inline keyword is available in C++ only */ -#if !defined(__cplusplus) -#define inline __inline -#endif -/* ssize_t is also not available (copy/paste from MinGW) */ -#ifndef _SSIZE_T_DEFINED -#define _SSIZE_T_DEFINED -#undef ssize_t -#ifdef _WIN64 - typedef __int64 ssize_t; -#else - typedef int ssize_t; -#endif /* _WIN64 */ -#endif /* _SSIZE_T_DEFINED */ -#endif /* _MSC_VER */ - -/* stdint.h is not available on older MSVC */ -#if defined(_MSC_VER) && (_MSC_VER < 1600) && (!defined(_STDINT)) && (!defined(_STDINT_H)) -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -#else -#include -#endif - -#if !defined(_WIN32_WCE) -#include -#endif - -#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) -#include -#endif - -#include -#include - -/* 'interface' might be defined as a macro on Windows, so we need to - * undefine it so as not to break the current libusb API, because - * libusb_config_descriptor has an 'interface' member - * As this can be problematic if you include windows.h after libusb.h - * in your sources, we force windows.h to be included first. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -#include -#if defined(interface) -#undef interface -#endif -#if !defined(__CYGWIN__) -#include -#endif -#endif - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -#define LIBUSB_DEPRECATED_FOR(f) \ - __attribute__((deprecated("Use " #f " instead"))) -#else -#define LIBUSB_DEPRECATED_FOR(f) -#endif /* __GNUC__ */ - -/** \def LIBUSB_CALL - * \ingroup libusb_misc - * libusb's Windows calling convention. - * - * Under Windows, the selection of available compilers and configurations - * means that, unlike other platforms, there is not one true calling - * convention (calling convention: the manner in which parameters are - * passed to functions in the generated assembly code). - * - * Matching the Windows API itself, libusb uses the WINAPI convention (which - * translates to the stdcall convention) and guarantees that the - * library is compiled in this way. The public header file also includes - * appropriate annotations so that your own software will use the right - * convention, even if another convention is being used by default within - * your codebase. - * - * The one consideration that you must apply in your software is to mark - * all functions which you use as libusb callbacks with this LIBUSB_CALL - * annotation, so that they too get compiled for the correct calling - * convention. - * - * On non-Windows operating systems, this macro is defined as nothing. This - * means that you can apply it to your code without worrying about - * cross-platform compatibility. - */ -/* LIBUSB_CALL must be defined on both definition and declaration of libusb - * functions. You'd think that declaration would be enough, but cygwin will - * complain about conflicting types unless both are marked this way. - * The placement of this macro is important too; it must appear after the - * return type, before the function name. See internal documentation for - * API_EXPORTED. - */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -#define LIBUSB_CALL WINAPI -#else -#define LIBUSB_CALL -#endif - -/** \def LIBUSB_API_VERSION - * \ingroup libusb_misc - * libusb's API version. - * - * Since version 1.0.13, to help with feature detection, libusb defines - * a LIBUSB_API_VERSION macro that gets increased every time there is a - * significant change to the API, such as the introduction of a new call, - * the definition of a new macro/enum member, or any other element that - * libusb applications may want to detect at compilation time. - * - * The macro is typically used in an application as follows: - * \code - * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234) - * // Use one of the newer features from the libusb API - * #endif - * \endcode - * - * Internally, LIBUSB_API_VERSION is defined as follows: - * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) - */ -#define LIBUSB_API_VERSION 0x01000105 - -/* The following is kept for compatibility, but will be deprecated in the future */ -#define LIBUSBX_API_VERSION LIBUSB_API_VERSION - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \ingroup libusb_misc - * Convert a 16-bit value from host-endian to little-endian format. On - * little endian systems, this function does nothing. On big endian systems, - * the bytes are swapped. - * \param x the host-endian value to convert - * \returns the value in little-endian byte order - */ -static inline uint16_t libusb_cpu_to_le16(const uint16_t x) -{ - union { - uint8_t b8[2]; - uint16_t b16; - } _tmp; - _tmp.b8[1] = (uint8_t) (x >> 8); - _tmp.b8[0] = (uint8_t) (x & 0xff); - return _tmp.b16; -} - -/** \def libusb_le16_to_cpu - * \ingroup libusb_misc - * Convert a 16-bit value from little-endian to host-endian format. On - * little endian systems, this function does nothing. On big endian systems, - * the bytes are swapped. - * \param x the little-endian value to convert - * \returns the value in host-endian byte order - */ -#define libusb_le16_to_cpu libusb_cpu_to_le16 - -/* standard USB stuff */ - -/** \ingroup libusb_desc - * Device and/or Interface Class codes */ -enum libusb_class_code { - /** In the context of a \ref libusb_device_descriptor "device descriptor", - * this bDeviceClass value indicates that each interface specifies its - * own class information and all interfaces operate independently. - */ - LIBUSB_CLASS_PER_INTERFACE = 0, - - /** Audio class */ - LIBUSB_CLASS_AUDIO = 1, - - /** Communications class */ - LIBUSB_CLASS_COMM = 2, - - /** Human Interface Device class */ - LIBUSB_CLASS_HID = 3, - - /** Physical */ - LIBUSB_CLASS_PHYSICAL = 5, - - /** Printer class */ - LIBUSB_CLASS_PRINTER = 7, - - /** Image class */ - LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */ - LIBUSB_CLASS_IMAGE = 6, - - /** Mass storage class */ - LIBUSB_CLASS_MASS_STORAGE = 8, - - /** Hub class */ - LIBUSB_CLASS_HUB = 9, - - /** Data class */ - LIBUSB_CLASS_DATA = 10, - - /** Smart Card */ - LIBUSB_CLASS_SMART_CARD = 0x0b, - - /** Content Security */ - LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, - - /** Video */ - LIBUSB_CLASS_VIDEO = 0x0e, - - /** Personal Healthcare */ - LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, - - /** Diagnostic Device */ - LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, - - /** Wireless class */ - LIBUSB_CLASS_WIRELESS = 0xe0, - - /** Application class */ - LIBUSB_CLASS_APPLICATION = 0xfe, - - /** Class is vendor-specific */ - LIBUSB_CLASS_VENDOR_SPEC = 0xff -}; - -/** \ingroup libusb_desc - * Descriptor types as defined by the USB specification. */ -enum libusb_descriptor_type { - /** Device descriptor. See libusb_device_descriptor. */ - LIBUSB_DT_DEVICE = 0x01, - - /** Configuration descriptor. See libusb_config_descriptor. */ - LIBUSB_DT_CONFIG = 0x02, - - /** String descriptor */ - LIBUSB_DT_STRING = 0x03, - - /** Interface descriptor. See libusb_interface_descriptor. */ - LIBUSB_DT_INTERFACE = 0x04, - - /** Endpoint descriptor. See libusb_endpoint_descriptor. */ - LIBUSB_DT_ENDPOINT = 0x05, - - /** BOS descriptor */ - LIBUSB_DT_BOS = 0x0f, - - /** Device Capability descriptor */ - LIBUSB_DT_DEVICE_CAPABILITY = 0x10, - - /** HID descriptor */ - LIBUSB_DT_HID = 0x21, - - /** HID report descriptor */ - LIBUSB_DT_REPORT = 0x22, - - /** Physical descriptor */ - LIBUSB_DT_PHYSICAL = 0x23, - - /** Hub descriptor */ - LIBUSB_DT_HUB = 0x29, - - /** SuperSpeed Hub descriptor */ - LIBUSB_DT_SUPERSPEED_HUB = 0x2a, - - /** SuperSpeed Endpoint Companion descriptor */ - LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30 -}; - -/* Descriptor sizes per descriptor type */ -#define LIBUSB_DT_DEVICE_SIZE 18 -#define LIBUSB_DT_CONFIG_SIZE 9 -#define LIBUSB_DT_INTERFACE_SIZE 9 -#define LIBUSB_DT_ENDPOINT_SIZE 7 -#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ -#define LIBUSB_DT_HUB_NONVAR_SIZE 7 -#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6 -#define LIBUSB_DT_BOS_SIZE 5 -#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3 - -/* BOS descriptor sizes */ -#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 -#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 -#define LIBUSB_BT_CONTAINER_ID_SIZE 20 - -/* We unwrap the BOS => define its max size */ -#define LIBUSB_DT_BOS_MAX_SIZE ((LIBUSB_DT_BOS_SIZE) +\ - (LIBUSB_BT_USB_2_0_EXTENSION_SIZE) +\ - (LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) +\ - (LIBUSB_BT_CONTAINER_ID_SIZE)) - -#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ -#define LIBUSB_ENDPOINT_DIR_MASK 0x80 - -/** \ingroup libusb_desc - * Endpoint direction. Values for bit 7 of the - * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. - */ -enum libusb_endpoint_direction { - /** In: device-to-host */ - LIBUSB_ENDPOINT_IN = 0x80, - - /** Out: host-to-device */ - LIBUSB_ENDPOINT_OUT = 0x00 -}; - -#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ - -/** \ingroup libusb_desc - * Endpoint transfer type. Values for bits 0:1 of the - * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. - */ -enum libusb_transfer_type { - /** Control endpoint */ - LIBUSB_TRANSFER_TYPE_CONTROL = 0, - - /** Isochronous endpoint */ - LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, - - /** Bulk endpoint */ - LIBUSB_TRANSFER_TYPE_BULK = 2, - - /** Interrupt endpoint */ - LIBUSB_TRANSFER_TYPE_INTERRUPT = 3, - - /** Stream endpoint */ - LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4, -}; - -/** \ingroup libusb_misc - * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ -enum libusb_standard_request { - /** Request status of the specific recipient */ - LIBUSB_REQUEST_GET_STATUS = 0x00, - - /** Clear or disable a specific feature */ - LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, - - /* 0x02 is reserved */ - - /** Set or enable a specific feature */ - LIBUSB_REQUEST_SET_FEATURE = 0x03, - - /* 0x04 is reserved */ - - /** Set device address for all future accesses */ - LIBUSB_REQUEST_SET_ADDRESS = 0x05, - - /** Get the specified descriptor */ - LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, - - /** Used to update existing descriptors or add new descriptors */ - LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, - - /** Get the current device configuration value */ - LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, - - /** Set device configuration */ - LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, - - /** Return the selected alternate setting for the specified interface */ - LIBUSB_REQUEST_GET_INTERFACE = 0x0A, - - /** Select an alternate interface for the specified interface */ - LIBUSB_REQUEST_SET_INTERFACE = 0x0B, - - /** Set then report an endpoint's synchronization frame */ - LIBUSB_REQUEST_SYNCH_FRAME = 0x0C, - - /** Sets both the U1 and U2 Exit Latency */ - LIBUSB_REQUEST_SET_SEL = 0x30, - - /** Delay from the time a host transmits a packet to the time it is - * received by the device. */ - LIBUSB_SET_ISOCH_DELAY = 0x31, -}; - -/** \ingroup libusb_misc - * Request type bits of the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control - * transfers. */ -enum libusb_request_type { - /** Standard */ - LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), - - /** Class */ - LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), - - /** Vendor */ - LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), - - /** Reserved */ - LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) -}; - -/** \ingroup libusb_misc - * Recipient bits of the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control - * transfers. Values 4 through 31 are reserved. */ -enum libusb_request_recipient { - /** Device */ - LIBUSB_RECIPIENT_DEVICE = 0x00, - - /** Interface */ - LIBUSB_RECIPIENT_INTERFACE = 0x01, - - /** Endpoint */ - LIBUSB_RECIPIENT_ENDPOINT = 0x02, - - /** Other */ - LIBUSB_RECIPIENT_OTHER = 0x03, -}; - -#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C - -/** \ingroup libusb_desc - * Synchronization type for isochronous endpoints. Values for bits 2:3 of the - * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in - * libusb_endpoint_descriptor. - */ -enum libusb_iso_sync_type { - /** No synchronization */ - LIBUSB_ISO_SYNC_TYPE_NONE = 0, - - /** Asynchronous */ - LIBUSB_ISO_SYNC_TYPE_ASYNC = 1, - - /** Adaptive */ - LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2, - - /** Synchronous */ - LIBUSB_ISO_SYNC_TYPE_SYNC = 3 -}; - -#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 - -/** \ingroup libusb_desc - * Usage type for isochronous endpoints. Values for bits 4:5 of the - * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in - * libusb_endpoint_descriptor. - */ -enum libusb_iso_usage_type { - /** Data endpoint */ - LIBUSB_ISO_USAGE_TYPE_DATA = 0, - - /** Feedback endpoint */ - LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1, - - /** Implicit feedback Data endpoint */ - LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2, -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB device descriptor. This - * descriptor is documented in section 9.6.1 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_device_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this - * context. */ - uint8_t bDescriptorType; - - /** USB specification release number in binary-coded decimal. A value of - * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ - uint16_t bcdUSB; - - /** USB-IF class code for the device. See \ref libusb_class_code. */ - uint8_t bDeviceClass; - - /** USB-IF subclass code for the device, qualified by the bDeviceClass - * value */ - uint8_t bDeviceSubClass; - - /** USB-IF protocol code for the device, qualified by the bDeviceClass and - * bDeviceSubClass values */ - uint8_t bDeviceProtocol; - - /** Maximum packet size for endpoint 0 */ - uint8_t bMaxPacketSize0; - - /** USB-IF vendor ID */ - uint16_t idVendor; - - /** USB-IF product ID */ - uint16_t idProduct; - - /** Device release number in binary-coded decimal */ - uint16_t bcdDevice; - - /** Index of string descriptor describing manufacturer */ - uint8_t iManufacturer; - - /** Index of string descriptor describing product */ - uint8_t iProduct; - - /** Index of string descriptor containing device serial number */ - uint8_t iSerialNumber; - - /** Number of possible configurations */ - uint8_t bNumConfigurations; -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB endpoint descriptor. This - * descriptor is documented in section 9.6.6 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_endpoint_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in - * this context. */ - uint8_t bDescriptorType; - - /** The address of the endpoint described by this descriptor. Bits 0:3 are - * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, - * see \ref libusb_endpoint_direction. - */ - uint8_t bEndpointAddress; - - /** Attributes which apply to the endpoint when it is configured using - * the bConfigurationValue. Bits 0:1 determine the transfer type and - * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for - * isochronous endpoints and correspond to \ref libusb_iso_sync_type. - * Bits 4:5 are also only used for isochronous endpoints and correspond to - * \ref libusb_iso_usage_type. Bits 6:7 are reserved. - */ - uint8_t bmAttributes; - - /** Maximum packet size this endpoint is capable of sending/receiving. */ - uint16_t wMaxPacketSize; - - /** Interval for polling endpoint for data transfers. */ - uint8_t bInterval; - - /** For audio devices only: the rate at which synchronization feedback - * is provided. */ - uint8_t bRefresh; - - /** For audio devices only: the address if the synch endpoint */ - uint8_t bSynchAddress; - - /** Extra descriptors. If libusb encounters unknown endpoint descriptors, - * it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB interface descriptor. This - * descriptor is documented in section 9.6.5 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_interface_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE - * in this context. */ - uint8_t bDescriptorType; - - /** Number of this interface */ - uint8_t bInterfaceNumber; - - /** Value used to select this alternate setting for this interface */ - uint8_t bAlternateSetting; - - /** Number of endpoints used by this interface (excluding the control - * endpoint). */ - uint8_t bNumEndpoints; - - /** USB-IF class code for this interface. See \ref libusb_class_code. */ - uint8_t bInterfaceClass; - - /** USB-IF subclass code for this interface, qualified by the - * bInterfaceClass value */ - uint8_t bInterfaceSubClass; - - /** USB-IF protocol code for this interface, qualified by the - * bInterfaceClass and bInterfaceSubClass values */ - uint8_t bInterfaceProtocol; - - /** Index of string descriptor describing this interface */ - uint8_t iInterface; - - /** Array of endpoint descriptors. This length of this array is determined - * by the bNumEndpoints field. */ - const struct libusb_endpoint_descriptor *endpoint; - - /** Extra descriptors. If libusb encounters unknown interface descriptors, - * it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup libusb_desc - * A collection of alternate settings for a particular USB interface. - */ -struct libusb_interface { - /** Array of interface descriptors. The length of this array is determined - * by the num_altsetting field. */ - const struct libusb_interface_descriptor *altsetting; - - /** The number of alternate settings that belong to this interface */ - int num_altsetting; -}; - -/** \ingroup libusb_desc - * A structure representing the standard USB configuration descriptor. This - * descriptor is documented in section 9.6.3 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_config_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG - * in this context. */ - uint8_t bDescriptorType; - - /** Total length of data returned for this configuration */ - uint16_t wTotalLength; - - /** Number of interfaces supported by this configuration */ - uint8_t bNumInterfaces; - - /** Identifier value for this configuration */ - uint8_t bConfigurationValue; - - /** Index of string descriptor describing this configuration */ - uint8_t iConfiguration; - - /** Configuration characteristics */ - uint8_t bmAttributes; - - /** Maximum power consumption of the USB device from this bus in this - * configuration when the device is fully operation. Expressed in units - * of 2 mA when the device is operating in high-speed mode and in units - * of 8 mA when the device is operating in super-speed mode. */ - uint8_t MaxPower; - - /** Array of interfaces supported by this configuration. The length of - * this array is determined by the bNumInterfaces field. */ - const struct libusb_interface *interface; - - /** Extra descriptors. If libusb encounters unknown configuration - * descriptors, it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup libusb_desc - * A structure representing the superspeed endpoint companion - * descriptor. This descriptor is documented in section 9.6.7 of - * the USB 3.0 specification. All multiple-byte fields are represented in - * host-endian format. - */ -struct libusb_ss_endpoint_companion_descriptor { - - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in - * this context. */ - uint8_t bDescriptorType; - - - /** The maximum number of packets the endpoint can send or - * receive as part of a burst. */ - uint8_t bMaxBurst; - - /** In bulk EP: bits 4:0 represents the maximum number of - * streams the EP supports. In isochronous EP: bits 1:0 - * represents the Mult - a zero based value that determines - * the maximum number of packets within a service interval */ - uint8_t bmAttributes; - - /** The total number of bytes this EP will transfer every - * service interval. valid only for periodic EPs. */ - uint16_t wBytesPerInterval; -}; - -/** \ingroup libusb_desc - * A generic representation of a BOS Device Capability descriptor. It is - * advised to check bDevCapabilityType and call the matching - * libusb_get_*_descriptor function to get a structure fully matching the type. - */ -struct libusb_bos_dev_capability_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - /** Device Capability type */ - uint8_t bDevCapabilityType; - /** Device Capability data (bLength - 3 bytes) */ - uint8_t dev_capability_data -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; -}; - -/** \ingroup libusb_desc - * A structure representing the Binary Device Object Store (BOS) descriptor. - * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_bos_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS - * in this context. */ - uint8_t bDescriptorType; - - /** Length of this descriptor and all of its sub descriptors */ - uint16_t wTotalLength; - - /** The number of separate device capability descriptors in - * the BOS */ - uint8_t bNumDeviceCaps; - - /** bNumDeviceCap Device Capability Descriptors */ - struct libusb_bos_dev_capability_descriptor *dev_capability -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; -}; - -/** \ingroup libusb_desc - * A structure representing the USB 2.0 Extension descriptor - * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_usb_2_0_extension_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - - /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION - * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ - uint8_t bDevCapabilityType; - - /** Bitmap encoding of supported device level features. - * A value of one in a bit location indicates a feature is - * supported; a value of zero indicates it is not supported. - * See \ref libusb_usb_2_0_extension_attributes. */ - uint32_t bmAttributes; -}; - -/** \ingroup libusb_desc - * A structure representing the SuperSpeed USB Device Capability descriptor - * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_ss_usb_device_capability_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - - /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ - uint8_t bDevCapabilityType; - - /** Bitmap encoding of supported device level features. - * A value of one in a bit location indicates a feature is - * supported; a value of zero indicates it is not supported. - * See \ref libusb_ss_usb_device_capability_attributes. */ - uint8_t bmAttributes; - - /** Bitmap encoding of the speed supported by this device when - * operating in SuperSpeed mode. See \ref libusb_supported_speed. */ - uint16_t wSpeedSupported; - - /** The lowest speed at which all the functionality supported - * by the device is available to the user. For example if the - * device supports all its functionality when connected at - * full speed and above then it sets this value to 1. */ - uint8_t bFunctionalitySupport; - - /** U1 Device Exit Latency. */ - uint8_t bU1DevExitLat; - - /** U2 Device Exit Latency. */ - uint16_t bU2DevExitLat; -}; - -/** \ingroup libusb_desc - * A structure representing the Container ID descriptor. - * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. - * All multiple-byte fields, except UUIDs, are represented in host-endian format. - */ -struct libusb_container_id_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ - uint8_t bDescriptorType; - - /** Capability type. Will have value - * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID - * LIBUSB_BT_CONTAINER_ID in this context. */ - uint8_t bDevCapabilityType; - - /** Reserved field */ - uint8_t bReserved; - - /** 128 bit UUID */ - uint8_t ContainerID[16]; -}; - -/** \ingroup libusb_asyncio - * Setup packet for control transfers. */ -struct libusb_control_setup { - /** Request type. Bits 0:4 determine recipient, see - * \ref libusb_request_recipient. Bits 5:6 determine type, see - * \ref libusb_request_type. Bit 7 determines data transfer direction, see - * \ref libusb_endpoint_direction. - */ - uint8_t bmRequestType; - - /** Request. If the type bits of bmRequestType are equal to - * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD - * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to - * \ref libusb_standard_request. For other cases, use of this field is - * application-specific. */ - uint8_t bRequest; - - /** Value. Varies according to request */ - uint16_t wValue; - - /** Index. Varies according to request, typically used to pass an index - * or offset */ - uint16_t wIndex; - - /** Number of bytes to transfer */ - uint16_t wLength; -}; - -#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) - -/* libusb */ - -struct libusb_context; -struct libusb_device; -struct libusb_device_handle; - -/** \ingroup libusb_lib - * Structure providing the version of the libusb runtime - */ -struct libusb_version { - /** Library major version. */ - const uint16_t major; - - /** Library minor version. */ - const uint16_t minor; - - /** Library micro version. */ - const uint16_t micro; - - /** Library nano version. */ - const uint16_t nano; - - /** Library release candidate suffix string, e.g. "-rc4". */ - const char *rc; - - /** For ABI compatibility only. */ - const char* describe; -}; - -/** \ingroup libusb_lib - * Structure representing a libusb session. The concept of individual libusb - * sessions allows for your program to use two libraries (or dynamically - * load two modules) which both independently use libusb. This will prevent - * interference between the individual libusb users - for example - * libusb_set_debug() will not affect the other user of the library, and - * libusb_exit() will not destroy resources that the other user is still - * using. - * - * Sessions are created by libusb_init() and destroyed through libusb_exit(). - * If your application is guaranteed to only ever include a single libusb - * user (i.e. you), you do not have to worry about contexts: pass NULL in - * every function call where a context is required. The default context - * will be used. - * - * For more information, see \ref libusb_contexts. - */ -typedef struct libusb_context libusb_context; - -/** \ingroup libusb_dev - * Structure representing a USB device detected on the system. This is an - * opaque type for which you are only ever provided with a pointer, usually - * originating from libusb_get_device_list(). - * - * Certain operations can be performed on a device, but in order to do any - * I/O you will have to first obtain a device handle using libusb_open(). - * - * Devices are reference counted with libusb_ref_device() and - * libusb_unref_device(), and are freed when the reference count reaches 0. - * New devices presented by libusb_get_device_list() have a reference count of - * 1, and libusb_free_device_list() can optionally decrease the reference count - * on all devices in the list. libusb_open() adds another reference which is - * later destroyed by libusb_close(). - */ -typedef struct libusb_device libusb_device; - - -/** \ingroup libusb_dev - * Structure representing a handle on a USB device. This is an opaque type for - * which you are only ever provided with a pointer, usually originating from - * libusb_open(). - * - * A device handle is used to perform I/O and other operations. When finished - * with a device handle, you should call libusb_close(). - */ -typedef struct libusb_device_handle libusb_device_handle; - -/** \ingroup libusb_dev - * Speed codes. Indicates the speed at which the device is operating. - */ -enum libusb_speed { - /** The OS doesn't report or know the device speed. */ - LIBUSB_SPEED_UNKNOWN = 0, - - /** The device is operating at low speed (1.5MBit/s). */ - LIBUSB_SPEED_LOW = 1, - - /** The device is operating at full speed (12MBit/s). */ - LIBUSB_SPEED_FULL = 2, - - /** The device is operating at high speed (480MBit/s). */ - LIBUSB_SPEED_HIGH = 3, - - /** The device is operating at super speed (5000MBit/s). */ - LIBUSB_SPEED_SUPER = 4, -}; - -/** \ingroup libusb_dev - * Supported speeds (wSpeedSupported) bitfield. Indicates what - * speeds the device supports. - */ -enum libusb_supported_speed { - /** Low speed operation supported (1.5MBit/s). */ - LIBUSB_LOW_SPEED_OPERATION = 1, - - /** Full speed operation supported (12MBit/s). */ - LIBUSB_FULL_SPEED_OPERATION = 2, - - /** High speed operation supported (480MBit/s). */ - LIBUSB_HIGH_SPEED_OPERATION = 4, - - /** Superspeed operation supported (5000MBit/s). */ - LIBUSB_SUPER_SPEED_OPERATION = 8, -}; - -/** \ingroup libusb_dev - * Masks for the bits of the - * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field - * of the USB 2.0 Extension descriptor. - */ -enum libusb_usb_2_0_extension_attributes { - /** Supports Link Power Management (LPM) */ - LIBUSB_BM_LPM_SUPPORT = 2, -}; - -/** \ingroup libusb_dev - * Masks for the bits of the - * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field - * field of the SuperSpeed USB Device Capability descriptor. - */ -enum libusb_ss_usb_device_capability_attributes { - /** Supports Latency Tolerance Messages (LTM) */ - LIBUSB_BM_LTM_SUPPORT = 2, -}; - -/** \ingroup libusb_dev - * USB capability types - */ -enum libusb_bos_type { - /** Wireless USB device capability */ - LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1, - - /** USB 2.0 extensions */ - LIBUSB_BT_USB_2_0_EXTENSION = 2, - - /** SuperSpeed USB device capability */ - LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3, - - /** Container ID type */ - LIBUSB_BT_CONTAINER_ID = 4, -}; - -/** \ingroup libusb_misc - * Error codes. Most libusb functions return 0 on success or one of these - * codes on failure. - * You can call libusb_error_name() to retrieve a string representation of an - * error code or libusb_strerror() to get an end-user suitable description of - * an error code. - */ -enum libusb_error { - /** Success (no error) */ - LIBUSB_SUCCESS = 0, - - /** Input/output error */ - LIBUSB_ERROR_IO = -1, - - /** Invalid parameter */ - LIBUSB_ERROR_INVALID_PARAM = -2, - - /** Access denied (insufficient permissions) */ - LIBUSB_ERROR_ACCESS = -3, - - /** No such device (it may have been disconnected) */ - LIBUSB_ERROR_NO_DEVICE = -4, - - /** Entity not found */ - LIBUSB_ERROR_NOT_FOUND = -5, - - /** Resource busy */ - LIBUSB_ERROR_BUSY = -6, - - /** Operation timed out */ - LIBUSB_ERROR_TIMEOUT = -7, - - /** Overflow */ - LIBUSB_ERROR_OVERFLOW = -8, - - /** Pipe error */ - LIBUSB_ERROR_PIPE = -9, - - /** System call interrupted (perhaps due to signal) */ - LIBUSB_ERROR_INTERRUPTED = -10, - - /** Insufficient memory */ - LIBUSB_ERROR_NO_MEM = -11, - - /** Operation not supported or unimplemented on this platform */ - LIBUSB_ERROR_NOT_SUPPORTED = -12, - - /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the - message strings in strerror.c when adding new error codes here. */ - - /** Other error */ - LIBUSB_ERROR_OTHER = -99, -}; - -/* Total number of error codes in enum libusb_error */ -#define LIBUSB_ERROR_COUNT 14 - -/** \ingroup libusb_asyncio - * Transfer status codes */ -enum libusb_transfer_status { - /** Transfer completed without error. Note that this does not indicate - * that the entire amount of requested data was transferred. */ - LIBUSB_TRANSFER_COMPLETED, - - /** Transfer failed */ - LIBUSB_TRANSFER_ERROR, - - /** Transfer timed out */ - LIBUSB_TRANSFER_TIMED_OUT, - - /** Transfer was cancelled */ - LIBUSB_TRANSFER_CANCELLED, - - /** For bulk/interrupt endpoints: halt condition detected (endpoint - * stalled). For control endpoints: control request not supported. */ - LIBUSB_TRANSFER_STALL, - - /** Device was disconnected */ - LIBUSB_TRANSFER_NO_DEVICE, - - /** Device sent more data than requested */ - LIBUSB_TRANSFER_OVERFLOW, - - /* NB! Remember to update libusb_error_name() - when adding new status codes here. */ -}; - -/** \ingroup libusb_asyncio - * libusb_transfer.flags values */ -enum libusb_transfer_flags { - /** Report short frames as errors */ - LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, - - /** Automatically free() transfer buffer during libusb_free_transfer(). - * Note that buffers allocated with libusb_dev_mem_alloc() should not - * be attempted freed in this way, since free() is not an appropriate - * way to release such memory. */ - LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, - - /** Automatically call libusb_free_transfer() after callback returns. - * If this flag is set, it is illegal to call libusb_free_transfer() - * from your transfer callback, as this will result in a double-free - * when this flag is acted upon. */ - LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2, - - /** Terminate transfers that are a multiple of the endpoint's - * wMaxPacketSize with an extra zero length packet. This is useful - * when a device protocol mandates that each logical request is - * terminated by an incomplete packet (i.e. the logical requests are - * not separated by other means). - * - * This flag only affects host-to-device transfers to bulk and interrupt - * endpoints. In other situations, it is ignored. - * - * This flag only affects transfers with a length that is a multiple of - * the endpoint's wMaxPacketSize. On transfers of other lengths, this - * flag has no effect. Therefore, if you are working with a device that - * needs a ZLP whenever the end of the logical request falls on a packet - * boundary, then it is sensible to set this flag on every - * transfer (you do not have to worry about only setting it on transfers - * that end on the boundary). - * - * This flag is currently only supported on Linux. - * On other systems, libusb_submit_transfer() will return - * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. - * - * Available since libusb-1.0.9. - */ - LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 << 3, -}; - -/** \ingroup libusb_asyncio - * Isochronous packet descriptor. */ -struct libusb_iso_packet_descriptor { - /** Length of data to request in this packet */ - unsigned int length; - - /** Amount of data that was actually transferred */ - unsigned int actual_length; - - /** Status code for this packet */ - enum libusb_transfer_status status; -}; - -struct libusb_transfer; - -/** \ingroup libusb_asyncio - * Asynchronous transfer callback function type. When submitting asynchronous - * transfers, you pass a pointer to a callback function of this type via the - * \ref libusb_transfer::callback "callback" member of the libusb_transfer - * structure. libusb will call this function later, when the transfer has - * completed or failed. See \ref libusb_asyncio for more information. - * \param transfer The libusb_transfer struct the callback function is being - * notified about. - */ -typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); - -/** \ingroup libusb_asyncio - * The generic USB transfer structure. The user populates this structure and - * then submits it in order to request a transfer. After the transfer has - * completed, the library populates the transfer with the results and passes - * it back to the user. - */ -struct libusb_transfer { - /** Handle of the device that this transfer will be submitted to */ - libusb_device_handle *dev_handle; - - /** A bitwise OR combination of \ref libusb_transfer_flags. */ - uint8_t flags; - - /** Address of the endpoint where this transfer will be sent. */ - unsigned char endpoint; - - /** Type of the endpoint from \ref libusb_transfer_type */ - unsigned char type; - - /** Timeout for this transfer in milliseconds. A value of 0 indicates no - * timeout. */ - unsigned int timeout; - - /** The status of the transfer. Read-only, and only for use within - * transfer callback function. - * - * If this is an isochronous transfer, this field may read COMPLETED even - * if there were errors in the frames. Use the - * \ref libusb_iso_packet_descriptor::status "status" field in each packet - * to determine if errors occurred. */ - enum libusb_transfer_status status; - - /** Length of the data buffer */ - int length; - - /** Actual length of data that was transferred. Read-only, and only for - * use within transfer callback function. Not valid for isochronous - * endpoint transfers. */ - int actual_length; - - /** Callback function. This will be invoked when the transfer completes, - * fails, or is cancelled. */ - libusb_transfer_cb_fn callback; - - /** User context data to pass to the callback function. */ - void *user_data; - - /** Data buffer */ - unsigned char *buffer; - - /** Number of isochronous packets. Only used for I/O with isochronous - * endpoints. */ - int num_iso_packets; - - /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; -}; - -/** \ingroup libusb_misc - * Capabilities supported by an instance of libusb on the current running - * platform. Test if the loaded library supports a given capability by calling - * \ref libusb_has_capability(). - */ -enum libusb_capability { - /** The libusb_has_capability() API is available. */ - LIBUSB_CAP_HAS_CAPABILITY = 0x0000, - /** Hotplug support is available on this platform. */ - LIBUSB_CAP_HAS_HOTPLUG = 0x0001, - /** The library can access HID devices without requiring user intervention. - * Note that before being able to actually access an HID device, you may - * still have to call additional libusb functions such as - * \ref libusb_detach_kernel_driver(). */ - LIBUSB_CAP_HAS_HID_ACCESS = 0x0100, - /** The library supports detaching of the default USB driver, using - * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ - LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101 -}; - -/** \ingroup libusb_lib - * Log message levels. - * - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) - * - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning - * and error messages are printed to stderr - * - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, - * warnings and errors to stderr - */ -enum libusb_log_level { - LIBUSB_LOG_LEVEL_NONE = 0, - LIBUSB_LOG_LEVEL_ERROR, - LIBUSB_LOG_LEVEL_WARNING, - LIBUSB_LOG_LEVEL_INFO, - LIBUSB_LOG_LEVEL_DEBUG, -}; - -int LIBUSB_CALL libusb_init(libusb_context **ctx); -void LIBUSB_CALL libusb_exit(libusb_context *ctx); -void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); -const struct libusb_version * LIBUSB_CALL libusb_get_version(void); -int LIBUSB_CALL libusb_has_capability(uint32_t capability); -const char * LIBUSB_CALL libusb_error_name(int errcode); -int LIBUSB_CALL libusb_setlocale(const char *locale); -const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode); - -ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, - libusb_device ***list); -void LIBUSB_CALL libusb_free_device_list(libusb_device **list, - int unref_devices); -libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); -void LIBUSB_CALL libusb_unref_device(libusb_device *dev); - -int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, - int *config); -int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, - struct libusb_device_descriptor *desc); -int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, - struct libusb_config_descriptor **config); -int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, - uint8_t config_index, struct libusb_config_descriptor **config); -int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, - uint8_t bConfigurationValue, struct libusb_config_descriptor **config); -void LIBUSB_CALL libusb_free_config_descriptor( - struct libusb_config_descriptor *config); -int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( - struct libusb_context *ctx, - const struct libusb_endpoint_descriptor *endpoint, - struct libusb_ss_endpoint_companion_descriptor **ep_comp); -void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( - struct libusb_ss_endpoint_companion_descriptor *ep_comp); -int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, - struct libusb_bos_descriptor **bos); -void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); -int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension); -void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor( - struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension); -int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor( - struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap); -void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor( - struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap); -int LIBUSB_CALL libusb_get_container_id_descriptor(struct libusb_context *ctx, - struct libusb_bos_dev_capability_descriptor *dev_cap, - struct libusb_container_id_descriptor **container_id); -void LIBUSB_CALL libusb_free_container_id_descriptor( - struct libusb_container_id_descriptor *container_id); -uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); -uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev); -int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t* port_numbers, int port_numbers_len); -LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers) -int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_length); -libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev); -uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); -int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); -int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, - unsigned char endpoint); -int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, - unsigned char endpoint); - -int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); -void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); -libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); - -int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, - int configuration); -int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, - int interface_number); - -libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( - libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); - -int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, - int interface_number, int alternate_setting); -int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, - unsigned char endpoint); -int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); - -int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints); -int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, - unsigned char *endpoints, int num_endpoints); - -unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, - size_t length); -int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, - unsigned char *buffer, size_t length); - -int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, - int interface_number); -int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( - libusb_device_handle *dev_handle, int enable); - -/* async I/O */ - -/** \ingroup libusb_asyncio - * Get the data section of a control transfer. This convenience function is here - * to remind you that the data does not start until 8 bytes into the actual - * buffer, as the setup packet comes first. - * - * Calling this function only makes sense from a transfer callback function, - * or situations where you have already allocated a suitably sized buffer at - * transfer->buffer. - * - * \param transfer a transfer - * \returns pointer to the first byte of the data section - */ -static inline unsigned char *libusb_control_transfer_get_data( - struct libusb_transfer *transfer) -{ - return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; -} - -/** \ingroup libusb_asyncio - * Get the control setup packet of a control transfer. This convenience - * function is here to remind you that the control setup occupies the first - * 8 bytes of the transfer data buffer. - * - * Calling this function only makes sense from a transfer callback function, - * or situations where you have already allocated a suitably sized buffer at - * transfer->buffer. - * - * \param transfer a transfer - * \returns a casted pointer to the start of the transfer data buffer - */ -static inline struct libusb_control_setup *libusb_control_transfer_get_setup( - struct libusb_transfer *transfer) -{ - return (struct libusb_control_setup *)(void *) transfer->buffer; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the setup packet (first 8 bytes of the data - * buffer) for a control transfer. The wIndex, wValue and wLength values should - * be given in host-endian byte order. - * - * \param buffer buffer to output the setup packet into - * This pointer must be aligned to at least 2 bytes boundary. - * \param bmRequestType see the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field of - * \ref libusb_control_setup - * \param bRequest see the - * \ref libusb_control_setup::bRequest "bRequest" field of - * \ref libusb_control_setup - * \param wValue see the - * \ref libusb_control_setup::wValue "wValue" field of - * \ref libusb_control_setup - * \param wIndex see the - * \ref libusb_control_setup::wIndex "wIndex" field of - * \ref libusb_control_setup - * \param wLength see the - * \ref libusb_control_setup::wLength "wLength" field of - * \ref libusb_control_setup - */ -static inline void libusb_fill_control_setup(unsigned char *buffer, - uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - uint16_t wLength) -{ - struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; - setup->bmRequestType = bmRequestType; - setup->bRequest = bRequest; - setup->wValue = libusb_cpu_to_le16(wValue); - setup->wIndex = libusb_cpu_to_le16(wIndex); - setup->wLength = libusb_cpu_to_le16(wLength); -} - -struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); -int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); -int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); -void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); -void LIBUSB_CALL libusb_transfer_set_stream_id( - struct libusb_transfer *transfer, uint32_t stream_id); -uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( - struct libusb_transfer *transfer); - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a control transfer. - * - * If you pass a transfer buffer to this function, the first 8 bytes will - * be interpreted as a control setup packet, and the wLength field will be - * used to automatically populate the \ref libusb_transfer::length "length" - * field of the transfer. Therefore the recommended approach is: - * -# Allocate a suitably sized data buffer (including space for control setup) - * -# Call libusb_fill_control_setup() - * -# If this is a host-to-device transfer with a data stage, put the data - * in place after the setup packet - * -# Call this function - * -# Call libusb_submit_transfer() - * - * It is also legal to pass a NULL buffer to this function, in which case this - * function will not attempt to populate the length field. Remember that you - * must then populate the buffer and length fields later. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param buffer data buffer. If provided, this function will interpret the - * first 8 bytes as a setup packet and infer the transfer length from that. - * This pointer must be aligned to at least 2 bytes boundary. - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_control_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, - unsigned int timeout) -{ - struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer; - transfer->dev_handle = dev_handle; - transfer->endpoint = 0; - transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; - transfer->timeout = timeout; - transfer->buffer = buffer; - if (setup) - transfer->length = (int) (LIBUSB_CONTROL_SETUP_SIZE - + libusb_le16_to_cpu(setup->wLength)); - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a bulk transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, - libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *buffer, int length, libusb_transfer_cb_fn callback, - void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_BULK; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a bulk transfer using bulk streams. - * - * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param stream_id bulk stream id for this transfer - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_bulk_stream_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char endpoint, uint32_t stream_id, - unsigned char *buffer, int length, libusb_transfer_cb_fn callback, - void *user_data, unsigned int timeout) -{ - libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, - length, callback, user_data, timeout); - transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; - libusb_transfer_set_stream_id(transfer, stream_id); -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for an interrupt transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_interrupt_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *buffer, int length, - libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for an isochronous transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param num_iso_packets the number of isochronous packets - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, - libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *buffer, int length, int num_iso_packets, - libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->num_iso_packets = num_iso_packets; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup libusb_asyncio - * Convenience function to set the length of all packets in an isochronous - * transfer, based on the num_iso_packets field in the transfer structure. - * - * \param transfer a transfer - * \param length the length to set in each isochronous packet descriptor - * \see libusb_get_max_packet_size() - */ -static inline void libusb_set_iso_packet_lengths( - struct libusb_transfer *transfer, unsigned int length) -{ - int i; - for (i = 0; i < transfer->num_iso_packets; i++) - transfer->iso_packet_desc[i].length = length; -} - -/** \ingroup libusb_asyncio - * Convenience function to locate the position of an isochronous packet - * within the buffer of an isochronous transfer. - * - * This is a thorough function which loops through all preceding packets, - * accumulating their lengths to find the position of the specified packet. - * Typically you will assign equal lengths to each packet in the transfer, - * and hence the above method is sub-optimal. You may wish to use - * libusb_get_iso_packet_buffer_simple() instead. - * - * \param transfer a transfer - * \param packet the packet to return the address of - * \returns the base address of the packet buffer inside the transfer buffer, - * or NULL if the packet does not exist. - * \see libusb_get_iso_packet_buffer_simple() - */ -static inline unsigned char *libusb_get_iso_packet_buffer( - struct libusb_transfer *transfer, unsigned int packet) -{ - int i; - size_t offset = 0; - int _packet; - - /* oops..slight bug in the API. packet is an unsigned int, but we use - * signed integers almost everywhere else. range-check and convert to - * signed to avoid compiler warnings. FIXME for libusb-2. */ - if (packet > INT_MAX) - return NULL; - _packet = (int) packet; - - if (_packet >= transfer->num_iso_packets) - return NULL; - - for (i = 0; i < _packet; i++) - offset += transfer->iso_packet_desc[i].length; - - return transfer->buffer + offset; -} - -/** \ingroup libusb_asyncio - * Convenience function to locate the position of an isochronous packet - * within the buffer of an isochronous transfer, for transfers where each - * packet is of identical size. - * - * This function relies on the assumption that every packet within the transfer - * is of identical size to the first packet. Calculating the location of - * the packet buffer is then just a simple calculation: - * buffer + (packet_size * packet) - * - * Do not use this function on transfers other than those that have identical - * packet lengths for each packet. - * - * \param transfer a transfer - * \param packet the packet to return the address of - * \returns the base address of the packet buffer inside the transfer buffer, - * or NULL if the packet does not exist. - * \see libusb_get_iso_packet_buffer() - */ -static inline unsigned char *libusb_get_iso_packet_buffer_simple( - struct libusb_transfer *transfer, unsigned int packet) -{ - int _packet; - - /* oops..slight bug in the API. packet is an unsigned int, but we use - * signed integers almost everywhere else. range-check and convert to - * signed to avoid compiler warnings. FIXME for libusb-2. */ - if (packet > INT_MAX) - return NULL; - _packet = (int) packet; - - if (_packet >= transfer->num_iso_packets) - return NULL; - - return transfer->buffer + ((int) transfer->iso_packet_desc[0].length * _packet); -} - -/* sync I/O */ - -int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, - uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout); - -int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - -int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - -/** \ingroup libusb_desc - * Retrieve a descriptor from the default control pipe. - * This is a convenience function which formulates the appropriate control - * message to retrieve the descriptor. - * - * \param dev_handle a device handle - * \param desc_type the descriptor type, see \ref libusb_descriptor_type - * \param desc_index the index of the descriptor to retrieve - * \param data output buffer for descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - */ -static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, - uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) -{ - return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), - 0, data, (uint16_t) length, 1000); -} - -/** \ingroup libusb_desc - * Retrieve a descriptor from a device. - * This is a convenience function which formulates the appropriate control - * message to retrieve the descriptor. The string returned is Unicode, as - * detailed in the USB specifications. - * - * \param dev_handle a device handle - * \param desc_index the index of the descriptor to retrieve - * \param langid the language ID for the string descriptor - * \param data output buffer for descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - * \see libusb_get_string_descriptor_ascii() - */ -static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, - uint8_t desc_index, uint16_t langid, unsigned char *data, int length) -{ - return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), - langid, data, (uint16_t) length, 1000); -} - -int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, - uint8_t desc_index, unsigned char *data, int length); - -/* polling and timeouts */ - -int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); -void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); -void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); -int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); -int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); -void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx); -void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); -void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); -int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); - -int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv); -int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, - struct timeval *tv, int *completed); -int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); -int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); -int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, - struct timeval *tv); -int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); -int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, - struct timeval *tv); - -/** \ingroup libusb_poll - * File descriptor for polling - */ -struct libusb_pollfd { - /** Numeric file descriptor */ - int fd; - - /** Event flags to poll for from . POLLIN indicates that you - * should monitor this file descriptor for becoming ready to read from, - * and POLLOUT indicates that you should monitor this file descriptor for - * nonblocking write readiness. */ - short events; -}; - -/** \ingroup libusb_poll - * Callback function, invoked when a new file descriptor should be added - * to the set of file descriptors monitored for events. - * \param fd the new file descriptor - * \param events events to monitor for, see \ref libusb_pollfd for a - * description - * \param user_data User data pointer specified in - * libusb_set_pollfd_notifiers() call - * \see libusb_set_pollfd_notifiers() - */ -typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, - void *user_data); - -/** \ingroup libusb_poll - * Callback function, invoked when a file descriptor should be removed from - * the set of file descriptors being monitored for events. After returning - * from this callback, do not use that file descriptor again. - * \param fd the file descriptor to stop monitoring - * \param user_data User data pointer specified in - * libusb_set_pollfd_notifiers() call - * \see libusb_set_pollfd_notifiers() - */ -typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); - -const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( - libusb_context *ctx); -void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds); -void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, - libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, - void *user_data); - -/** \ingroup libusb_hotplug - * Callback handle. - * - * Callbacks handles are generated by libusb_hotplug_register_callback() - * and can be used to deregister callbacks. Callback handles are unique - * per libusb_context and it is safe to call libusb_hotplug_deregister_callback() - * on an already deregisted callback. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * For more information, see \ref libusb_hotplug. - */ -typedef int libusb_hotplug_callback_handle; - -/** \ingroup libusb_hotplug - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * Flags for hotplug events */ -typedef enum { - /** Default value when not using any flags. */ - LIBUSB_HOTPLUG_NO_FLAGS = 0, - - /** Arm the callback and fire it for all matching currently attached devices. */ - LIBUSB_HOTPLUG_ENUMERATE = 1<<0, -} libusb_hotplug_flag; - -/** \ingroup libusb_hotplug - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * Hotplug events */ -typedef enum { - /** A device has been plugged in and is ready to use */ - LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01, - - /** A device has left and is no longer available. - * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. - * It is safe to call libusb_get_device_descriptor on a device that has left */ - LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02, -} libusb_hotplug_event; - -/** \ingroup libusb_hotplug - * Wildcard matching for hotplug events */ -#define LIBUSB_HOTPLUG_MATCH_ANY -1 - -/** \ingroup libusb_hotplug - * Hotplug callback function type. When requesting hotplug event notifications, - * you pass a pointer to a callback function of this type. - * - * This callback may be called by an internal event thread and as such it is - * recommended the callback do minimal processing before returning. - * - * libusb will call this function later, when a matching event had happened on - * a matching device. See \ref libusb_hotplug for more information. - * - * It is safe to call either libusb_hotplug_register_callback() or - * libusb_hotplug_deregister_callback() from within a callback function. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * \param ctx context of this notification - * \param device libusb_device this event occurred on - * \param event event that occurred - * \param user_data user data provided when this callback was registered - * \returns bool whether this callback is finished processing events. - * returning 1 will cause this callback to be deregistered - */ -typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, - libusb_device *device, - libusb_hotplug_event event, - void *user_data); - -/** \ingroup libusb_hotplug - * Register a hotplug callback function - * - * Register a callback with the libusb_context. The callback will fire - * when a matching event occurs on a matching device. The callback is - * armed until either it is deregistered with libusb_hotplug_deregister_callback() - * or the supplied callback returns 1 to indicate it is finished processing events. - * - * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be - * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices - * already plugged into the machine. Note that libusb modifies its internal - * device list from a separate thread, while calling hotplug callbacks from - * libusb_handle_events(), so it is possible for a device to already be present - * on, or removed from, its internal device list, while the hotplug callbacks - * still need to be dispatched. This means that when using \ref - * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival - * of the same device, once from libusb_hotplug_register_callback() and once - * from libusb_handle_events(); and/or your callback may be called for the - * removal of a device for which an arrived call was never made. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * \param[in] ctx context to register this callback with - * \param[in] events bitwise or of events that will trigger this callback. See \ref - * libusb_hotplug_event - * \param[in] flags hotplug callback flags. See \ref libusb_hotplug_flag - * \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - * \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - * \param[in] cb_fn the function to be invoked on a matching event/device - * \param[in] user_data user data to pass to the callback function - * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) - * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure - */ -int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, - libusb_hotplug_event events, - libusb_hotplug_flag flags, - int vendor_id, int product_id, - int dev_class, - libusb_hotplug_callback_fn cb_fn, - void *user_data, - libusb_hotplug_callback_handle *callback_handle); - -/** \ingroup libusb_hotplug - * Deregisters a hotplug callback. - * - * Deregister a callback from a libusb_context. This function is safe to call from within - * a hotplug callback. - * - * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - * - * \param[in] ctx context this callback is registered with - * \param[in] callback_handle the handle of the callback to deregister - */ -void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, - libusb_hotplug_callback_handle callback_handle); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/libusbi.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/libusbi.h deleted file mode 100644 index 752e3988787..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/libusbi.h +++ /dev/null @@ -1,1149 +0,0 @@ -/* - * Internal header for libusb - * Copyright © 2007-2009 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSBI_H -#define LIBUSBI_H - -#include - -#include - -#include -#include -#include -#include -#ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_MISSING_H -#include -#endif - -#include "libusb.h" -#include "version.h" - -/* Inside the libusb code, mark all public functions as follows: - * return_type API_EXPORTED function_name(params) { ... } - * But if the function returns a pointer, mark it as follows: - * DEFAULT_VISIBILITY return_type * LIBUSB_CALL function_name(params) { ... } - * In the libusb public header, mark all declarations as: - * return_type LIBUSB_CALL function_name(params); - */ -#define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY - -#ifdef __cplusplus -extern "C" { -#endif - -#define DEVICE_DESC_LENGTH 18 - -#define USB_MAXENDPOINTS 32 -#define USB_MAXINTERFACES 32 -#define USB_MAXCONFIG 8 - -/* Backend specific capabilities */ -#define USBI_CAP_HAS_HID_ACCESS 0x00010000 -#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 - -/* Maximum number of bytes in a log line */ -#define USBI_MAX_LOG_LEN 1024 -/* Terminator for log lines */ -#define USBI_LOG_LINE_END "\n" - -/* The following is used to silence warnings for unused variables */ -#define UNUSED(var) do { (void)(var); } while(0) - -#if !defined(ARRAYSIZE) -#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0])) -#endif - -struct list_head { - struct list_head *prev, *next; -}; - -/* Get an entry from the list - * ptr - the address of this list_head element in "type" - * type - the data type that contains "member" - * member - the list_head element in "type" - */ -#define list_entry(ptr, type, member) \ - ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member))) - -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -/* Get each entry from a list - * pos - A structure pointer has a "member" element - * head - list head - * member - the list_head element in "pos" - * type - the type of the first parameter - */ -#define list_for_each_entry(pos, head, member, type) \ - for (pos = list_entry((head)->next, type, member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, type, member)) - -#define list_for_each_entry_safe(pos, n, head, member, type) \ - for (pos = list_entry((head)->next, type, member), \ - n = list_entry(pos->member.next, type, member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, type, member)) - -#define list_empty(entry) ((entry)->next == (entry)) - -static inline void list_init(struct list_head *entry) -{ - entry->prev = entry->next = entry; -} - -static inline void list_add(struct list_head *entry, struct list_head *head) -{ - entry->next = head->next; - entry->prev = head; - - head->next->prev = entry; - head->next = entry; -} - -static inline void list_add_tail(struct list_head *entry, - struct list_head *head) -{ - entry->next = head; - entry->prev = head->prev; - - head->prev->next = entry; - head->prev = entry; -} - -static inline void list_del(struct list_head *entry) -{ - entry->next->prev = entry->prev; - entry->prev->next = entry->next; - entry->next = entry->prev = NULL; -} - -static inline void *usbi_reallocf(void *ptr, size_t size) -{ - void *ret = realloc(ptr, size); - if (!ret) - free(ptr); - return ret; -} - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *mptr = (ptr); \ - (type *)( (char *)mptr - offsetof(type,member) );}) - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0) - -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -#define TIMEVAL_TV_SEC_TYPE long -#else -#define TIMEVAL_TV_SEC_TYPE time_t -#endif - -/* Some platforms don't have this define */ -#ifndef TIMESPEC_TO_TIMEVAL -#define TIMESPEC_TO_TIMEVAL(tv, ts) \ - do { \ - (tv)->tv_sec = (TIMEVAL_TV_SEC_TYPE) (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ - } while (0) -#endif - -void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, ...); - -void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, - const char *function, const char *format, va_list args); - -#if !defined(_MSC_VER) || _MSC_VER >= 1400 - -#ifdef ENABLE_LOGGING -#define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) -#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) -#else -#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0) -#define usbi_dbg(...) do {} while(0) -#endif - -#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) -#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) -#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__) - -#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ - -#ifdef ENABLE_LOGGING -#define LOG_BODY(ctxt, level) \ -{ \ - va_list args; \ - va_start(args, format); \ - usbi_log_v(ctxt, level, "", format, args); \ - va_end(args); \ -} -#else -#define LOG_BODY(ctxt, level) \ -{ \ - (void)(ctxt); \ -} -#endif - -static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_INFO) -static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_WARNING) -static inline void usbi_err(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx, LIBUSB_LOG_LEVEL_ERROR) - -static inline void usbi_dbg(const char *format, ...) - LOG_BODY(NULL, LIBUSB_LOG_LEVEL_DEBUG) - -#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ - -#define USBI_GET_CONTEXT(ctx) \ - do { \ - if (!(ctx)) \ - (ctx) = usbi_default_context; \ - } while(0) - -#define DEVICE_CTX(dev) ((dev)->ctx) -#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) -#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) -#define ITRANSFER_CTX(transfer) \ - (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) - -#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN)) -#define IS_EPOUT(ep) (!IS_EPIN(ep)) -#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN)) -#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer)) - -/* Internal abstraction for thread synchronization */ -#if defined(THREADS_POSIX) -#include "os/threads_posix.h" -#elif defined(OS_WINDOWS) || defined(OS_WINCE) -#include "os/threads_windows.h" -#endif - -extern struct libusb_context *usbi_default_context; - -/* Forward declaration for use in context (fully defined inside poll abstraction) */ -struct pollfd; - -struct libusb_context { - int debug; - int debug_fixed; - - /* internal event pipe, used for signalling occurrence of an internal event. */ - int event_pipe[2]; - - struct list_head usb_devs; - usbi_mutex_t usb_devs_lock; - - /* A list of open handles. Backends are free to traverse this if required. - */ - struct list_head open_devs; - usbi_mutex_t open_devs_lock; - - /* A list of registered hotplug callbacks */ - struct list_head hotplug_cbs; - usbi_mutex_t hotplug_cbs_lock; - - /* this is a list of in-flight transfer handles, sorted by timeout - * expiration. URBs to timeout the soonest are placed at the beginning of - * the list, URBs that will time out later are placed after, and urbs with - * infinite timeout are always placed at the very end. */ - struct list_head flying_transfers; - /* Note paths taking both this and usbi_transfer->lock must always - * take this lock first */ - usbi_mutex_t flying_transfers_lock; - - /* user callbacks for pollfd changes */ - libusb_pollfd_added_cb fd_added_cb; - libusb_pollfd_removed_cb fd_removed_cb; - void *fd_cb_user_data; - - /* ensures that only one thread is handling events at any one time */ - usbi_mutex_t events_lock; - - /* used to see if there is an active thread doing event handling */ - int event_handler_active; - - /* A thread-local storage key to track which thread is performing event - * handling */ - usbi_tls_key_t event_handling_key; - - /* used to wait for event completion in threads other than the one that is - * event handling */ - usbi_mutex_t event_waiters_lock; - usbi_cond_t event_waiters_cond; - - /* A lock to protect internal context event data. */ - usbi_mutex_t event_data_lock; - - /* A bitmask of flags that are set to indicate specific events that need to - * be handled. Protected by event_data_lock. */ - unsigned int event_flags; - - /* A counter that is set when we want to interrupt and prevent event handling, - * in order to safely close a device. Protected by event_data_lock. */ - unsigned int device_close; - - /* list and count of poll fds and an array of poll fd structures that is - * (re)allocated as necessary prior to polling. Protected by event_data_lock. */ - struct list_head ipollfds; - struct pollfd *pollfds; - POLL_NFDS_TYPE pollfds_cnt; - - /* A list of pending hotplug messages. Protected by event_data_lock. */ - struct list_head hotplug_msgs; - - /* A list of pending completed transfers. Protected by event_data_lock. */ - struct list_head completed_transfers; - -#ifdef USBI_TIMERFD_AVAILABLE - /* used for timeout handling, if supported by OS. - * this timerfd is maintained to trigger on the next pending timeout */ - int timerfd; -#endif - - struct list_head list; -}; - -enum usbi_event_flags { - /* The list of pollfds has been modified */ - USBI_EVENT_POLLFDS_MODIFIED = 1 << 0, - - /* The user has interrupted the event handler */ - USBI_EVENT_USER_INTERRUPT = 1 << 1, -}; - -/* Macros for managing event handling state */ -#define usbi_handling_events(ctx) \ - (usbi_tls_key_get((ctx)->event_handling_key) != NULL) - -#define usbi_start_event_handling(ctx) \ - usbi_tls_key_set((ctx)->event_handling_key, ctx) - -#define usbi_end_event_handling(ctx) \ - usbi_tls_key_set((ctx)->event_handling_key, NULL) - -/* Update the following macro if new event sources are added */ -#define usbi_pending_events(ctx) \ - ((ctx)->event_flags || (ctx)->device_close \ - || !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers)) - -#ifdef USBI_TIMERFD_AVAILABLE -#define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) -#else -#define usbi_using_timerfd(ctx) (0) -#endif - -struct libusb_device { - /* lock protects refcnt, everything else is finalized at initialization - * time */ - usbi_mutex_t lock; - int refcnt; - - struct libusb_context *ctx; - - uint8_t bus_number; - uint8_t port_number; - struct libusb_device* parent_dev; - uint8_t device_address; - uint8_t num_configurations; - enum libusb_speed speed; - - struct list_head list; - unsigned long session_data; - - struct libusb_device_descriptor device_descriptor; - int attached; - - unsigned char os_priv -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif -#if defined(OS_SUNOS) - __attribute__ ((aligned (8))); -#else - ; -#endif -}; - -struct libusb_device_handle { - /* lock protects claimed_interfaces */ - usbi_mutex_t lock; - unsigned long claimed_interfaces; - - struct list_head list; - struct libusb_device *dev; - int auto_detach_kernel_driver; - unsigned char os_priv -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif -#if defined(OS_SUNOS) - __attribute__ ((aligned (8))); -#else - ; -#endif -}; - -enum { - USBI_CLOCK_MONOTONIC, - USBI_CLOCK_REALTIME -}; - -/* in-memory transfer layout: - * - * 1. struct usbi_transfer - * 2. struct libusb_transfer (which includes iso packets) [variable size] - * 3. os private data [variable size] - * - * from a libusb_transfer, you can get the usbi_transfer by rewinding the - * appropriate number of bytes. - * the usbi_transfer includes the number of allocated packets, so you can - * determine the size of the transfer and hence the start and length of the - * OS-private data. - */ - -struct usbi_transfer { - int num_iso_packets; - struct list_head list; - struct list_head completed_list; - struct timeval timeout; - int transferred; - uint32_t stream_id; - uint8_t state_flags; /* Protected by usbi_transfer->lock */ - uint8_t timeout_flags; /* Protected by the flying_stransfers_lock */ - - /* this lock is held during libusb_submit_transfer() and - * libusb_cancel_transfer() (allowing the OS backend to prevent duplicate - * cancellation, submission-during-cancellation, etc). the OS backend - * should also take this lock in the handle_events path, to prevent the user - * cancelling the transfer from another thread while you are processing - * its completion (presumably there would be races within your OS backend - * if this were possible). - * Note paths taking both this and the flying_transfers_lock must - * always take the flying_transfers_lock first */ - usbi_mutex_t lock; -}; - -enum usbi_transfer_state_flags { - /* Transfer successfully submitted by backend */ - USBI_TRANSFER_IN_FLIGHT = 1 << 0, - - /* Cancellation was requested via libusb_cancel_transfer() */ - USBI_TRANSFER_CANCELLING = 1 << 1, - - /* Operation on the transfer failed because the device disappeared */ - USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 2, -}; - -enum usbi_transfer_timeout_flags { - /* Set by backend submit_transfer() if the OS handles timeout */ - USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 0, - - /* The transfer timeout has been handled */ - USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 1, - - /* The transfer timeout was successfully processed */ - USBI_TRANSFER_TIMED_OUT = 1 << 2, -}; - -#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ - ((struct libusb_transfer *)(((unsigned char *)(transfer)) \ - + sizeof(struct usbi_transfer))) -#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ - ((struct usbi_transfer *)(((unsigned char *)(transfer)) \ - - sizeof(struct usbi_transfer))) - -static inline void *usbi_transfer_get_os_priv(struct usbi_transfer *transfer) -{ - return ((unsigned char *)transfer) + sizeof(struct usbi_transfer) - + sizeof(struct libusb_transfer) - + (transfer->num_iso_packets - * sizeof(struct libusb_iso_packet_descriptor)); -} - -/* bus structures */ - -/* All standard descriptors have these 2 fields in common */ -struct usb_descriptor_header { - uint8_t bLength; - uint8_t bDescriptorType; -}; - -/* shared data and functions */ - -int usbi_io_init(struct libusb_context *ctx); -void usbi_io_exit(struct libusb_context *ctx); - -struct libusb_device *usbi_alloc_device(struct libusb_context *ctx, - unsigned long session_id); -struct libusb_device *usbi_get_device_by_session_id(struct libusb_context *ctx, - unsigned long session_id); -int usbi_sanitize_device(struct libusb_device *dev); -void usbi_handle_disconnect(struct libusb_device_handle *dev_handle); - -int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, - enum libusb_transfer_status status); -int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer); -void usbi_signal_transfer_completion(struct usbi_transfer *transfer); - -int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, - void *dest, int host_endian); -int usbi_device_cache_descriptor(libusb_device *dev); -int usbi_get_config_index_by_value(struct libusb_device *dev, - uint8_t bConfigurationValue, int *idx); - -void usbi_connect_device (struct libusb_device *dev); -void usbi_disconnect_device (struct libusb_device *dev); - -int usbi_signal_event(struct libusb_context *ctx); -int usbi_clear_event(struct libusb_context *ctx); - -/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ -#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) ||\ - defined(OS_HAIKU) || defined(OS_SUNOS) -#include -#include "os/poll_posix.h" -#elif defined(OS_WINDOWS) || defined(OS_WINCE) -#include "os/poll_windows.h" -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define snprintf usbi_snprintf -#define vsnprintf usbi_vsnprintf -int usbi_snprintf(char *dst, size_t size, const char *format, ...); -int usbi_vsnprintf(char *dst, size_t size, const char *format, va_list ap); -#define LIBUSB_PRINTF_WIN32 -#endif - -struct usbi_pollfd { - /* must come first */ - struct libusb_pollfd pollfd; - - struct list_head list; -}; - -int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); -void usbi_remove_pollfd(struct libusb_context *ctx, int fd); - -/* device discovery */ - -/* we traverse usbfs without knowing how many devices we are going to find. - * so we create this discovered_devs model which is similar to a linked-list - * which grows when required. it can be freed once discovery has completed, - * eliminating the need for a list node in the libusb_device structure - * itself. */ -struct discovered_devs { - size_t len; - size_t capacity; - struct libusb_device *devices -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; -}; - -struct discovered_devs *discovered_devs_append( - struct discovered_devs *discdevs, struct libusb_device *dev); - -/* OS abstraction */ - -/* This is the interface that OS backends need to implement. - * All fields are mandatory, except ones explicitly noted as optional. */ -struct usbi_os_backend { - /* A human-readable name for your backend, e.g. "Linux usbfs" */ - const char *name; - - /* Binary mask for backend specific capabilities */ - uint32_t caps; - - /* Perform initialization of your backend. You might use this function - * to determine specific capabilities of the system, allocate required - * data structures for later, etc. - * - * This function is called when a libusb user initializes the library - * prior to use. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*init)(struct libusb_context *ctx); - - /* Deinitialization. Optional. This function should destroy anything - * that was set up by init. - * - * This function is called when the user deinitializes the library. - */ - void (*exit)(void); - - /* Enumerate all the USB devices on the system, returning them in a list - * of discovered devices. - * - * Your implementation should enumerate all devices on the system, - * regardless of whether they have been seen before or not. - * - * When you have found a device, compute a session ID for it. The session - * ID should uniquely represent that particular device for that particular - * connection session since boot (i.e. if you disconnect and reconnect a - * device immediately after, it should be assigned a different session ID). - * If your OS cannot provide a unique session ID as described above, - * presenting a session ID of (bus_number << 8 | device_address) should - * be sufficient. Bus numbers and device addresses wrap and get reused, - * but that is an unlikely case. - * - * After computing a session ID for a device, call - * usbi_get_device_by_session_id(). This function checks if libusb already - * knows about the device, and if so, it provides you with a reference - * to a libusb_device structure for it. - * - * If usbi_get_device_by_session_id() returns NULL, it is time to allocate - * a new device structure for the device. Call usbi_alloc_device() to - * obtain a new libusb_device structure with reference count 1. Populate - * the bus_number and device_address attributes of the new device, and - * perform any other internal backend initialization you need to do. At - * this point, you should be ready to provide device descriptors and so - * on through the get_*_descriptor functions. Finally, call - * usbi_sanitize_device() to perform some final sanity checks on the - * device. Assuming all of the above succeeded, we can now continue. - * If any of the above failed, remember to unreference the device that - * was returned by usbi_alloc_device(). - * - * At this stage we have a populated libusb_device structure (either one - * that was found earlier, or one that we have just allocated and - * populated). This can now be added to the discovered devices list - * using discovered_devs_append(). Note that discovered_devs_append() - * may reallocate the list, returning a new location for it, and also - * note that reallocation can fail. Your backend should handle these - * error conditions appropriately. - * - * This function should not generate any bus I/O and should not block. - * If I/O is required (e.g. reading the active configuration value), it is - * OK to ignore these suggestions :) - * - * This function is executed when the user wishes to retrieve a list - * of USB devices connected to the system. - * - * If the backend has hotplug support, this function is not used! - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*get_device_list)(struct libusb_context *ctx, - struct discovered_devs **discdevs); - - /* Apps which were written before hotplug support, may listen for - * hotplug events on their own and call libusb_get_device_list on - * device addition. In this case libusb_get_device_list will likely - * return a list without the new device in there, as the hotplug - * event thread will still be busy enumerating the device, which may - * take a while, or may not even have seen the event yet. - * - * To avoid this libusb_get_device_list will call this optional - * function for backends with hotplug support before copying - * ctx->usb_devs to the user. In this function the backend should - * ensure any pending hotplug events are fully processed before - * returning. - * - * Optional, should be implemented by backends with hotplug support. - */ - void (*hotplug_poll)(void); - - /* Open a device for I/O and other USB operations. The device handle - * is preallocated for you, you can retrieve the device in question - * through handle->dev. - * - * Your backend should allocate any internal resources required for I/O - * and other operations so that those operations can happen (hopefully) - * without hiccup. This is also a good place to inform libusb that it - * should monitor certain file descriptors related to this device - - * see the usbi_add_pollfd() function. - * - * This function should not generate any bus I/O and should not block. - * - * This function is called when the user attempts to obtain a device - * handle for a device. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since - * discovery - * - another LIBUSB_ERROR code on other failure - * - * Do not worry about freeing the handle on failed open, the upper layers - * do this for you. - */ - int (*open)(struct libusb_device_handle *dev_handle); - - /* Close a device such that the handle cannot be used again. Your backend - * should destroy any resources that were allocated in the open path. - * This may also be a good place to call usbi_remove_pollfd() to inform - * libusb of any file descriptors associated with this device that should - * no longer be monitored. - * - * This function is called when the user closes a device handle. - */ - void (*close)(struct libusb_device_handle *dev_handle); - - /* Retrieve the device descriptor from a device. - * - * The descriptor should be retrieved from memory, NOT via bus I/O to the - * device. This means that you may have to cache it in a private structure - * during get_device_list enumeration. Alternatively, you may be able - * to retrieve it from a kernel interface (some Linux setups can do this) - * still without generating bus I/O. - * - * This function is expected to write DEVICE_DESC_LENGTH (18) bytes into - * buffer, which is guaranteed to be big enough. - * - * This function is called when sanity-checking a device before adding - * it to the list of discovered devices, and also when the user requests - * to read the device descriptor. - * - * This function is expected to return the descriptor in bus-endian format - * (LE). If it returns the multi-byte values in host-endian format, - * set the host_endian output parameter to "1". - * - * Return 0 on success or a LIBUSB_ERROR code on failure. - */ - int (*get_device_descriptor)(struct libusb_device *device, - unsigned char *buffer, int *host_endian); - - /* Get the ACTIVE configuration descriptor for a device. - * - * The descriptor should be retrieved from memory, NOT via bus I/O to the - * device. This means that you may have to cache it in a private structure - * during get_device_list enumeration. You may also have to keep track - * of which configuration is active when the user changes it. - * - * This function is expected to write len bytes of data into buffer, which - * is guaranteed to be big enough. If you can only do a partial write, - * return an error code. - * - * This function is expected to return the descriptor in bus-endian format - * (LE). If it returns the multi-byte values in host-endian format, - * set the host_endian output parameter to "1". - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the device is in unconfigured state - * - another LIBUSB_ERROR code on other failure - */ - int (*get_active_config_descriptor)(struct libusb_device *device, - unsigned char *buffer, size_t len, int *host_endian); - - /* Get a specific configuration descriptor for a device. - * - * The descriptor should be retrieved from memory, NOT via bus I/O to the - * device. This means that you may have to cache it in a private structure - * during get_device_list enumeration. - * - * The requested descriptor is expressed as a zero-based index (i.e. 0 - * indicates that we are requesting the first descriptor). The index does - * not (necessarily) equal the bConfigurationValue of the configuration - * being requested. - * - * This function is expected to write len bytes of data into buffer, which - * is guaranteed to be big enough. If you can only do a partial write, - * return an error code. - * - * This function is expected to return the descriptor in bus-endian format - * (LE). If it returns the multi-byte values in host-endian format, - * set the host_endian output parameter to "1". - * - * Return the length read on success or a LIBUSB_ERROR code on failure. - */ - int (*get_config_descriptor)(struct libusb_device *device, - uint8_t config_index, unsigned char *buffer, size_t len, - int *host_endian); - - /* Like get_config_descriptor but then by bConfigurationValue instead - * of by index. - * - * Optional, if not present the core will call get_config_descriptor - * for all configs until it finds the desired bConfigurationValue. - * - * Returns a pointer to the raw-descriptor in *buffer, this memory - * is valid as long as device is valid. - * - * Returns the length of the returned raw-descriptor on success, - * or a LIBUSB_ERROR code on failure. - */ - int (*get_config_descriptor_by_value)(struct libusb_device *device, - uint8_t bConfigurationValue, unsigned char **buffer, - int *host_endian); - - /* Get the bConfigurationValue for the active configuration for a device. - * Optional. This should only be implemented if you can retrieve it from - * cache (don't generate I/O). - * - * If you cannot retrieve this from cache, either do not implement this - * function, or return LIBUSB_ERROR_NOT_SUPPORTED. This will cause - * libusb to retrieve the information through a standard control transfer. - * - * This function must be non-blocking. - * Return: - * - 0 on success - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - LIBUSB_ERROR_NOT_SUPPORTED if the value cannot be retrieved without - * blocking - * - another LIBUSB_ERROR code on other failure. - */ - int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config); - - /* Set the active configuration for a device. - * - * A configuration value of -1 should put the device in unconfigured state. - * - * This function can block. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the configuration does not exist - * - LIBUSB_ERROR_BUSY if interfaces are currently claimed (and hence - * configuration cannot be changed) - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure. - */ - int (*set_configuration)(struct libusb_device_handle *dev_handle, int config); - - /* Claim an interface. When claimed, the application can then perform - * I/O to an interface's endpoints. - * - * This function should not generate any bus I/O and should not block. - * Interface claiming is a logical operation that simply ensures that - * no other drivers/applications are using the interface, and after - * claiming, no other drivers/applications can use the interface because - * we now "own" it. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the interface does not exist - * - LIBUSB_ERROR_BUSY if the interface is in use by another driver/app - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number); - - /* Release a previously claimed interface. - * - * This function should also generate a SET_INTERFACE control request, - * resetting the alternate setting of that interface to 0. It's OK for - * this function to block as a result. - * - * You will only ever be asked to release an interface which was - * successfully claimed earlier. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number); - - /* Set the alternate setting for an interface. - * - * You will only ever be asked to set the alternate setting for an - * interface which was successfully claimed earlier. - * - * It's OK for this function to block. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the alternate setting does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle, - int interface_number, int altsetting); - - /* Clear a halt/stall condition on an endpoint. - * - * It's OK for this function to block. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if the endpoint does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*clear_halt)(struct libusb_device_handle *dev_handle, - unsigned char endpoint); - - /* Perform a USB port reset to reinitialize a device. - * - * If possible, the device handle should still be usable after the reset - * completes, assuming that the device descriptors did not change during - * reset and all previous interface state can be restored. - * - * If something changes, or you cannot easily locate/verify the resetted - * device, return LIBUSB_ERROR_NOT_FOUND. This prompts the application - * to close the old handle and re-enumerate the device. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if re-enumeration is required, or if the device - * has been disconnected since it was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*reset_device)(struct libusb_device_handle *dev_handle); - - /* Alloc num_streams usb3 bulk streams on the passed in endpoints */ - int (*alloc_streams)(struct libusb_device_handle *dev_handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints); - - /* Free usb3 bulk streams allocated with alloc_streams */ - int (*free_streams)(struct libusb_device_handle *dev_handle, - unsigned char *endpoints, int num_endpoints); - - /* Allocate persistent DMA memory for the given device, suitable for - * zerocopy. May return NULL on failure. Optional to implement. - */ - unsigned char *(*dev_mem_alloc)(struct libusb_device_handle *handle, - size_t len); - - /* Free memory allocated by dev_mem_alloc. */ - int (*dev_mem_free)(struct libusb_device_handle *handle, - unsigned char *buffer, size_t len); - - /* Determine if a kernel driver is active on an interface. Optional. - * - * The presence of a kernel driver on an interface indicates that any - * calls to claim_interface would fail with the LIBUSB_ERROR_BUSY code. - * - * Return: - * - 0 if no driver is active - * - 1 if a driver is active - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*kernel_driver_active)(struct libusb_device_handle *dev_handle, - int interface_number); - - /* Detach a kernel driver from an interface. Optional. - * - * After detaching a kernel driver, the interface should be available - * for claim. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - another LIBUSB_ERROR code on other failure - */ - int (*detach_kernel_driver)(struct libusb_device_handle *dev_handle, - int interface_number); - - /* Attach a kernel driver to an interface. Optional. - * - * Reattach a kernel driver to the device. - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NOT_FOUND if no kernel driver was active - * - LIBUSB_ERROR_INVALID_PARAM if the interface does not exist - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected since it - * was opened - * - LIBUSB_ERROR_BUSY if a program or driver has claimed the interface, - * preventing reattachment - * - another LIBUSB_ERROR code on other failure - */ - int (*attach_kernel_driver)(struct libusb_device_handle *dev_handle, - int interface_number); - - /* Destroy a device. Optional. - * - * This function is called when the last reference to a device is - * destroyed. It should free any resources allocated in the get_device_list - * path. - */ - void (*destroy_device)(struct libusb_device *dev); - - /* Submit a transfer. Your implementation should take the transfer, - * morph it into whatever form your platform requires, and submit it - * asynchronously. - * - * This function must not block. - * - * This function gets called with the flying_transfers_lock locked! - * - * Return: - * - 0 on success - * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * - another LIBUSB_ERROR code on other failure - */ - int (*submit_transfer)(struct usbi_transfer *itransfer); - - /* Cancel a previously submitted transfer. - * - * This function must not block. The transfer cancellation must complete - * later, resulting in a call to usbi_handle_transfer_cancellation() - * from the context of handle_events. - */ - int (*cancel_transfer)(struct usbi_transfer *itransfer); - - /* Clear a transfer as if it has completed or cancelled, but do not - * report any completion/cancellation to the library. You should free - * all private data from the transfer as if you were just about to report - * completion or cancellation. - * - * This function might seem a bit out of place. It is used when libusb - * detects a disconnected device - it calls this function for all pending - * transfers before reporting completion (with the disconnect code) to - * the user. Maybe we can improve upon this internal interface in future. - */ - void (*clear_transfer_priv)(struct usbi_transfer *itransfer); - - /* Handle any pending events on file descriptors. Optional. - * - * Provide this function when file descriptors directly indicate device - * or transfer activity. If your backend does not have such file descriptors, - * implement the handle_transfer_completion function below. - * - * This involves monitoring any active transfers and processing their - * completion or cancellation. - * - * The function is passed an array of pollfd structures (size nfds) - * as a result of the poll() system call. The num_ready parameter - * indicates the number of file descriptors that have reported events - * (i.e. the poll() return value). This should be enough information - * for you to determine which actions need to be taken on the currently - * active transfers. - * - * For any cancelled transfers, call usbi_handle_transfer_cancellation(). - * For completed transfers, call usbi_handle_transfer_completion(). - * For control/bulk/interrupt transfers, populate the "transferred" - * element of the appropriate usbi_transfer structure before calling the - * above functions. For isochronous transfers, populate the status and - * transferred fields of the iso packet descriptors of the transfer. - * - * This function should also be able to detect disconnection of the - * device, reporting that situation with usbi_handle_disconnect(). - * - * When processing an event related to a transfer, you probably want to - * take usbi_transfer.lock to prevent races. See the documentation for - * the usbi_transfer structure. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*handle_events)(struct libusb_context *ctx, - struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); - - /* Handle transfer completion. Optional. - * - * Provide this function when there are no file descriptors available - * that directly indicate device or transfer activity. If your backend does - * have such file descriptors, implement the handle_events function above. - * - * Your backend must tell the library when a transfer has completed by - * calling usbi_signal_transfer_completion(). You should store any private - * information about the transfer and its completion status in the transfer's - * private backend data. - * - * During event handling, this function will be called on each transfer for - * which usbi_signal_transfer_completion() was called. - * - * For any cancelled transfers, call usbi_handle_transfer_cancellation(). - * For completed transfers, call usbi_handle_transfer_completion(). - * For control/bulk/interrupt transfers, populate the "transferred" - * element of the appropriate usbi_transfer structure before calling the - * above functions. For isochronous transfers, populate the status and - * transferred fields of the iso packet descriptors of the transfer. - * - * Return 0 on success, or a LIBUSB_ERROR code on failure. - */ - int (*handle_transfer_completion)(struct usbi_transfer *itransfer); - - /* Get time from specified clock. At least two clocks must be implemented - by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. - - Description of clocks: - USBI_CLOCK_REALTIME : clock returns time since system epoch. - USBI_CLOCK_MONOTONIC: clock returns time since unspecified start - time (usually boot). - */ - int (*clock_gettime)(int clkid, struct timespec *tp); - -#ifdef USBI_TIMERFD_AVAILABLE - /* clock ID of the clock that should be used for timerfd */ - clockid_t (*get_timerfd_clockid)(void); -#endif - - /* Number of bytes to reserve for per-device private backend data. - * This private data area is accessible through the "os_priv" field of - * struct libusb_device. */ - size_t device_priv_size; - - /* Number of bytes to reserve for per-handle private backend data. - * This private data area is accessible through the "os_priv" field of - * struct libusb_device. */ - size_t device_handle_priv_size; - - /* Number of bytes to reserve for per-transfer private backend data. - * This private data area is accessible by calling - * usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance. - */ - size_t transfer_priv_size; -}; - -extern const struct usbi_os_backend * const usbi_backend; - -extern const struct usbi_os_backend linux_usbfs_backend; -extern const struct usbi_os_backend darwin_backend; -extern const struct usbi_os_backend openbsd_backend; -extern const struct usbi_os_backend netbsd_backend; -extern const struct usbi_os_backend windows_backend; -extern const struct usbi_os_backend usbdk_backend; -extern const struct usbi_os_backend wince_backend; -extern const struct usbi_os_backend haiku_usb_raw_backend; -extern const struct usbi_os_backend sunos_backend; - -extern struct list_head active_contexts_list; -extern usbi_mutex_static_t active_contexts_lock; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/darwin_usb.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/darwin_usb.c deleted file mode 100644 index b0219d1b057..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/darwin_usb.c +++ /dev/null @@ -1,2094 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode:nil -*- */ -/* - * darwin backend for libusb 1.0 - * Copyright © 2008-2016 Nathan Hjelm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - #include -#endif - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 -/* Apple deprecated the darwin atomics in 10.12 in favor of C11 atomics */ -#include -#define libusb_darwin_atomic_fetch_add(x, y) atomic_fetch_add(x, y) - -_Atomic int32_t initCount = ATOMIC_VAR_INIT(0); -#else -/* use darwin atomics if the target is older than 10.12 */ -#include - -/* OSAtomicAdd32Barrier returns the new value */ -#define libusb_darwin_atomic_fetch_add(x, y) (OSAtomicAdd32Barrier(y, x) - y) - -static volatile int32_t initCount = 0; -#endif - -#include "darwin_usb.h" - -/* async event thread */ -static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER; - -static pthread_once_t darwin_init_once = PTHREAD_ONCE_INIT; - -static clock_serv_t clock_realtime; -static clock_serv_t clock_monotonic; - -static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */ -static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */ - -static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER; -static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices}; -static char *darwin_device_class = kIOUSBDeviceClassName; - -#define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) - -/* async event thread */ -static pthread_t libusb_darwin_at; - -static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian); -static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface); -static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface); -static int darwin_reset_device(struct libusb_device_handle *dev_handle); -static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0); - -static int darwin_scan_devices(struct libusb_context *ctx); -static int process_new_device (struct libusb_context *ctx, io_service_t service); - -#if defined(ENABLE_LOGGING) -static const char *darwin_error_str (int result) { - static char string_buffer[50]; - switch (result) { - case kIOReturnSuccess: - return "no error"; - case kIOReturnNotOpen: - return "device not opened for exclusive access"; - case kIOReturnNoDevice: - return "no connection to an IOService"; - case kIOUSBNoAsyncPortErr: - return "no async port has been opened for interface"; - case kIOReturnExclusiveAccess: - return "another process has device opened for exclusive access"; - case kIOUSBPipeStalled: - return "pipe is stalled"; - case kIOReturnError: - return "could not establish a connection to the Darwin kernel"; - case kIOUSBTransactionTimeout: - return "transaction timed out"; - case kIOReturnBadArgument: - return "invalid argument"; - case kIOReturnAborted: - return "transaction aborted"; - case kIOReturnNotResponding: - return "device not responding"; - case kIOReturnOverrun: - return "data overrun"; - case kIOReturnCannotWire: - return "physical memory can not be wired down"; - case kIOReturnNoResources: - return "out of resources"; - case kIOUSBHighSpeedSplitError: - return "high speed split error"; - default: - snprintf(string_buffer, sizeof(string_buffer), "unknown error (0x%x)", result); - return string_buffer; - } -} -#endif - -static int darwin_to_libusb (int result) { - switch (result) { - case kIOReturnUnderrun: - case kIOReturnSuccess: - return LIBUSB_SUCCESS; - case kIOReturnNotOpen: - case kIOReturnNoDevice: - return LIBUSB_ERROR_NO_DEVICE; - case kIOReturnExclusiveAccess: - return LIBUSB_ERROR_ACCESS; - case kIOUSBPipeStalled: - return LIBUSB_ERROR_PIPE; - case kIOReturnBadArgument: - return LIBUSB_ERROR_INVALID_PARAM; - case kIOUSBTransactionTimeout: - return LIBUSB_ERROR_TIMEOUT; - case kIOReturnNotResponding: - case kIOReturnAborted: - case kIOReturnError: - case kIOUSBNoAsyncPortErr: - default: - return LIBUSB_ERROR_OTHER; - } -} - -/* this function must be called with the darwin_cached_devices_lock held */ -static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) { - cached_dev->refcount--; - /* free the device and remove it from the cache */ - if (0 == cached_dev->refcount) { - list_del(&cached_dev->list); - - (*(cached_dev->device))->Release(cached_dev->device); - free (cached_dev); - } -} - -static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) { - cached_dev->refcount++; -} - -static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - - /* current interface */ - struct darwin_interface *cInterface; - - int8_t i, iface; - - usbi_dbg ("converting ep address 0x%02x to pipeRef and interface", ep); - - for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { - cInterface = &priv->interfaces[iface]; - - if (dev_handle->claimed_interfaces & (1 << iface)) { - for (i = 0 ; i < cInterface->num_endpoints ; i++) { - if (cInterface->endpoint_addrs[i] == ep) { - *pipep = i + 1; - - if (ifcp) - *ifcp = iface; - - if (interface_out) - *interface_out = cInterface; - - usbi_dbg ("pipe %d on interface %d matches", *pipep, iface); - return 0; - } - } - } - } - - /* No pipe found with the correct endpoint address */ - usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); - - return LIBUSB_ERROR_NOT_FOUND; -} - -static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) { - CFMutableDictionaryRef matchingDict = IOServiceMatching(darwin_device_class); - - if (!matchingDict) - return kIOReturnError; - - if (location) { - CFMutableDictionaryRef propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (propertyMatchDict) { - /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this - internally (CFNumberType of locationID is 3) */ - CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location); - - CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF); - /* release our reference to the CFNumber (CFDictionarySetValue retains it) */ - CFRelease (locationCF); - - CFDictionarySetValue (matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); - /* release out reference to the CFMutableDictionaryRef (CFDictionarySetValue retains it) */ - CFRelease (propertyMatchDict); - } - /* else we can still proceed as long as the caller accounts for the possibility of other devices in the iterator */ - } - - return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator); -} - -/* Returns 1 on success, 0 on failure. */ -static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) { - CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); - int ret = 0; - - if (cfNumber) { - if (CFGetTypeID(cfNumber) == CFNumberGetTypeID()) { - ret = CFNumberGetValue(cfNumber, type, p); - } - - CFRelease (cfNumber); - } - - return ret; -} - -static int get_ioregistry_value_data (io_service_t service, CFStringRef property, ssize_t size, void *p) { - CFTypeRef cfData = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0); - int ret = 0; - - if (cfData) { - if (CFGetTypeID (cfData) == CFDataGetTypeID ()) { - CFIndex length = CFDataGetLength (cfData); - if (length < size) { - size = length; - } - - CFDataGetBytes (cfData, CFRangeMake(0, size), p); - ret = 1; - } - - CFRelease (cfData); - } - - return ret; -} - -static usb_device_t **darwin_device_from_service (io_service_t service) -{ - io_cf_plugin_ref_t *plugInInterface = NULL; - usb_device_t **device; - kern_return_t result; - SInt32 score; - - result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, &plugInInterface, - &score); - - if (kIOReturnSuccess != result || !plugInInterface) { - usbi_dbg ("could not set up plugin for service: %s", darwin_error_str (result)); - return NULL; - } - - (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID), - (LPVOID)&device); - /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ - (*plugInInterface)->Release (plugInInterface); - - return device; -} - -static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) { - struct libusb_context *ctx; - io_service_t service; - - usbi_mutex_lock(&active_contexts_lock); - - while ((service = IOIteratorNext(add_devices))) { - /* add this device to each active context's device list */ - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - process_new_device (ctx, service);; - } - - IOObjectRelease(service); - } - - usbi_mutex_unlock(&active_contexts_lock); -} - -static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { - struct libusb_device *dev = NULL; - struct libusb_context *ctx; - struct darwin_cached_device *old_device; - - io_service_t device; - UInt64 session; - int ret; - - usbi_mutex_lock(&active_contexts_lock); - - while ((device = IOIteratorNext (rem_devices)) != 0) { - /* get the location from the i/o registry */ - ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session); - IOObjectRelease (device); - if (!ret) - continue; - - /* we need to match darwin_ref_cached_device call made in darwin_get_cached_device function - otherwise no cached device will ever get freed */ - usbi_mutex_lock(&darwin_cached_devices_lock); - list_for_each_entry(old_device, &darwin_cached_devices, list, struct darwin_cached_device) { - if (old_device->session == session) { - darwin_deref_cached_device (old_device); - break; - } - } - usbi_mutex_unlock(&darwin_cached_devices_lock); - - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - usbi_dbg ("notifying context %p of device disconnect", ctx); - - dev = usbi_get_device_by_session_id(ctx, (unsigned long) session); - if (dev) { - /* signal the core that this device has been disconnected. the core will tear down this device - when the reference count reaches 0 */ - usbi_disconnect_device(dev); - libusb_unref_device(dev); - } - } - } - - usbi_mutex_unlock(&active_contexts_lock); -} - -static void darwin_hotplug_poll (void) -{ - /* not sure if 5 seconds will be too long/short but it should work ok */ - mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0}; - - /* since a kernel thread may nodify the IOInterators used for - * hotplug notidication we can't just clear the iterators. - * instead just wait until all IOService providers are quiet */ - (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout); -} - -static void darwin_clear_iterator (io_iterator_t iter) { - io_service_t device; - - while ((device = IOIteratorNext (iter)) != 0) - IOObjectRelease (device); -} - -static void *darwin_event_thread_main (void *arg0) { - IOReturn kresult; - struct libusb_context *ctx = (struct libusb_context *)arg0; - CFRunLoopRef runloop; - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - /* Set this thread's name, so it can be seen in the debugger - and crash reports. */ - pthread_setname_np ("org.libusb.device-hotplug"); -#endif - -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 && MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - /* Tell the Objective-C garbage collector about this thread. - This is required because, unlike NSThreads, pthreads are - not automatically registered. Although we don't use - Objective-C, we use CoreFoundation, which does. - Garbage collection support was entirely removed in 10.12, - so don't bother there. */ - objc_registerThreadWithCollector(); -#endif - - /* hotplug (device arrival/removal) sources */ - CFRunLoopSourceContext libusb_shutdown_cfsourcectx; - CFRunLoopSourceRef libusb_notification_cfsource; - io_notification_port_t libusb_notification_port; - io_iterator_t libusb_rem_device_iterator; - io_iterator_t libusb_add_device_iterator; - - usbi_dbg ("creating hotplug event source"); - - runloop = CFRunLoopGetCurrent (); - CFRetain (runloop); - - /* add the shutdown cfsource to the run loop */ - memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx)); - libusb_shutdown_cfsourcectx.info = runloop; - libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop; - libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx); - CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); - - /* add the notification port to the run loop */ - libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault); - libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port); - CFRunLoopAddSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); - - /* create notifications for removed devices */ - kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification, - IOServiceMatching(darwin_device_class), - darwin_devices_detached, - ctx, &libusb_rem_device_iterator); - - if (kresult != kIOReturnSuccess) { - usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); - - pthread_exit (NULL); - } - - /* create notifications for attached devices */ - kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification, - IOServiceMatching(darwin_device_class), - darwin_devices_attached, - ctx, &libusb_add_device_iterator); - - if (kresult != kIOReturnSuccess) { - usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); - - pthread_exit (NULL); - } - - /* arm notifiers */ - darwin_clear_iterator (libusb_rem_device_iterator); - darwin_clear_iterator (libusb_add_device_iterator); - - usbi_dbg ("darwin event thread ready to receive events"); - - /* signal the main thread that the hotplug runloop has been created. */ - pthread_mutex_lock (&libusb_darwin_at_mutex); - libusb_darwin_acfl = runloop; - pthread_cond_signal (&libusb_darwin_at_cond); - pthread_mutex_unlock (&libusb_darwin_at_mutex); - - /* run the runloop */ - CFRunLoopRun(); - - usbi_dbg ("darwin event thread exiting"); - - /* remove the notification cfsource */ - CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode); - - /* remove the shutdown cfsource */ - CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode); - - /* delete notification port */ - IONotificationPortDestroy (libusb_notification_port); - - /* delete iterators */ - IOObjectRelease (libusb_rem_device_iterator); - IOObjectRelease (libusb_add_device_iterator); - - CFRelease (libusb_darwin_acfls); - CFRelease (runloop); - - libusb_darwin_acfls = NULL; - libusb_darwin_acfl = NULL; - - pthread_exit (NULL); -} - -/* cleanup function to destroy cached devices */ -static void __attribute__((destructor)) _darwin_finalize(void) { - struct darwin_cached_device *dev, *next; - - usbi_mutex_lock(&darwin_cached_devices_lock); - list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) { - darwin_deref_cached_device(dev); - } - usbi_mutex_unlock(&darwin_cached_devices_lock); -} - -static void darwin_check_version (void) { - /* adjust for changes in the USB stack in xnu 15 */ - int sysctl_args[] = {CTL_KERN, KERN_OSRELEASE}; - long version; - char version_string[256] = {'\0',}; - size_t length = 256; - - sysctl(sysctl_args, 2, version_string, &length, NULL, 0); - - errno = 0; - version = strtol (version_string, NULL, 10); - if (0 == errno && version >= 15) { - darwin_device_class = "IOUSBHostDevice"; - } -} - -static int darwin_init(struct libusb_context *ctx) { - host_name_port_t host_self; - int rc; - - rc = pthread_once (&darwin_init_once, darwin_check_version); - if (rc) { - return LIBUSB_ERROR_OTHER; - } - - rc = darwin_scan_devices (ctx); - if (LIBUSB_SUCCESS != rc) { - return rc; - } - - if (libusb_darwin_atomic_fetch_add (&initCount, 1) == 0) { - /* create the clocks that will be used */ - - host_self = mach_host_self(); - host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime); - host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic); - mach_port_deallocate(mach_task_self(), host_self); - - pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, ctx); - - pthread_mutex_lock (&libusb_darwin_at_mutex); - while (!libusb_darwin_acfl) - pthread_cond_wait (&libusb_darwin_at_cond, &libusb_darwin_at_mutex); - pthread_mutex_unlock (&libusb_darwin_at_mutex); - } - - return rc; -} - -static void darwin_exit (void) { - if (libusb_darwin_atomic_fetch_add (&initCount, -1) == 1) { - mach_port_deallocate(mach_task_self(), clock_realtime); - mach_port_deallocate(mach_task_self(), clock_monotonic); - - /* stop the event runloop and wait for the thread to terminate. */ - CFRunLoopSourceSignal(libusb_darwin_acfls); - CFRunLoopWakeUp (libusb_darwin_acfl); - pthread_join (libusb_darwin_at, NULL); - } -} - -static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - - /* return cached copy */ - memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH); - - *host_endian = 0; - - return 0; -} - -static int get_configuration_index (struct libusb_device *dev, int config_value) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - UInt8 i, numConfig; - IOUSBConfigurationDescriptorPtr desc; - IOReturn kresult; - - /* is there a simpler way to determine the index? */ - kresult = (*(priv->device))->GetNumberOfConfigurations (priv->device, &numConfig); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - for (i = 0 ; i < numConfig ; i++) { - (*(priv->device))->GetConfigurationDescriptorPtr (priv->device, i, &desc); - - if (desc->bConfigurationValue == config_value) - return i; - } - - /* configuration not found */ - return LIBUSB_ERROR_NOT_FOUND; -} - -static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - int config_index; - - if (0 == priv->active_config) - return LIBUSB_ERROR_NOT_FOUND; - - config_index = get_configuration_index (dev, priv->active_config); - if (config_index < 0) - return config_index; - - return darwin_get_config_descriptor (dev, config_index, buffer, len, host_endian); -} - -static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) { - struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev); - IOUSBConfigurationDescriptorPtr desc; - IOReturn kresult; - int ret; - - if (!priv || !priv->device) - return LIBUSB_ERROR_OTHER; - - kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, config_index, &desc); - if (kresult == kIOReturnSuccess) { - /* copy descriptor */ - if (libusb_le16_to_cpu(desc->wTotalLength) < len) - len = libusb_le16_to_cpu(desc->wTotalLength); - - memmove (buffer, desc, len); - - /* GetConfigurationDescriptorPtr returns the descriptor in USB bus order */ - *host_endian = 0; - } - - ret = darwin_to_libusb (kresult); - if (ret != LIBUSB_SUCCESS) - return ret; - - return (int) len; -} - -/* check whether the os has configured the device */ -static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) { - usb_device_t **darwin_device = dev->device; - - IOUSBConfigurationDescriptorPtr configDesc; - IOUSBFindInterfaceRequest request; - kern_return_t kresult; - io_iterator_t interface_iterator; - io_service_t firstInterface; - - if (dev->dev_descriptor.bNumConfigurations < 1) { - usbi_err (ctx, "device has no configurations"); - return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */ - } - - /* checking the configuration of a root hub simulation takes ~1 s in 10.11. the device is - not usable anyway */ - if (0x05ac == dev->dev_descriptor.idVendor && 0x8005 == dev->dev_descriptor.idProduct) { - usbi_dbg ("ignoring configuration on root hub simulation"); - dev->active_config = 0; - return 0; - } - - /* find the first configuration */ - kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc); - dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1; - - /* check if the device is already configured. there is probably a better way than iterating over the - to accomplish this (the trick is we need to avoid a call to GetConfigurations since buggy devices - might lock up on the device request) */ - - /* Setup the Interface Request */ - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); - if (kresult) - return darwin_to_libusb (kresult); - - /* iterate once */ - firstInterface = IOIteratorNext(interface_iterator); - - /* done with the interface iterator */ - IOObjectRelease(interface_iterator); - - if (firstInterface) { - IOObjectRelease (firstInterface); - - /* device is configured */ - if (dev->dev_descriptor.bNumConfigurations == 1) - /* to avoid problems with some devices get the configurations value from the configuration descriptor */ - dev->active_config = dev->first_config; - else - /* devices with more than one configuration should work with GetConfiguration */ - (*darwin_device)->GetConfiguration (darwin_device, &dev->active_config); - } else - /* not configured */ - dev->active_config = 0; - - usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config); - - return 0; -} - -static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) { - IOUSBDevRequestTO req; - - memset (buffer, 0, buffer_size); - - /* Set up request for descriptor/ */ - req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); - req.bRequest = kUSBRqGetDescriptor; - req.wValue = desc << 8; - req.wIndex = desc_index; - req.wLength = buffer_size; - req.pData = buffer; - req.noDataTimeout = 20; - req.completionTimeout = 100; - - return (*device)->DeviceRequestTO (device, &req); -} - -static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) { - usb_device_t **device = dev->device; - int retries = 1, delay = 30000; - int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1; - int is_open = 0; - int ret = 0, ret2; - UInt8 bDeviceClass; - UInt16 idProduct, idVendor; - - dev->can_enumerate = 0; - - (*device)->GetDeviceClass (device, &bDeviceClass); - (*device)->GetDeviceProduct (device, &idProduct); - (*device)->GetDeviceVendor (device, &idVendor); - - /* According to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some - * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request. Still, - * to follow the spec as closely as possible, try opening the device */ - is_open = ((*device)->USBDeviceOpenSeize(device) == kIOReturnSuccess); - - do { - /**** retrieve device descriptor ****/ - ret = darwin_request_descriptor (device, kUSBDeviceDesc, 0, &dev->dev_descriptor, sizeof(dev->dev_descriptor)); - - if (kIOReturnOverrun == ret && kUSBDeviceDesc == dev->dev_descriptor.bDescriptorType) - /* received an overrun error but we still received a device descriptor */ - ret = kIOReturnSuccess; - - if (kIOUSBVendorIDAppleComputer == idVendor) { - /* NTH: don't bother retrying or unsuspending Apple devices */ - break; - } - - if (kIOReturnSuccess == ret && (0 == dev->dev_descriptor.bNumConfigurations || - 0 == dev->dev_descriptor.bcdUSB)) { - /* work around for incorrectly configured devices */ - if (try_reconfigure && is_open) { - usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again..."); - - /* set the first configuration */ - (*device)->SetConfiguration(device, 1); - - /* don't try to reconfigure again */ - try_reconfigure = 0; - } - - ret = kIOUSBPipeStalled; - } - - if (kIOReturnSuccess != ret && is_open && try_unsuspend) { - /* device may be suspended. unsuspend it and try again */ -#if DeviceVersion >= 320 - UInt32 info = 0; - - /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */ - (void)(*device)->GetUSBDeviceInformation (device, &info); - - /* note that the device was suspended */ - if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info) - try_unsuspend = 1; -#endif - - if (try_unsuspend) { - /* try to unsuspend the device */ - ret2 = (*device)->USBDeviceSuspend (device, 0); - if (kIOReturnSuccess != ret2) { - /* prevent log spew from poorly behaving devices. this indicates the - os actually had trouble communicating with the device */ - usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2)); - } else - unsuspended = 1; - - try_unsuspend = 0; - } - } - - if (kIOReturnSuccess != ret) { - usbi_dbg("kernel responded with code: 0x%08x. sleeping for %d ms before trying again", ret, delay/1000); - /* sleep for a little while before trying again */ - nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); - } - } while (kIOReturnSuccess != ret && retries--); - - if (unsuspended) - /* resuspend the device */ - (void)(*device)->USBDeviceSuspend (device, 1); - - if (is_open) - (void) (*device)->USBDeviceClose (device); - - if (ret != kIOReturnSuccess) { - /* a debug message was already printed out for this error */ - if (LIBUSB_CLASS_HUB == bDeviceClass) - usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", - idVendor, idProduct, darwin_error_str (ret), ret); - else - usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device", - idVendor, idProduct, darwin_error_str (ret), ret); - return darwin_to_libusb (ret); - } - - /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ - if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) { - /* not a valid device */ - usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", - idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct)); - return LIBUSB_ERROR_NO_DEVICE; - } - - usbi_dbg ("cached device descriptor:"); - usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType); - usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB); - usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass); - usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass); - usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol); - usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0); - usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor); - usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct); - usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice); - usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer); - usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct); - usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber); - usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations); - - dev->can_enumerate = 1; - - return LIBUSB_SUCCESS; -} - -static int get_device_port (io_service_t service, UInt8 *port) { - kern_return_t result; - io_service_t parent; - int ret = 0; - - if (get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, port)) { - return 1; - } - - result = IORegistryEntryGetParentEntry (service, kIOServicePlane, &parent); - if (kIOReturnSuccess == result) { - ret = get_ioregistry_value_data (parent, CFSTR("port"), 1, port); - IOObjectRelease (parent); - } - - return ret; -} - -static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service, - struct darwin_cached_device **cached_out) { - struct darwin_cached_device *new_device; - UInt64 sessionID = 0, parent_sessionID = 0; - int ret = LIBUSB_SUCCESS; - usb_device_t **device; - io_service_t parent; - kern_return_t result; - UInt8 port = 0; - - /* get some info from the io registry */ - (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID); - if (!get_device_port (service, &port)) { - usbi_dbg("could not get connected port number"); - } - - usbi_dbg("finding cached device for sessionID 0x%" PRIx64, sessionID); - - result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent); - - if (kIOReturnSuccess == result) { - (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID); - IOObjectRelease(parent); - } - - usbi_mutex_lock(&darwin_cached_devices_lock); - do { - *cached_out = NULL; - - list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) { - usbi_dbg("matching sessionID 0x%" PRIx64 " against cached device with sessionID 0x%" PRIx64, sessionID, new_device->session); - if (new_device->session == sessionID) { - usbi_dbg("using cached device for device"); - *cached_out = new_device; - break; - } - } - - if (*cached_out) - break; - - usbi_dbg("caching new device with sessionID 0x%" PRIx64, sessionID); - - device = darwin_device_from_service (service); - if (!device) { - ret = LIBUSB_ERROR_NO_DEVICE; - break; - } - - new_device = calloc (1, sizeof (*new_device)); - if (!new_device) { - ret = LIBUSB_ERROR_NO_MEM; - break; - } - - /* add this device to the cached device list */ - list_add(&new_device->list, &darwin_cached_devices); - - (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address); - - /* keep a reference to this device */ - darwin_ref_cached_device(new_device); - - new_device->device = device; - new_device->session = sessionID; - (*device)->GetLocationID (device, &new_device->location); - new_device->port = port; - new_device->parent_session = parent_sessionID; - - /* cache the device descriptor */ - ret = darwin_cache_device_descriptor(ctx, new_device); - if (ret) - break; - - if (new_device->can_enumerate) { - snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address, - new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct, - new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass); - } - } while (0); - - usbi_mutex_unlock(&darwin_cached_devices_lock); - - /* keep track of devices regardless of if we successfully enumerate them to - prevent them from being enumerated multiple times */ - - *cached_out = new_device; - - return ret; -} - -static int process_new_device (struct libusb_context *ctx, io_service_t service) { - struct darwin_device_priv *priv; - struct libusb_device *dev = NULL; - struct darwin_cached_device *cached_device; - UInt8 devSpeed; - int ret = 0; - - do { - ret = darwin_get_cached_device (ctx, service, &cached_device); - - if (ret < 0 || !cached_device->can_enumerate) { - return ret; - } - - /* check current active configuration (and cache the first configuration value-- - which may be used by claim_interface) */ - ret = darwin_check_configuration (ctx, cached_device); - if (ret) - break; - - usbi_dbg ("allocating new device in context %p for with session 0x%" PRIx64, - ctx, cached_device->session); - - dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session); - if (!dev) { - return LIBUSB_ERROR_NO_MEM; - } - - priv = (struct darwin_device_priv *)dev->os_priv; - - priv->dev = cached_device; - darwin_ref_cached_device (priv->dev); - - if (cached_device->parent_session > 0) { - dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session); - } else { - dev->parent_dev = NULL; - } - dev->port_number = cached_device->port; - dev->bus_number = cached_device->location >> 24; - dev->device_address = cached_device->address; - - (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed); - - switch (devSpeed) { - case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break; - case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break; - case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break; -#if DeviceVersion >= 500 - case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break; -#endif - default: - usbi_warn (ctx, "Got unknown device speed %d", devSpeed); - } - - ret = usbi_sanitize_device (dev); - if (ret < 0) - break; - - usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address, - dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path); - } while (0); - - if (0 == ret) { - usbi_connect_device (dev); - } else { - libusb_unref_device (dev); - } - - return ret; -} - -static int darwin_scan_devices(struct libusb_context *ctx) { - io_iterator_t deviceIterator; - io_service_t service; - kern_return_t kresult; - - kresult = usb_setup_device_iterator (&deviceIterator, 0); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - while ((service = IOIteratorNext (deviceIterator))) { - (void) process_new_device (ctx, service); - - IOObjectRelease(service); - } - - IOObjectRelease(deviceIterator); - - return 0; -} - -static int darwin_open (struct libusb_device_handle *dev_handle) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOReturn kresult; - - if (0 == dpriv->open_count) { - /* try to open the device */ - kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); - if (kresult != kIOReturnSuccess) { - usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); - - if (kIOReturnExclusiveAccess != kresult) { - return darwin_to_libusb (kresult); - } - - /* it is possible to perform some actions on a device that is not open so do not return an error */ - priv->is_open = 0; - } else { - priv->is_open = 1; - } - - /* create async event source */ - kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource); - if (kresult != kIOReturnSuccess) { - usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult)); - - if (priv->is_open) { - (*(dpriv->device))->USBDeviceClose (dpriv->device); - } - - priv->is_open = 0; - - return darwin_to_libusb (kresult); - } - - CFRetain (libusb_darwin_acfl); - - /* add the cfSource to the aync run loop */ - CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes); - } - - /* device opened successfully */ - dpriv->open_count++; - - usbi_dbg ("device open for access"); - - return 0; -} - -static void darwin_close (struct libusb_device_handle *dev_handle) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOReturn kresult; - int i; - - if (dpriv->open_count == 0) { - /* something is probably very wrong if this is the case */ - usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!"); - return; - } - - dpriv->open_count--; - - /* make sure all interfaces are released */ - for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) - libusb_release_interface (dev_handle, i); - - if (0 == dpriv->open_count) { - /* delete the device's async event source */ - if (priv->cfSource) { - CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode); - CFRelease (priv->cfSource); - priv->cfSource = NULL; - CFRelease (libusb_darwin_acfl); - } - - if (priv->is_open) { - /* close the device */ - kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device); - if (kresult) { - /* Log the fact that we had a problem closing the file, however failing a - * close isn't really an error, so return success anyway */ - usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); - } - } - } -} - -static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - - *config = (int) dpriv->active_config; - - return 0; -} - -static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOReturn kresult; - int i; - - /* Setting configuration will invalidate the interface, so we need - to reclaim it. First, dispose of existing interfaces, if any. */ - for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) - darwin_release_interface (dev_handle, i); - - kresult = (*(dpriv->device))->SetConfiguration (dpriv->device, config); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - /* Reclaim any interfaces. */ - for (i = 0 ; i < USB_MAXINTERFACES ; i++) - if (dev_handle->claimed_interfaces & (1 << i)) - darwin_claim_interface (dev_handle, i); - - dpriv->active_config = config; - - return 0; -} - -static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) { - IOUSBFindInterfaceRequest request; - kern_return_t kresult; - io_iterator_t interface_iterator; - UInt8 bInterfaceNumber; - int ret; - - *usbInterfacep = IO_OBJECT_NULL; - - /* Setup the Interface Request */ - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - kresult = (*(darwin_device))->CreateInterfaceIterator(darwin_device, &request, &interface_iterator); - if (kresult) - return kresult; - - while ((*usbInterfacep = IOIteratorNext(interface_iterator))) { - /* find the interface number */ - ret = get_ioregistry_value_number (*usbInterfacep, CFSTR("bInterfaceNumber"), kCFNumberSInt8Type, - &bInterfaceNumber); - - if (ret && bInterfaceNumber == ifc) { - break; - } - - (void) IOObjectRelease (*usbInterfacep); - } - - /* done with the interface iterator */ - IOObjectRelease(interface_iterator); - - return 0; -} - -static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - kern_return_t kresult; - - u_int8_t numep, direction, number; - u_int8_t dont_care1, dont_care3; - u_int16_t dont_care2; - int rc; - - usbi_dbg ("building table of endpoints."); - - /* retrieve the total number of endpoints on this interface */ - kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - /* iterate through pipe references */ - for (int i = 1 ; i <= numep ; i++) { - kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1, - &dont_care2, &dont_care3); - - if (kresult != kIOReturnSuccess) { - /* probably a buggy device. try to get the endpoint address from the descriptors */ - struct libusb_config_descriptor *config; - const struct libusb_endpoint_descriptor *endpoint_desc; - UInt8 alt_setting; - - kresult = (*(cInterface->interface))->GetAlternateSetting (cInterface->interface, &alt_setting); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "can't get alternate setting for interface"); - return darwin_to_libusb (kresult); - } - - rc = libusb_get_active_config_descriptor (dev_handle->dev, &config); - if (LIBUSB_SUCCESS != rc) { - return rc; - } - - endpoint_desc = config->interface[iface].altsetting[alt_setting].endpoint + i - 1; - - cInterface->endpoint_addrs[i - 1] = endpoint_desc->bEndpointAddress; - } else { - cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); - } - - usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, cInterface->endpoint_addrs[i - 1] >> kUSBRqDirnShift, - cInterface->endpoint_addrs[i - 1] & LIBUSB_ENDPOINT_ADDRESS_MASK); - } - - cInterface->num_endpoints = numep; - - return 0; -} - -static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - io_service_t usbInterface = IO_OBJECT_NULL; - IOReturn kresult; - IOCFPlugInInterface **plugInInterface = NULL; - SInt32 score; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); - if (kresult != kIOReturnSuccess) - return darwin_to_libusb (kresult); - - /* make sure we have an interface */ - if (!usbInterface && dpriv->first_config != 0) { - usbi_info (HANDLE_CTX (dev_handle), "no interface found; setting configuration: %d", dpriv->first_config); - - /* set the configuration */ - kresult = darwin_set_configuration (dev_handle, dpriv->first_config); - if (kresult != LIBUSB_SUCCESS) { - usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); - return kresult; - } - - kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - } - - if (!usbInterface) { - usbi_err (HANDLE_CTX (dev_handle), "interface not found"); - return LIBUSB_ERROR_NOT_FOUND; - } - - /* get an interface to the device's interface */ - kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, &plugInInterface, &score); - - /* ignore release error */ - (void)IOObjectRelease (usbInterface); - - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - if (!plugInInterface) { - usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); - return LIBUSB_ERROR_NOT_FOUND; - } - - /* Do the actual claim */ - kresult = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - (LPVOID)&cInterface->interface); - /* We no longer need the intermediate plug-in */ - /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */ - (*plugInInterface)->Release (plugInInterface); - if (kresult || !cInterface->interface) { - usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - /* claim the interface */ - kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); - return darwin_to_libusb (kresult); - } - - /* update list of endpoints */ - kresult = get_endpoints (dev_handle, iface); - if (kresult) { - /* this should not happen */ - darwin_release_interface (dev_handle, iface); - usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); - return kresult; - } - - cInterface->cfSource = NULL; - - /* create async event source */ - kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); - if (kresult != kIOReturnSuccess) { - usbi_err (HANDLE_CTX (dev_handle), "could not create async event source"); - - /* can't continue without an async event source */ - (void)darwin_release_interface (dev_handle, iface); - - return darwin_to_libusb (kresult); - } - - /* add the cfSource to the async thread's run loop */ - CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - - usbi_dbg ("interface opened"); - - return 0; -} - -static int darwin_release_interface(struct libusb_device_handle *dev_handle, int iface) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - IOReturn kresult; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - /* Check to see if an interface is open */ - if (!cInterface->interface) - return LIBUSB_SUCCESS; - - /* clean up endpoint data */ - cInterface->num_endpoints = 0; - - /* delete the interface's async event source */ - if (cInterface->cfSource) { - CFRunLoopRemoveSource (libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - CFRelease (cInterface->cfSource); - } - - kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); - if (kresult) - usbi_warn (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); - - kresult = (*(cInterface->interface))->Release(cInterface->interface); - if (kresult != kIOReturnSuccess) - usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); - - cInterface->interface = (usb_interface_t **) IO_OBJECT_NULL; - - return darwin_to_libusb (kresult); -} - -static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) { - struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv; - IOReturn kresult; - - /* current interface */ - struct darwin_interface *cInterface = &priv->interfaces[iface]; - - if (!cInterface->interface) - return LIBUSB_ERROR_NO_DEVICE; - - kresult = (*(cInterface->interface))->SetAlternateInterface (cInterface->interface, altsetting); - if (kresult != kIOReturnSuccess) - darwin_reset_device (dev_handle); - - /* update list of endpoints */ - kresult = get_endpoints (dev_handle, iface); - if (kresult) { - /* this should not happen */ - darwin_release_interface (dev_handle, iface); - usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); - return kresult; - } - - return darwin_to_libusb (kresult); -} - -static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { - /* current interface */ - struct darwin_interface *cInterface; - IOReturn kresult; - uint8_t pipeRef; - - /* determine the interface/endpoint to use */ - if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - /* newer versions of darwin support clearing additional bits on the device's endpoint */ - kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); - if (kresult) - usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); - - return darwin_to_libusb (kresult); -} - -static int darwin_reset_device(struct libusb_device_handle *dev_handle) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - IOUSBDeviceDescriptor descriptor; - IOUSBConfigurationDescriptorPtr cached_configuration; - IOUSBConfigurationDescriptor configuration; - bool reenumerate = false; - IOReturn kresult; - int i; - - kresult = (*(dpriv->device))->ResetDevice (dpriv->device); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); - return darwin_to_libusb (kresult); - } - - do { - usbi_dbg ("darwin/reset_device: checking if device descriptor changed"); - - /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */ - (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor)); - - /* check if the device descriptor has changed */ - if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) { - reenumerate = true; - break; - } - - /* check if any configuration descriptor has changed */ - for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) { - usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i); - - (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration)); - (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration); - - if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) { - reenumerate = true; - break; - } - } - } while (0); - - if (reenumerate) { - usbi_dbg ("darwin/reset_device: device requires reenumeration"); - (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg ("darwin/reset_device: device reset complete"); - - return LIBUSB_SUCCESS; -} - -static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) { - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev); - io_service_t usbInterface; - CFTypeRef driver; - IOReturn kresult; - - kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); - if (kresult) { - usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); - - return darwin_to_libusb (kresult); - } - - driver = IORegistryEntryCreateCFProperty (usbInterface, kIOBundleIdentifierKey, kCFAllocatorDefault, 0); - IOObjectRelease (usbInterface); - - if (driver) { - CFRelease (driver); - - return 1; - } - - /* no driver */ - return 0; -} - -/* attaching/detaching kernel drivers is not currently supported (maybe in the future?) */ -static int darwin_attach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { - UNUSED(dev_handle); - UNUSED(interface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle, int interface) { - UNUSED(dev_handle); - UNUSED(interface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static void darwin_destroy_device(struct libusb_device *dev) { - struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv; - - if (dpriv->dev) { - /* need to hold the lock in case this is the last reference to the device */ - usbi_mutex_lock(&darwin_cached_devices_lock); - darwin_deref_cached_device (dpriv->dev); - dpriv->dev = NULL; - usbi_mutex_unlock(&darwin_cached_devices_lock); - } -} - -static int submit_bulk_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - IOReturn ret; - uint8_t transferType; - /* None of the values below are used in libusbx for bulk transfers */ - uint8_t direction, number, interval, pipeRef; - uint16_t maxPacketSize; - - struct darwin_interface *cInterface; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); - - if (ret) { - usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(ret), ret); - return darwin_to_libusb (ret); - } - - if (0 != (transfer->length % maxPacketSize)) { - /* do not need a zero packet */ - transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET; - } - - /* submit the request */ - /* timeouts are unavailable on interrupt endpoints */ - if (transferType == kUSBInterrupt) { - if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, darwin_async_io_callback, itransfer); - else - ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, darwin_async_io_callback, itransfer); - } else { - itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; - - if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, (void *)itransfer); - else - ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer, - transfer->length, transfer->timeout, transfer->timeout, - darwin_async_io_callback, (void *)itransfer); - } - - if (ret) - usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(ret), ret); - - return darwin_to_libusb (ret); -} - -#if InterfaceVersion >= 550 -static int submit_stream_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_interface *cInterface; - uint8_t pipeRef; - IOReturn ret; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; - - if (IS_XFERIN(transfer)) - ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, (void *)itransfer); - else - ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, - transfer->buffer, transfer->length, transfer->timeout, - transfer->timeout, darwin_async_io_callback, (void *)itransfer); - - if (ret) - usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(ret), ret); - - return darwin_to_libusb (ret); -} -#endif - -static int submit_iso_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - IOReturn kresult; - uint8_t direction, number, interval, pipeRef, transferType; - uint16_t maxPacketSize; - UInt64 frame; - AbsoluteTime atTime; - int i; - - struct darwin_interface *cInterface; - - /* construct an array of IOUSBIsocFrames, reuse the old one if possible */ - if (tpriv->isoc_framelist && tpriv->num_iso_packets != transfer->num_iso_packets) { - free(tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - } - - if (!tpriv->isoc_framelist) { - tpriv->num_iso_packets = transfer->num_iso_packets; - tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame)); - if (!tpriv->isoc_framelist) - return LIBUSB_ERROR_NO_MEM; - } - - /* copy the frame list from the libusb descriptor (the structures differ only is member order) */ - for (i = 0 ; i < transfer->num_iso_packets ; i++) - tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length; - - /* determine the interface/endpoint to use */ - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - /* determine the properties of this endpoint and the speed of the device */ - (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); - - /* Last but not least we need the bus frame number */ - kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); - if (kresult) { - usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); - free(tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - - return darwin_to_libusb (kresult); - } - - (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number, - &transferType, &maxPacketSize, &interval); - - /* schedule for a frame a little in the future */ - frame += 4; - - if (cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint]) - frame = cInterface->frames[transfer->endpoint]; - - /* submit the request */ - if (IS_XFERIN(transfer)) - kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, - itransfer); - else - kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame, - transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback, - itransfer); - - if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed) - /* Full speed */ - cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)); - else - /* High/super speed */ - cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8; - - if (kresult != kIOReturnSuccess) { - usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out", - darwin_error_str(kresult)); - free (tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - } - - return darwin_to_libusb (kresult); -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer; - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - IOReturn kresult; - - memset(&tpriv->req, 0, sizeof(tpriv->req)); - - /* IOUSBDeviceInterface expects the request in cpu endianness */ - tpriv->req.bmRequestType = setup->bmRequestType; - tpriv->req.bRequest = setup->bRequest; - /* these values should be in bus order from libusb_fill_control_setup */ - tpriv->req.wValue = OSSwapLittleToHostInt16 (setup->wValue); - tpriv->req.wIndex = OSSwapLittleToHostInt16 (setup->wIndex); - tpriv->req.wLength = OSSwapLittleToHostInt16 (setup->wLength); - /* data is stored after the libusb control block */ - tpriv->req.pData = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - tpriv->req.completionTimeout = transfer->timeout; - tpriv->req.noDataTimeout = transfer->timeout; - - itransfer->timeout_flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; - - /* all transfers in libusb-1.0 are async */ - - if (transfer->endpoint) { - struct darwin_interface *cInterface; - uint8_t pipeRef; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer); - } else - /* control request on endpoint 0 */ - kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); - - if (kresult != kIOReturnSuccess) - usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); - - return darwin_to_libusb (kresult); -} - -static int darwin_submit_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: -#if InterfaceVersion >= 550 - return submit_stream_transfer(itransfer); -#else - usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers"); - return LIBUSB_ERROR_NOT_SUPPORTED; -#endif - default: - usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int cancel_control_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); - IOReturn kresult; - - usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe"); - - if (!dpriv->device) - return LIBUSB_ERROR_NO_DEVICE; - - kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); - - return darwin_to_libusb (kresult); -} - -static int darwin_abort_transfers (struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev); - struct darwin_interface *cInterface; - uint8_t pipeRef, iface; - IOReturn kresult; - - if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) { - usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); - - return LIBUSB_ERROR_NOT_FOUND; - } - - if (!dpriv->device) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef); - - /* abort transactions */ -#if InterfaceVersion >= 550 - if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type) - (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); - else -#endif - (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); - - usbi_dbg ("calling clear pipe stall to clear the data toggle bit"); - - /* newer versions of darwin support clearing additional bits on the device's endpoint */ - kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); - - return darwin_to_libusb (kresult); -} - -static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return cancel_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return darwin_abort_transfers (itransfer); - default: - usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static void darwin_clear_transfer_priv (struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && tpriv->isoc_framelist) { - free (tpriv->isoc_framelist); - tpriv->isoc_framelist = NULL; - } -} - -static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) { - struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon; - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - usbi_dbg ("an async io operation has completed"); - - /* if requested write a zero packet */ - if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - struct darwin_interface *cInterface; - uint8_t pipeRef; - - (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface); - - (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0); - } - - tpriv->result = result; - tpriv->size = (UInt32) (uintptr_t) arg0; - - /* signal the core that this transfer is complete */ - usbi_signal_transfer_completion(itransfer); -} - -static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) { - if (itransfer->timeout_flags & USBI_TRANSFER_TIMED_OUT) - result = kIOUSBTransactionTimeout; - - switch (result) { - case kIOReturnUnderrun: - case kIOReturnSuccess: - return LIBUSB_TRANSFER_COMPLETED; - case kIOReturnAborted: - return LIBUSB_TRANSFER_CANCELLED; - case kIOUSBPipeStalled: - usbi_dbg ("transfer error: pipe is stalled"); - return LIBUSB_TRANSFER_STALL; - case kIOReturnOverrun: - usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: data overrun"); - return LIBUSB_TRANSFER_OVERFLOW; - case kIOUSBTransactionTimeout: - usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: timed out"); - itransfer->timeout_flags |= USBI_TRANSFER_TIMED_OUT; - return LIBUSB_TRANSFER_TIMED_OUT; - default: - usbi_warn (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result); - return LIBUSB_TRANSFER_ERROR; - } -} - -static int darwin_handle_transfer_completion (struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int isIsoc = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type; - int isBulk = LIBUSB_TRANSFER_TYPE_BULK == transfer->type; - int isControl = LIBUSB_TRANSFER_TYPE_CONTROL == transfer->type; - int isInterrupt = LIBUSB_TRANSFER_TYPE_INTERRUPT == transfer->type; - int i; - - if (!isIsoc && !isBulk && !isControl && !isInterrupt) { - usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_dbg ("handling %s completion with kernel status %d", - isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", tpriv->result); - - if (kIOReturnSuccess == tpriv->result || kIOReturnUnderrun == tpriv->result) { - if (isIsoc && tpriv->isoc_framelist) { - /* copy isochronous results back */ - - for (i = 0; i < transfer->num_iso_packets ; i++) { - struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i]; - lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus); - lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount; - } - } else if (!isIsoc) - itransfer->transferred += tpriv->size; - } - - /* it is ok to handle cancelled transfers without calling usbi_handle_transfer_cancellation (we catch timeout transfers) */ - return usbi_handle_transfer_completion (itransfer, darwin_transfer_status (itransfer, tpriv->result)); -} - -static int darwin_clock_gettime(int clk_id, struct timespec *tp) { - mach_timespec_t sys_time; - clock_serv_t clock_ref; - - switch (clk_id) { - case USBI_CLOCK_REALTIME: - /* CLOCK_REALTIME represents time since the epoch */ - clock_ref = clock_realtime; - break; - case USBI_CLOCK_MONOTONIC: - /* use system boot time as reference for the monotonic clock */ - clock_ref = clock_monotonic; - break; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } - - clock_get_time (clock_ref, &sys_time); - - tp->tv_sec = sys_time.tv_sec; - tp->tv_nsec = sys_time.tv_nsec; - - return 0; -} - -#if InterfaceVersion >= 550 -static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, - int num_endpoints) { - struct darwin_interface *cInterface; - UInt32 supportsStreams; - uint8_t pipeRef; - int rc, i; - - /* find the mimimum number of supported streams on the endpoint list */ - for (i = 0 ; i < num_endpoints ; ++i) { - if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) { - return rc; - } - - (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); - if (num_streams > supportsStreams) - num_streams = supportsStreams; - } - - /* it is an error if any endpoint in endpoints does not support streams */ - if (0 == num_streams) - return LIBUSB_ERROR_INVALID_PARAM; - - /* create the streams */ - for (i = 0 ; i < num_endpoints ; ++i) { - (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface); - - rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams); - if (kIOReturnSuccess != rc) - return darwin_to_libusb(rc); - } - - return num_streams; -} - -static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) { - struct darwin_interface *cInterface; - UInt32 supportsStreams; - uint8_t pipeRef; - int rc; - - for (int i = 0 ; i < num_endpoints ; ++i) { - if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) - return rc; - - (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); - if (0 == supportsStreams) - return LIBUSB_ERROR_INVALID_PARAM; - - rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0); - if (kIOReturnSuccess != rc) - return darwin_to_libusb(rc); - } - - return LIBUSB_SUCCESS; -} -#endif - -const struct usbi_os_backend darwin_backend = { - .name = "Darwin", - .caps = 0, - .init = darwin_init, - .exit = darwin_exit, - .get_device_list = NULL, /* not needed */ - .get_device_descriptor = darwin_get_device_descriptor, - .get_active_config_descriptor = darwin_get_active_config_descriptor, - .get_config_descriptor = darwin_get_config_descriptor, - .hotplug_poll = darwin_hotplug_poll, - - .open = darwin_open, - .close = darwin_close, - .get_configuration = darwin_get_configuration, - .set_configuration = darwin_set_configuration, - .claim_interface = darwin_claim_interface, - .release_interface = darwin_release_interface, - - .set_interface_altsetting = darwin_set_interface_altsetting, - .clear_halt = darwin_clear_halt, - .reset_device = darwin_reset_device, - -#if InterfaceVersion >= 550 - .alloc_streams = darwin_alloc_streams, - .free_streams = darwin_free_streams, -#endif - - .kernel_driver_active = darwin_kernel_driver_active, - .detach_kernel_driver = darwin_detach_kernel_driver, - .attach_kernel_driver = darwin_attach_kernel_driver, - - .destroy_device = darwin_destroy_device, - - .submit_transfer = darwin_submit_transfer, - .cancel_transfer = darwin_cancel_transfer, - .clear_transfer_priv = darwin_clear_transfer_priv, - - .handle_transfer_completion = darwin_handle_transfer_completion, - - .clock_gettime = darwin_clock_gettime, - - .device_priv_size = sizeof(struct darwin_device_priv), - .device_handle_priv_size = sizeof(struct darwin_device_handle_priv), - .transfer_priv_size = sizeof(struct darwin_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/darwin_usb.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/darwin_usb.h deleted file mode 100644 index 118043421a3..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/darwin_usb.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * darwin backend for libusb 1.0 - * Copyright © 2008-2015 Nathan Hjelm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if !defined(LIBUSB_DARWIN_H) -#define LIBUSB_DARWIN_H - -#include "libusbi.h" - -#include -#include -#include -#include - -/* IOUSBInterfaceInferface */ -#if defined (kIOUSBInterfaceInterfaceID700) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 - -#define usb_interface_t IOUSBInterfaceInterface700 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID700 -#define InterfaceVersion 700 - -#elif defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 - -#define usb_interface_t IOUSBInterfaceInterface550 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 -#define InterfaceVersion 550 - -#elif defined (kIOUSBInterfaceInterfaceID500) - -#define usb_interface_t IOUSBInterfaceInterface500 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 -#define InterfaceVersion 500 - -#elif defined (kIOUSBInterfaceInterfaceID300) - -#define usb_interface_t IOUSBInterfaceInterface300 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 -#define InterfaceVersion 300 - -#elif defined (kIOUSBInterfaceInterfaceID245) - -#define usb_interface_t IOUSBInterfaceInterface245 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID245 -#define InterfaceVersion 245 - -#elif defined (kIOUSBInterfaceInterfaceID220) - -#define usb_interface_t IOUSBInterfaceInterface220 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 -#define InterfaceVersion 220 - -#else - -#error "IOUSBFamily is too old. Please upgrade your OS" - -#endif - -/* IOUSBDeviceInterface */ -#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 - -#define usb_device_t IOUSBDeviceInterface500 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 -#define DeviceVersion 500 - -#elif defined (kIOUSBDeviceInterfaceID320) - -#define usb_device_t IOUSBDeviceInterface320 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID320 -#define DeviceVersion 320 - -#elif defined (kIOUSBDeviceInterfaceID300) - -#define usb_device_t IOUSBDeviceInterface300 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID300 -#define DeviceVersion 300 - -#elif defined (kIOUSBDeviceInterfaceID245) - -#define usb_device_t IOUSBDeviceInterface245 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID245 -#define DeviceVersion 245 - -#elif defined (kIOUSBDeviceInterfaceID220) -#define usb_device_t IOUSBDeviceInterface197 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID197 -#define DeviceVersion 197 - -#else - -#error "IOUSBFamily is too old. Please upgrade your OS" - -#endif - -#if !defined(IO_OBJECT_NULL) -#define IO_OBJECT_NULL ((io_object_t) 0) -#endif - -typedef IOCFPlugInInterface *io_cf_plugin_ref_t; -typedef IONotificationPortRef io_notification_port_t; - -/* private structures */ -struct darwin_cached_device { - struct list_head list; - IOUSBDeviceDescriptor dev_descriptor; - UInt32 location; - UInt64 parent_session; - UInt64 session; - UInt16 address; - char sys_path[21]; - usb_device_t **device; - int open_count; - UInt8 first_config, active_config, port; - int can_enumerate; - int refcount; -}; - -struct darwin_device_priv { - struct darwin_cached_device *dev; -}; - -struct darwin_device_handle_priv { - int is_open; - CFRunLoopSourceRef cfSource; - - struct darwin_interface { - usb_interface_t **interface; - uint8_t num_endpoints; - CFRunLoopSourceRef cfSource; - uint64_t frames[256]; - uint8_t endpoint_addrs[USB_MAXENDPOINTS]; - } interfaces[USB_MAXINTERFACES]; -}; - -struct darwin_transfer_priv { - /* Isoc */ - IOUSBIsocFrame *isoc_framelist; - int num_iso_packets; - - /* Control */ - IOUSBDevRequestTO req; - - /* Bulk */ - - /* Completion status */ - IOReturn result; - UInt32 size; -}; - -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_pollfs.cpp b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_pollfs.cpp deleted file mode 100644 index e0c77132061..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_pollfs.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2007-2008, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Lotz - */ - -#include "haiku_usb.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class WatchedEntry { -public: - WatchedEntry(BMessenger *, entry_ref *); - ~WatchedEntry(); - bool EntryCreated(entry_ref *ref); - bool EntryRemoved(ino_t node); - bool InitCheck(); - -private: - BMessenger* fMessenger; - node_ref fNode; - bool fIsDirectory; - USBDevice* fDevice; - WatchedEntry* fEntries; - WatchedEntry* fLink; - bool fInitCheck; -}; - - -class RosterLooper : public BLooper { -public: - RosterLooper(USBRoster *); - void Stop(); - virtual void MessageReceived(BMessage *); - bool InitCheck(); - -private: - USBRoster* fRoster; - WatchedEntry* fRoot; - BMessenger* fMessenger; - bool fInitCheck; -}; - - -WatchedEntry::WatchedEntry(BMessenger *messenger, entry_ref *ref) - : fMessenger(messenger), - fIsDirectory(false), - fDevice(NULL), - fEntries(NULL), - fLink(NULL), - fInitCheck(false) -{ - BEntry entry(ref); - entry.GetNodeRef(&fNode); - - BDirectory directory; - if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) { - fIsDirectory = true; - - while (directory.GetNextEntry(&entry) >= B_OK) { - if (entry.GetRef(ref) < B_OK) - continue; - - WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); - if (child == NULL) - continue; - if (child->InitCheck() == false) { - delete child; - continue; - } - - child->fLink = fEntries; - fEntries = child; - } - - watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger); - } - else { - if (strncmp(ref->name, "raw", 3) == 0) - return; - - BPath path, parent_path; - entry.GetPath(&path); - fDevice = new(std::nothrow) USBDevice(path.Path()); - if (fDevice != NULL && fDevice->InitCheck() == true) { - // Add this new device to each active context's device list - struct libusb_context *ctx; - unsigned long session_id = (unsigned long)&fDevice; - - usbi_mutex_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev) { - usbi_dbg("using previously allocated device with location %lu", session_id); - libusb_unref_device(dev); - continue; - } - usbi_dbg("allocating new device with location %lu", session_id); - dev = usbi_alloc_device(ctx, session_id); - if (!dev) { - usbi_dbg("device allocation failed"); - continue; - } - *((USBDevice **)dev->os_priv) = fDevice; - - // Calculate pseudo-device-address - int addr, tmp; - if (strcmp(path.Leaf(), "hub") == 0) - tmp = 100; //Random Number - else - sscanf(path.Leaf(), "%d", &tmp); - addr = tmp + 1; - path.GetParent(&parent_path); - while (strcmp(parent_path.Leaf(), "usb") != 0) { - sscanf(parent_path.Leaf(), "%d", &tmp); - addr += tmp + 1; - parent_path.GetParent(&parent_path); - } - sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number); - dev->device_address = addr - (dev->bus_number + 1); - - if (usbi_sanitize_device(dev) < 0) { - usbi_dbg("device sanitization failed"); - libusb_unref_device(dev); - continue; - } - usbi_connect_device(dev); - } - usbi_mutex_unlock(&active_contexts_lock); - } - else if (fDevice) { - delete fDevice; - fDevice = NULL; - return; - } - } - fInitCheck = true; -} - - -WatchedEntry::~WatchedEntry() -{ - if (fIsDirectory) { - watch_node(&fNode, B_STOP_WATCHING, *fMessenger); - - WatchedEntry *child = fEntries; - while (child) { - WatchedEntry *next = child->fLink; - delete child; - child = next; - } - } - - if (fDevice) { - // Remove this device from each active context's device list - struct libusb_context *ctx; - struct libusb_device *dev; - unsigned long session_id = (unsigned long)&fDevice; - - usbi_mutex_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev != NULL) { - usbi_disconnect_device(dev); - libusb_unref_device(dev); - } else { - usbi_dbg("device with location %lu not found", session_id); - } - } - usbi_mutex_static_unlock(&active_contexts_lock); - delete fDevice; - } -} - - -bool -WatchedEntry::EntryCreated(entry_ref *ref) -{ - if (!fIsDirectory) - return false; - - if (ref->directory != fNode.node) { - WatchedEntry *child = fEntries; - while (child) { - if (child->EntryCreated(ref)) - return true; - child = child->fLink; - } - return false; - } - - WatchedEntry *child = new(std::nothrow) WatchedEntry(fMessenger, ref); - if (child == NULL) - return false; - child->fLink = fEntries; - fEntries = child; - return true; -} - - -bool -WatchedEntry::EntryRemoved(ino_t node) -{ - if (!fIsDirectory) - return false; - - WatchedEntry *child = fEntries; - WatchedEntry *lastChild = NULL; - while (child) { - if (child->fNode.node == node) { - if (lastChild) - lastChild->fLink = child->fLink; - else - fEntries = child->fLink; - delete child; - return true; - } - - if (child->EntryRemoved(node)) - return true; - - lastChild = child; - child = child->fLink; - } - return false; -} - - -bool -WatchedEntry::InitCheck() -{ - return fInitCheck; -} - - -RosterLooper::RosterLooper(USBRoster *roster) - : BLooper("LibusbRoster Looper"), - fRoster(roster), - fRoot(NULL), - fMessenger(NULL), - fInitCheck(false) -{ - BEntry entry("/dev/bus/usb"); - if (!entry.Exists()) { - usbi_err(NULL, "usb_raw not published"); - return; - } - - Run(); - fMessenger = new(std::nothrow) BMessenger(this); - if (fMessenger == NULL) { - usbi_err(NULL, "error creating BMessenger object"); - return; - } - - if (Lock()) { - entry_ref ref; - entry.GetRef(&ref); - fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref); - Unlock(); - if (fRoot == NULL) - return; - if (fRoot->InitCheck() == false) { - delete fRoot; - fRoot = NULL; - return; - } - } - fInitCheck = true; -} - - -void -RosterLooper::Stop() -{ - Lock(); - delete fRoot; - delete fMessenger; - Quit(); -} - - -void -RosterLooper::MessageReceived(BMessage *message) -{ - int32 opcode; - if (message->FindInt32("opcode", &opcode) < B_OK) - return; - - switch (opcode) { - case B_ENTRY_CREATED: - { - dev_t device; - ino_t directory; - const char *name; - if (message->FindInt32("device", &device) < B_OK || - message->FindInt64("directory", &directory) < B_OK || - message->FindString("name", &name) < B_OK) - break; - - entry_ref ref(device, directory, name); - fRoot->EntryCreated(&ref); - break; - } - case B_ENTRY_REMOVED: - { - ino_t node; - if (message->FindInt64("node", &node) < B_OK) - break; - fRoot->EntryRemoved(node); - break; - } - } -} - - -bool -RosterLooper::InitCheck() -{ - return fInitCheck; -} - - -USBRoster::USBRoster() - : fLooper(NULL) -{ -} - - -USBRoster::~USBRoster() -{ - Stop(); -} - - -int -USBRoster::Start() -{ - if (fLooper == NULL) { - fLooper = new(std::nothrow) RosterLooper(this); - if (fLooper == NULL || ((RosterLooper *)fLooper)->InitCheck() == false) { - if (fLooper) - fLooper = NULL; - return LIBUSB_ERROR_OTHER; - } - } - return LIBUSB_SUCCESS; -} - - -void -USBRoster::Stop() -{ - if (fLooper) { - ((RosterLooper *)fLooper)->Stop(); - fLooper = NULL; - } -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb.h deleted file mode 100644 index d51ae9eae8f..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Haiku Backend for libusb - * Copyright © 2014 Akshay Jaggi - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include "libusbi.h" -#include "haiku_usb_raw.h" - -using namespace std; - -class USBDevice; -class USBDeviceHandle; -class USBTransfer; - -class USBDevice { -public: - USBDevice(const char *); - virtual ~USBDevice(); - const char* Location() const; - uint8 CountConfigurations() const; - const usb_device_descriptor* Descriptor() const; - const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const; - const usb_configuration_descriptor* ActiveConfiguration() const; - uint8 EndpointToIndex(uint8) const; - uint8 EndpointToInterface(uint8) const; - int ClaimInterface(int); - int ReleaseInterface(int); - int CheckInterfacesFree(int); - int SetActiveConfiguration(int); - int ActiveConfigurationIndex() const; - bool InitCheck(); -private: - int Initialise(); - unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask - usb_device_descriptor fDeviceDescriptor; - unsigned char** fConfigurationDescriptors; - int fActiveConfiguration; - char* fPath; - map fConfigToIndex; - map* fEndpointToIndex; - map* fEndpointToInterface; - bool fInitCheck; -}; - -class USBDeviceHandle { -public: - USBDeviceHandle(USBDevice *dev); - virtual ~USBDeviceHandle(); - int ClaimInterface(int); - int ReleaseInterface(int); - int SetConfiguration(int); - int SetAltSetting(int, int); - status_t SubmitTransfer(struct usbi_transfer *); - status_t CancelTransfer(USBTransfer *); - bool InitCheck(); -private: - int fRawFD; - static status_t TransfersThread(void *); - void TransfersWorker(); - USBDevice* fUSBDevice; - unsigned int fClaimedInterfaces; - BList fTransfers; - BLocker fTransfersLock; - sem_id fTransfersSem; - thread_id fTransfersThread; - bool fInitCheck; -}; - -class USBTransfer { -public: - USBTransfer(struct usbi_transfer *, USBDevice *); - virtual ~USBTransfer(); - void Do(int); - struct usbi_transfer* UsbiTransfer(); - void SetCancelled(); - bool IsCancelled(); -private: - struct usbi_transfer* fUsbiTransfer; - struct libusb_transfer* fLibusbTransfer; - USBDevice* fUSBDevice; - BLocker fStatusLock; - bool fCancelled; -}; - -class USBRoster { -public: - USBRoster(); - virtual ~USBRoster(); - int Start(); - void Stop(); -private: - void* fLooper; -}; diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_backend.cpp b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_backend.cpp deleted file mode 100644 index d3de8cc0808..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_backend.cpp +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Haiku Backend for libusb - * Copyright © 2014 Akshay Jaggi - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include -#include -#include -#include - -#include "haiku_usb.h" - -int _errno_to_libusb(int status) -{ - return status; -} - -USBTransfer::USBTransfer(struct usbi_transfer *itransfer, USBDevice *device) -{ - fUsbiTransfer = itransfer; - fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - fUSBDevice = device; - fCancelled = false; -} - -USBTransfer::~USBTransfer() -{ -} - -struct usbi_transfer * -USBTransfer::UsbiTransfer() -{ - return fUsbiTransfer; -} - -void -USBTransfer::SetCancelled() -{ - fCancelled = true; -} - -bool -USBTransfer::IsCancelled() -{ - return fCancelled; -} - -void -USBTransfer::Do(int fRawFD) -{ - switch (fLibusbTransfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - { - struct libusb_control_setup *setup = (struct libusb_control_setup *)fLibusbTransfer->buffer; - usb_raw_command command; - command.control.request_type = setup->bmRequestType; - command.control.request = setup->bRequest; - command.control.value = setup->wValue; - command.control.index = setup->wIndex; - command.control.length = setup->wLength; - command.control.data = fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - if (fCancelled) - break; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) || - command.control.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed control transfer"); - break; - } - fUsbiTransfer->transferred = command.control.length; - } - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - { - usb_raw_command command; - command.transfer.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); - command.transfer.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); - command.transfer.data = fLibusbTransfer->buffer; - command.transfer.length = fLibusbTransfer->length; - if (fCancelled) - break; - if (fLibusbTransfer->type == LIBUSB_TRANSFER_TYPE_BULK) { - if (ioctl(fRawFD, B_USB_RAW_COMMAND_BULK_TRANSFER, &command, sizeof(command)) || - command.transfer.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed bulk transfer"); - break; - } - } - else { - if (ioctl(fRawFD, B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, &command, sizeof(command)) || - command.transfer.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed interrupt transfer"); - break; - } - } - fUsbiTransfer->transferred = command.transfer.length; - } - break; - // IsochronousTransfers not tested - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - { - usb_raw_command command; - command.isochronous.interface = fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); - command.isochronous.endpoint = fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); - command.isochronous.data = fLibusbTransfer->buffer; - command.isochronous.length = fLibusbTransfer->length; - command.isochronous.packet_count = fLibusbTransfer->num_iso_packets; - int i; - usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets]; - for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) { - if ((int16)(fLibusbTransfer->iso_packet_desc[i]).length != (fLibusbTransfer->iso_packet_desc[i]).length) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer"); - break; - } - packetDescriptors[i].request_length = (int16)(fLibusbTransfer->iso_packet_desc[i]).length; - } - if (i < fLibusbTransfer->num_iso_packets) - break; // TODO Handle this error - command.isochronous.packet_descriptors = packetDescriptors; - if (fCancelled) - break; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER, &command, sizeof(command)) || - command.isochronous.status != B_USB_RAW_STATUS_SUCCESS) { - fUsbiTransfer->transferred = -1; - usbi_err(TRANSFER_CTX(fLibusbTransfer), "failed isochronous transfer"); - break; - } - for (i = 0; i < fLibusbTransfer->num_iso_packets; i++) { - (fLibusbTransfer->iso_packet_desc[i]).actual_length = packetDescriptors[i].actual_length; - switch (packetDescriptors[i].status) { - case B_OK: - (fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_COMPLETED; - break; - default: - (fLibusbTransfer->iso_packet_desc[i]).status = LIBUSB_TRANSFER_ERROR; - break; - } - } - delete[] packetDescriptors; - // Do we put the length of transfer here, for isochronous transfers? - fUsbiTransfer->transferred = command.transfer.length; - } - break; - default: - usbi_err(TRANSFER_CTX(fLibusbTransfer), "Unknown type of transfer"); - } -} - -bool -USBDeviceHandle::InitCheck() -{ - return fInitCheck; -} - -status_t -USBDeviceHandle::TransfersThread(void *self) -{ - USBDeviceHandle *handle = (USBDeviceHandle *)self; - handle->TransfersWorker(); - return B_OK; -} - -void -USBDeviceHandle::TransfersWorker() -{ - while (true) { - status_t status = acquire_sem(fTransfersSem); - if (status == B_BAD_SEM_ID) - break; - if (status == B_INTERRUPTED) - continue; - fTransfersLock.Lock(); - USBTransfer *fPendingTransfer = (USBTransfer *) fTransfers.RemoveItem((int32)0); - fTransfersLock.Unlock(); - fPendingTransfer->Do(fRawFD); - usbi_signal_transfer_completion(fPendingTransfer->UsbiTransfer()); - } -} - -status_t -USBDeviceHandle::SubmitTransfer(struct usbi_transfer *itransfer) -{ - USBTransfer *transfer = new USBTransfer(itransfer, fUSBDevice); - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = transfer; - BAutolock locker(fTransfersLock); - fTransfers.AddItem(transfer); - release_sem(fTransfersSem); - return LIBUSB_SUCCESS; -} - -status_t -USBDeviceHandle::CancelTransfer(USBTransfer *transfer) -{ - transfer->SetCancelled(); - fTransfersLock.Lock(); - bool removed = fTransfers.RemoveItem(transfer); - fTransfersLock.Unlock(); - if(removed) - usbi_signal_transfer_completion(transfer->UsbiTransfer()); - return LIBUSB_SUCCESS; -} - -USBDeviceHandle::USBDeviceHandle(USBDevice *dev) - : - fTransfersThread(-1), - fUSBDevice(dev), - fClaimedInterfaces(0), - fInitCheck(false) -{ - fRawFD = open(dev->Location(), O_RDWR | O_CLOEXEC); - if (fRawFD < 0) { - usbi_err(NULL,"failed to open device"); - return; - } - fTransfersSem = create_sem(0, "Transfers Queue Sem"); - fTransfersThread = spawn_thread(TransfersThread, "Transfer Worker", B_NORMAL_PRIORITY, this); - resume_thread(fTransfersThread); - fInitCheck = true; -} - -USBDeviceHandle::~USBDeviceHandle() -{ - if (fRawFD > 0) - close(fRawFD); - for(int i = 0; i < 32; i++) { - if (fClaimedInterfaces & (1 << i)) - ReleaseInterface(i); - } - delete_sem(fTransfersSem); - if (fTransfersThread > 0) - wait_for_thread(fTransfersThread, NULL); -} - -int -USBDeviceHandle::ClaimInterface(int inumber) -{ - int status = fUSBDevice->ClaimInterface(inumber); - if (status == LIBUSB_SUCCESS) - fClaimedInterfaces |= (1 << inumber); - return status; -} - -int -USBDeviceHandle::ReleaseInterface(int inumber) -{ - fUSBDevice->ReleaseInterface(inumber); - fClaimedInterfaces &= ~(1 << inumber); - return LIBUSB_SUCCESS; -} - -int -USBDeviceHandle::SetConfiguration(int config) -{ - int config_index = fUSBDevice->CheckInterfacesFree(config); - if(config_index == LIBUSB_ERROR_BUSY || config_index == LIBUSB_ERROR_NOT_FOUND) - return config_index; - usb_raw_command command; - command.config.config_index = config_index; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_CONFIGURATION, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - return _errno_to_libusb(command.config.status); - } - fUSBDevice->SetActiveConfiguration(config_index); - return LIBUSB_SUCCESS; -} - -int -USBDeviceHandle::SetAltSetting(int inumber, int alt) -{ - usb_raw_command command; - command.alternate.config_index = fUSBDevice->ActiveConfigurationIndex(); - command.alternate.interface_index = inumber; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, &command, sizeof(command)) || - command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "Error retrieving active alternate interface"); - return _errno_to_libusb(command.alternate.status); - } - if (command.alternate.alternate_info == alt) { - usbi_dbg("Setting alternate interface successful"); - return LIBUSB_SUCCESS; - } - command.alternate.alternate_info = alt; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_SET_ALT_INTERFACE, &command, sizeof(command)) || - command.alternate.status != B_USB_RAW_STATUS_SUCCESS) { //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY - usbi_err(NULL, "Error setting alternate interface"); - return _errno_to_libusb(command.alternate.status); - } - usbi_dbg("Setting alternate interface successful"); - return LIBUSB_SUCCESS; -} - - -USBDevice::USBDevice(const char *path) - : - fPath(NULL), - fActiveConfiguration(0), //0? - fConfigurationDescriptors(NULL), - fClaimedInterfaces(0), - fEndpointToIndex(NULL), - fEndpointToInterface(NULL), - fInitCheck(false) -{ - fPath=strdup(path); - Initialise(); -} - -USBDevice::~USBDevice() -{ - free(fPath); - if (fConfigurationDescriptors) { - for(int i = 0; i < fDeviceDescriptor.num_configurations; i++) { - if (fConfigurationDescriptors[i]) - delete fConfigurationDescriptors[i]; - } - delete[] fConfigurationDescriptors; - } - if (fEndpointToIndex) - delete[] fEndpointToIndex; - if (fEndpointToInterface) - delete[] fEndpointToInterface; -} - -bool -USBDevice::InitCheck() -{ - return fInitCheck; -} - -const char * -USBDevice::Location() const -{ - return fPath; -} - -uint8 -USBDevice::CountConfigurations() const -{ - return fDeviceDescriptor.num_configurations; -} - -const usb_device_descriptor * -USBDevice::Descriptor() const -{ - return &fDeviceDescriptor; -} - -const usb_configuration_descriptor * -USBDevice::ConfigurationDescriptor(uint32 index) const -{ - if (index > CountConfigurations()) - return NULL; - return (usb_configuration_descriptor *) fConfigurationDescriptors[index]; -} - -const usb_configuration_descriptor * -USBDevice::ActiveConfiguration() const -{ - return (usb_configuration_descriptor *) fConfigurationDescriptors[fActiveConfiguration]; -} - -int -USBDevice::ActiveConfigurationIndex() const -{ - return fActiveConfiguration; -} - -int USBDevice::ClaimInterface(int interface) -{ - if (interface > ActiveConfiguration()->number_interfaces) - return LIBUSB_ERROR_NOT_FOUND; - if (fClaimedInterfaces & (1 << interface)) - return LIBUSB_ERROR_BUSY; - fClaimedInterfaces |= (1 << interface); - return LIBUSB_SUCCESS; -} - -int USBDevice::ReleaseInterface(int interface) -{ - fClaimedInterfaces &= ~(1 << interface); - return LIBUSB_SUCCESS; -} - -int -USBDevice::CheckInterfacesFree(int config) -{ - if (fConfigToIndex.count(config) == 0) - return LIBUSB_ERROR_NOT_FOUND; - if (fClaimedInterfaces == 0) - return fConfigToIndex[(uint8)config]; - return LIBUSB_ERROR_BUSY; -} - -int -USBDevice::SetActiveConfiguration(int config_index) -{ - fActiveConfiguration = config_index; - return LIBUSB_SUCCESS; -} - -uint8 -USBDevice::EndpointToIndex(uint8 address) const -{ - return fEndpointToIndex[fActiveConfiguration][address]; -} - -uint8 -USBDevice::EndpointToInterface(uint8 address) const -{ - return fEndpointToInterface[fActiveConfiguration][address]; -} - -int -USBDevice::Initialise() //Do we need more error checking, etc? How to report? -{ - int fRawFD = open(fPath, O_RDWR | O_CLOEXEC); - if (fRawFD < 0) - return B_ERROR; - usb_raw_command command; - command.device.descriptor = &fDeviceDescriptor; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command, sizeof(command)) || - command.device.status != B_USB_RAW_STATUS_SUCCESS) { - close(fRawFD); - return B_ERROR; - } - - fConfigurationDescriptors = new(std::nothrow) unsigned char *[fDeviceDescriptor.num_configurations]; - fEndpointToIndex = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; - fEndpointToInterface = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; - for (int i = 0; i < fDeviceDescriptor.num_configurations; i++) { - usb_configuration_descriptor tmp_config; - command.config.descriptor = &tmp_config; - command.config.config_index = i; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving configuration descriptor"); - close(fRawFD); - return B_ERROR; - } - fConfigToIndex[tmp_config.configuration_value] = i; - fConfigurationDescriptors[i] = new(std::nothrow) unsigned char[tmp_config.total_length]; - command.control.request_type = 128; - command.control.request = 6; - command.control.value = (2 << 8) | i; - command.control.index = 0; - command.control.length = tmp_config.total_length; - command.control.data = fConfigurationDescriptors[i]; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) || - command.control.status!=B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving full configuration descriptor"); - close(fRawFD); - return B_ERROR; - } - for (int j = 0; j < tmp_config.number_interfaces; j++) { - command.alternate.config_index = i; - command.alternate.interface_index = j; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving number of alternate interfaces"); - close(fRawFD); - return B_ERROR; - } - int num_alternate = command.alternate.alternate_info; - for (int k = 0; k < num_alternate; k++) { - usb_interface_descriptor tmp_interface; - command.interface_etc.config_index = i; - command.interface_etc.interface_index = j; - command.interface_etc.alternate_index = k; - command.interface_etc.descriptor = &tmp_interface; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving interface descriptor"); - close(fRawFD); - return B_ERROR; - } - for (int l = 0; l < tmp_interface.num_endpoints; l++) { - usb_endpoint_descriptor tmp_endpoint; - command.endpoint_etc.config_index = i; - command.endpoint_etc.interface_index = j; - command.endpoint_etc.alternate_index = k; - command.endpoint_etc.endpoint_index = l; - command.endpoint_etc.descriptor = &tmp_endpoint; - if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command, sizeof(command)) || - command.config.status != B_USB_RAW_STATUS_SUCCESS) { - usbi_err(NULL, "failed retrieving endpoint descriptor"); - close(fRawFD); - return B_ERROR; - } - fEndpointToIndex[i][tmp_endpoint.endpoint_address] = l; - fEndpointToInterface[i][tmp_endpoint.endpoint_address] = j; - } - } - } - } - close(fRawFD); - fInitCheck = true; - return B_OK; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_raw.cpp b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_raw.cpp deleted file mode 100644 index 77adbd1e60e..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_raw.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Haiku Backend for libusb - * Copyright © 2014 Akshay Jaggi - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include -#include -#include -#include - -#include "haiku_usb.h" - -USBRoster gUsbRoster; -int32 gInitCount = 0; - -static int -haiku_init(struct libusb_context *ctx) -{ - if (atomic_add(&gInitCount, 1) == 0) - return gUsbRoster.Start(); - return LIBUSB_SUCCESS; -} - -static void -haiku_exit(void) -{ - if (atomic_add(&gInitCount, -1) == 1) - gUsbRoster.Stop(); -} - -static int -haiku_open(struct libusb_device_handle *dev_handle) -{ - USBDevice *dev = *((USBDevice **)dev_handle->dev->os_priv); - USBDeviceHandle *handle = new(std::nothrow) USBDeviceHandle(dev); - if (handle == NULL) - return LIBUSB_ERROR_NO_MEM; - if (handle->InitCheck() == false) { - delete handle; - return LIBUSB_ERROR_NO_DEVICE; - } - *((USBDeviceHandle **)dev_handle->os_priv) = handle; - return LIBUSB_SUCCESS; -} - -static void -haiku_close(struct libusb_device_handle *dev_handle) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - if (handle == NULL) - return; - delete handle; - *((USBDeviceHandle **)dev_handle->os_priv) = NULL; -} - -static int -haiku_get_device_descriptor(struct libusb_device *device, unsigned char *buffer, int *host_endian) -{ - USBDevice *dev = *((USBDevice **)device->os_priv); - memcpy(buffer, dev->Descriptor(), DEVICE_DESC_LENGTH); - *host_endian = 0; - return LIBUSB_SUCCESS; -} - -static int -haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian) -{ - USBDevice *dev = *((USBDevice **)device->os_priv); - const usb_configuration_descriptor *act_config = dev->ActiveConfiguration(); - if (len > act_config->total_length) - return LIBUSB_ERROR_OVERFLOW; - memcpy(buffer, act_config, len); - *host_endian = 0; - return LIBUSB_SUCCESS; -} - -static int -haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - USBDevice *dev = *((USBDevice **)device->os_priv); - const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index); - if (config == NULL) { - usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor"); - return LIBUSB_ERROR_INVALID_PARAM; - } - if (len > config->total_length) - len = config->total_length; - memcpy(buffer, config, len); - *host_endian = 0; - return len; -} - -static int -haiku_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - USBDeviceHandle *handle= *((USBDeviceHandle **)dev_handle->os_priv); - return handle->SetConfiguration(config); -} - -static int -haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - return handle->ClaimInterface(interface_number); -} - -static int -haiku_set_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - return handle->SetAltSetting(interface_number, altsetting); -} - -static int -haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number) -{ - USBDeviceHandle *handle = *((USBDeviceHandle **)dev_handle->os_priv); - haiku_set_altsetting(dev_handle,interface_number, 0); - return handle->ReleaseInterface(interface_number); -} - -static int -haiku_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv); - return fDeviceHandle->SubmitTransfer(itransfer); -} - -static int -haiku_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - USBDeviceHandle *fDeviceHandle = *((USBDeviceHandle **)fLibusbTransfer->dev_handle->os_priv); - return fDeviceHandle->CancelTransfer(*((USBTransfer **)usbi_transfer_get_os_priv(itransfer))); -} - -static void -haiku_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)); - delete transfer; - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; -} - -static int -haiku_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - USBTransfer *transfer = *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)); - - usbi_mutex_lock(&itransfer->lock); - if (transfer->IsCancelled()) { - delete transfer; - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; - usbi_mutex_unlock(&itransfer->lock); - if (itransfer->transferred < 0) - itransfer->transferred = 0; - return usbi_handle_transfer_cancellation(itransfer); - } - libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; - if (itransfer->transferred < 0) { - usbi_err(ITRANSFER_CTX(itransfer), "error in transfer"); - status = LIBUSB_TRANSFER_ERROR; - itransfer->transferred = 0; - } - delete transfer; - *((USBTransfer **)usbi_transfer_get_os_priv(itransfer)) = NULL; - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, status); -} - -static int -haiku_clock_gettime(int clkid, struct timespec *tp) -{ - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - return LIBUSB_ERROR_INVALID_PARAM; -} - -const struct usbi_os_backend haiku_usb_raw_backend = { - /*.name =*/ "Haiku usbfs", - /*.caps =*/ 0, - /*.init =*/ haiku_init, - /*.exit =*/ haiku_exit, - /*.get_device_list =*/ NULL, - /*.hotplug_poll =*/ NULL, - /*.open =*/ haiku_open, - /*.close =*/ haiku_close, - /*.get_device_descriptor =*/ haiku_get_device_descriptor, - /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor, - /*.get_config_descriptor =*/ haiku_get_config_descriptor, - /*.get_config_descriptor_by_value =*/ NULL, - - - /*.get_configuration =*/ NULL, - /*.set_configuration =*/ haiku_set_configuration, - /*.claim_interface =*/ haiku_claim_interface, - /*.release_interface =*/ haiku_release_interface, - - /*.set_interface_altsetting =*/ haiku_set_altsetting, - /*.clear_halt =*/ NULL, - /*.reset_device =*/ NULL, - - /*.alloc_streams =*/ NULL, - /*.free_streams =*/ NULL, - - /*.dev_mem_alloc =*/ NULL, - /*.dev_mem_free =*/ NULL, - - /*.kernel_driver_active =*/ NULL, - /*.detach_kernel_driver =*/ NULL, - /*.attach_kernel_driver =*/ NULL, - - /*.destroy_device =*/ NULL, - - /*.submit_transfer =*/ haiku_submit_transfer, - /*.cancel_transfer =*/ haiku_cancel_transfer, - /*.clear_transfer_priv =*/ haiku_clear_transfer_priv, - - /*.handle_events =*/ NULL, - /*.handle_transfer_completion =*/ haiku_handle_transfer_completion, - - /*.clock_gettime =*/ haiku_clock_gettime, - -#ifdef USBI_TIMERFD_AVAILABLE - /*.get_timerfd_clockid =*/ NULL, -#endif - - /*.device_priv_size =*/ sizeof(USBDevice *), - /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle *), - /*.transfer_priv_size =*/ sizeof(USBTransfer *), -}; diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_raw.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_raw.h deleted file mode 100644 index 5baf53d7c91..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/haiku_usb_raw.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2006-2008, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - */ - -#ifndef _USB_RAW_H_ -#define _USB_RAW_H_ - -#include - -#define B_USB_RAW_PROTOCOL_VERSION 0x0015 -#define B_USB_RAW_ACTIVE_ALTERNATE 0xffffffff - -typedef enum { - B_USB_RAW_COMMAND_GET_VERSION = 0x1000, - - B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000, - B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, - B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, - B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, - B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, - B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, - B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, - - B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000, - B_USB_RAW_COMMAND_SET_FEATURE, - B_USB_RAW_COMMAND_CLEAR_FEATURE, - B_USB_RAW_COMMAND_GET_STATUS, - B_USB_RAW_COMMAND_GET_DESCRIPTOR, - B_USB_RAW_COMMAND_SET_ALT_INTERFACE, - - B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000, - B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, - B_USB_RAW_COMMAND_BULK_TRANSFER, - B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER -} usb_raw_command_id; - - -typedef enum { - B_USB_RAW_STATUS_SUCCESS = 0, - - B_USB_RAW_STATUS_FAILED, - B_USB_RAW_STATUS_ABORTED, - B_USB_RAW_STATUS_STALLED, - B_USB_RAW_STATUS_CRC_ERROR, - B_USB_RAW_STATUS_TIMEOUT, - - B_USB_RAW_STATUS_INVALID_CONFIGURATION, - B_USB_RAW_STATUS_INVALID_INTERFACE, - B_USB_RAW_STATUS_INVALID_ENDPOINT, - B_USB_RAW_STATUS_INVALID_STRING, - - B_USB_RAW_STATUS_NO_MEMORY -} usb_raw_command_status; - - -typedef union { - struct { - status_t status; - } version; - - struct { - status_t status; - usb_device_descriptor *descriptor; - } device; - - struct { - status_t status; - usb_configuration_descriptor *descriptor; - uint32 config_index; - } config; - - struct { - status_t status; - uint32 alternate_info; - uint32 config_index; - uint32 interface_index; - } alternate; - - struct { - status_t status; - usb_interface_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - } interface; - - struct { - status_t status; - usb_interface_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 alternate_index; - } interface_etc; - - struct { - status_t status; - usb_endpoint_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 endpoint_index; - } endpoint; - - struct { - status_t status; - usb_endpoint_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 alternate_index; - uint32 endpoint_index; - } endpoint_etc; - - struct { - status_t status; - usb_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 generic_index; - size_t length; - } generic; - - struct { - status_t status; - usb_descriptor *descriptor; - uint32 config_index; - uint32 interface_index; - uint32 alternate_index; - uint32 generic_index; - size_t length; - } generic_etc; - - struct { - status_t status; - usb_string_descriptor *descriptor; - uint32 string_index; - size_t length; - } string; - - struct { - status_t status; - uint8 type; - uint8 index; - uint16 language_id; - void *data; - size_t length; - } descriptor; - - struct { - status_t status; - uint8 request_type; - uint8 request; - uint16 value; - uint16 index; - uint16 length; - void *data; - } control; - - struct { - status_t status; - uint32 interface; - uint32 endpoint; - void *data; - size_t length; - } transfer; - - struct { - status_t status; - uint32 interface; - uint32 endpoint; - void *data; - size_t length; - usb_iso_packet_descriptor *packet_descriptors; - uint32 packet_count; - } isochronous; -} usb_raw_command; - -#endif // _USB_RAW_H_ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_netlink.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_netlink.c deleted file mode 100644 index 60cf3ad1bd0..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_netlink.c +++ /dev/null @@ -1,400 +0,0 @@ -/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ -/* - * Linux usbfs backend for libusb - * Copyright (C) 2007-2009 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt - * Copyright (c) 2013 Nathan Hjelm - * Copyright (c) 2016 Chris Dickens - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_ASM_TYPES_H -#include -#endif - -#include -#include - -#include "libusbi.h" -#include "linux_usbfs.h" - -#define NL_GROUP_KERNEL 1 - -static int linux_netlink_socket = -1; -static int netlink_control_pipe[2] = { -1, -1 }; -static pthread_t libusb_linux_event_thread; - -static void *linux_netlink_event_thread_main(void *arg); - -static int set_fd_cloexec_nb(int fd) -{ - int flags; - -#if defined(FD_CLOEXEC) - flags = fcntl(fd, F_GETFD); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd flags (%d)", errno); - return -1; - } - - if (!(flags & FD_CLOEXEC)) { - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { - usbi_err(NULL, "failed to set netlink fd flags (%d)", errno); - return -1; - } - } -#endif - - flags = fcntl(fd, F_GETFL); - if (flags == -1) { - usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno); - return -1; - } - - if (!(flags & O_NONBLOCK)) { - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { - usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno); - return -1; - } - } - - return 0; -} - -int linux_netlink_start_event_monitor(void) -{ - struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL }; - int socktype = SOCK_RAW; - int opt = 1; - int ret; - -#if defined(SOCK_CLOEXEC) - socktype |= SOCK_CLOEXEC; -#endif -#if defined(SOCK_NONBLOCK) - socktype |= SOCK_NONBLOCK; -#endif - - linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); - if (linux_netlink_socket == -1 && errno == EINVAL) { - usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype); - linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); - } - - if (linux_netlink_socket == -1) { - usbi_err(NULL, "failed to create netlink socket (%d)", errno); - goto err; - } - - ret = set_fd_cloexec_nb(linux_netlink_socket); - if (ret == -1) - goto err_close_socket; - - ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); - if (ret == -1) { - usbi_err(NULL, "failed to bind netlink socket (%d)", errno); - goto err_close_socket; - } - - ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt)); - if (ret == -1) { - usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno); - goto err_close_socket; - } - - ret = usbi_pipe(netlink_control_pipe); - if (ret) { - usbi_err(NULL, "failed to create netlink control pipe"); - goto err_close_socket; - } - - ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL); - if (ret != 0) { - usbi_err(NULL, "failed to create netlink event thread (%d)", ret); - goto err_close_pipe; - } - - return LIBUSB_SUCCESS; - -err_close_pipe: - close(netlink_control_pipe[0]); - close(netlink_control_pipe[1]); - netlink_control_pipe[0] = -1; - netlink_control_pipe[1] = -1; -err_close_socket: - close(linux_netlink_socket); - linux_netlink_socket = -1; -err: - return LIBUSB_ERROR_OTHER; -} - -int linux_netlink_stop_event_monitor(void) -{ - char dummy = 1; - ssize_t r; - - assert(linux_netlink_socket != -1); - - /* Write some dummy data to the control pipe and - * wait for the thread to exit */ - r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy)); - if (r <= 0) - usbi_warn(NULL, "netlink control pipe signal failed"); - - pthread_join(libusb_linux_event_thread, NULL); - - close(linux_netlink_socket); - linux_netlink_socket = -1; - - /* close and reset control pipe */ - close(netlink_control_pipe[0]); - close(netlink_control_pipe[1]); - netlink_control_pipe[0] = -1; - netlink_control_pipe[1] = -1; - - return LIBUSB_SUCCESS; -} - -static const char *netlink_message_parse(const char *buffer, size_t len, const char *key) -{ - const char *end = buffer + len; - size_t keylen = strlen(key); - - while (buffer < end && *buffer) { - if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=') - return buffer + keylen + 1; - buffer += strlen(buffer) + 1; - } - - return NULL; -} - -/* parse parts of netlink message common to both libudev and the kernel */ -static int linux_netlink_parse(const char *buffer, size_t len, int *detached, - const char **sys_name, uint8_t *busnum, uint8_t *devaddr) -{ - const char *tmp, *slash; - - errno = 0; - - *sys_name = NULL; - *detached = 0; - *busnum = 0; - *devaddr = 0; - - tmp = netlink_message_parse(buffer, len, "ACTION"); - if (!tmp) { - return -1; - } else if (strcmp(tmp, "remove") == 0) { - *detached = 1; - } else if (strcmp(tmp, "add") != 0) { - usbi_dbg("unknown device action %s", tmp); - return -1; - } - - /* check that this is a usb message */ - tmp = netlink_message_parse(buffer, len, "SUBSYSTEM"); - if (!tmp || strcmp(tmp, "usb") != 0) { - /* not usb. ignore */ - return -1; - } - - /* check that this is an actual usb device */ - tmp = netlink_message_parse(buffer, len, "DEVTYPE"); - if (!tmp || strcmp(tmp, "usb_device") != 0) { - /* not usb. ignore */ - return -1; - } - - tmp = netlink_message_parse(buffer, len, "BUSNUM"); - if (tmp) { - *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - tmp = netlink_message_parse(buffer, len, "DEVNUM"); - if (NULL == tmp) - return -1; - - *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - } else { - /* no bus number. try "DEVICE" */ - tmp = netlink_message_parse(buffer, len, "DEVICE"); - if (!tmp) { - /* not usb. ignore */ - return -1; - } - - /* Parse a device path such as /dev/bus/usb/003/004 */ - slash = strrchr(tmp, '/'); - if (!slash) - return -1; - - *busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - *devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff); - if (errno) { - errno = 0; - return -1; - } - - return 0; - } - - tmp = netlink_message_parse(buffer, len, "DEVPATH"); - if (!tmp) - return -1; - - slash = strrchr(tmp, '/'); - if (slash) - *sys_name = slash + 1; - - /* found a usb device */ - return 0; -} - -static int linux_netlink_read_message(void) -{ - char cred_buffer[CMSG_SPACE(sizeof(struct ucred))]; - char msg_buffer[2048]; - const char *sys_name = NULL; - uint8_t busnum, devaddr; - int detached, r; - ssize_t len; - struct cmsghdr *cmsg; - struct ucred *cred; - struct sockaddr_nl sa_nl; - struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) }; - struct msghdr msg = { - .msg_iov = &iov, .msg_iovlen = 1, - .msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer), - .msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl) - }; - - /* read netlink message */ - len = recvmsg(linux_netlink_socket, &msg, 0); - if (len == -1) { - if (errno != EAGAIN && errno != EINTR) - usbi_err(NULL, "error receiving message from netlink (%d)", errno); - return -1; - } - - if (len < 32 || (msg.msg_flags & MSG_TRUNC)) { - usbi_err(NULL, "invalid netlink message length"); - return -1; - } - - if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) { - usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)", - (unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid); - return -1; - } - - cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { - usbi_dbg("ignoring netlink message with no sender credentials"); - return -1; - } - - cred = (struct ucred *)CMSG_DATA(cmsg); - if (cred->uid != 0) { - usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid); - return -1; - } - - r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr); - if (r) - return r; - - usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s", - busnum, devaddr, sys_name, detached ? "yes" : "no"); - - /* signal device is available (or not) to all contexts */ - if (detached) - linux_device_disconnected(busnum, devaddr); - else - linux_hotplug_enumerate(busnum, devaddr, sys_name); - - return 0; -} - -static void *linux_netlink_event_thread_main(void *arg) -{ - char dummy; - ssize_t r; - struct pollfd fds[] = { - { .fd = netlink_control_pipe[0], - .events = POLLIN }, - { .fd = linux_netlink_socket, - .events = POLLIN }, - }; - - UNUSED(arg); - - usbi_dbg("netlink event thread entering"); - - while (poll(fds, 2, -1) >= 0) { - if (fds[0].revents & POLLIN) { - /* activity on control pipe, read the byte and exit */ - r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) - usbi_warn(NULL, "netlink control pipe read failed"); - break; - } - if (fds[1].revents & POLLIN) { - usbi_mutex_static_lock(&linux_hotplug_lock); - linux_netlink_read_message(); - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - } - - usbi_dbg("netlink event thread exiting"); - - return NULL; -} - -void linux_netlink_hotplug_poll(void) -{ - int r; - - usbi_mutex_static_lock(&linux_hotplug_lock); - do { - r = linux_netlink_read_message(); - } while (r == 0); - usbi_mutex_static_unlock(&linux_hotplug_lock); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_udev.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_udev.c deleted file mode 100644 index 61d953d8c2d..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_udev.c +++ /dev/null @@ -1,311 +0,0 @@ -/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ -/* - * Linux usbfs backend for libusb - * Copyright (C) 2007-2009 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt - * Copyright (c) 2012-2013 Nathan Hjelm - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "linux_usbfs.h" - -/* udev context */ -static struct udev *udev_ctx = NULL; -static int udev_monitor_fd = -1; -static int udev_control_pipe[2] = {-1, -1}; -static struct udev_monitor *udev_monitor = NULL; -static pthread_t linux_event_thread; - -static void udev_hotplug_event(struct udev_device* udev_dev); -static void *linux_udev_event_thread_main(void *arg); - -int linux_udev_start_event_monitor(void) -{ - int r; - - assert(udev_ctx == NULL); - udev_ctx = udev_new(); - if (!udev_ctx) { - usbi_err(NULL, "could not create udev context"); - goto err; - } - - udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev"); - if (!udev_monitor) { - usbi_err(NULL, "could not initialize udev monitor"); - goto err_free_ctx; - } - - r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device"); - if (r) { - usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem"); - goto err_free_monitor; - } - - if (udev_monitor_enable_receiving(udev_monitor)) { - usbi_err(NULL, "failed to enable the udev monitor"); - goto err_free_monitor; - } - - udev_monitor_fd = udev_monitor_get_fd(udev_monitor); - - /* Some older versions of udev are not non-blocking by default, - * so make sure this is set */ - r = fcntl(udev_monitor_fd, F_GETFL); - if (r == -1) { - usbi_err(NULL, "getting udev monitor fd flags (%d)", errno); - goto err_free_monitor; - } - r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK); - if (r) { - usbi_err(NULL, "setting udev monitor fd flags (%d)", errno); - goto err_free_monitor; - } - - r = usbi_pipe(udev_control_pipe); - if (r) { - usbi_err(NULL, "could not create udev control pipe"); - goto err_free_monitor; - } - - r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL); - if (r) { - usbi_err(NULL, "creating hotplug event thread (%d)", r); - goto err_close_pipe; - } - - return LIBUSB_SUCCESS; - -err_close_pipe: - close(udev_control_pipe[0]); - close(udev_control_pipe[1]); -err_free_monitor: - udev_monitor_unref(udev_monitor); - udev_monitor = NULL; - udev_monitor_fd = -1; -err_free_ctx: - udev_unref(udev_ctx); -err: - udev_ctx = NULL; - return LIBUSB_ERROR_OTHER; -} - -int linux_udev_stop_event_monitor(void) -{ - char dummy = 1; - int r; - - assert(udev_ctx != NULL); - assert(udev_monitor != NULL); - assert(udev_monitor_fd != -1); - - /* Write some dummy data to the control pipe and - * wait for the thread to exit */ - r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy)); - if (r <= 0) { - usbi_warn(NULL, "udev control pipe signal failed"); - } - pthread_join(linux_event_thread, NULL); - - /* Release the udev monitor */ - udev_monitor_unref(udev_monitor); - udev_monitor = NULL; - udev_monitor_fd = -1; - - /* Clean up the udev context */ - udev_unref(udev_ctx); - udev_ctx = NULL; - - /* close and reset control pipe */ - close(udev_control_pipe[0]); - close(udev_control_pipe[1]); - udev_control_pipe[0] = -1; - udev_control_pipe[1] = -1; - - return LIBUSB_SUCCESS; -} - -static void *linux_udev_event_thread_main(void *arg) -{ - char dummy; - int r; - struct udev_device* udev_dev; - struct pollfd fds[] = { - {.fd = udev_control_pipe[0], - .events = POLLIN}, - {.fd = udev_monitor_fd, - .events = POLLIN}, - }; - - usbi_dbg("udev event thread entering."); - - while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) { - if (r < 0) { - /* temporary failure */ - continue; - } - if (fds[0].revents & POLLIN) { - /* activity on control pipe, read the byte and exit */ - r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy)); - if (r <= 0) { - usbi_warn(NULL, "udev control pipe read failed"); - } - break; - } - if (fds[1].revents & POLLIN) { - usbi_mutex_static_lock(&linux_hotplug_lock); - udev_dev = udev_monitor_receive_device(udev_monitor); - if (udev_dev) - udev_hotplug_event(udev_dev); - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - } - - usbi_dbg("udev event thread exiting"); - - return NULL; -} - -static int udev_device_info(struct libusb_context *ctx, int detached, - struct udev_device *udev_dev, uint8_t *busnum, - uint8_t *devaddr, const char **sys_name) { - const char *dev_node; - - dev_node = udev_device_get_devnode(udev_dev); - if (!dev_node) { - return LIBUSB_ERROR_OTHER; - } - - *sys_name = udev_device_get_sysname(udev_dev); - if (!*sys_name) { - return LIBUSB_ERROR_OTHER; - } - - return linux_get_device_address(ctx, detached, busnum, devaddr, - dev_node, *sys_name); -} - -static void udev_hotplug_event(struct udev_device* udev_dev) -{ - const char* udev_action; - const char* sys_name = NULL; - uint8_t busnum = 0, devaddr = 0; - int detached; - int r; - - do { - udev_action = udev_device_get_action(udev_dev); - if (!udev_action) { - break; - } - - detached = !strncmp(udev_action, "remove", 6); - - r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name); - if (LIBUSB_SUCCESS != r) { - break; - } - - usbi_dbg("udev hotplug event. action: %s.", udev_action); - - if (strncmp(udev_action, "add", 3) == 0) { - linux_hotplug_enumerate(busnum, devaddr, sys_name); - } else if (detached) { - linux_device_disconnected(busnum, devaddr); - } else { - usbi_err(NULL, "ignoring udev action %s", udev_action); - } - } while (0); - - udev_device_unref(udev_dev); -} - -int linux_udev_scan_devices(struct libusb_context *ctx) -{ - struct udev_enumerate *enumerator; - struct udev_list_entry *devices, *entry; - struct udev_device *udev_dev; - const char *sys_name; - int r; - - assert(udev_ctx != NULL); - - enumerator = udev_enumerate_new(udev_ctx); - if (NULL == enumerator) { - usbi_err(ctx, "error creating udev enumerator"); - return LIBUSB_ERROR_OTHER; - } - - udev_enumerate_add_match_subsystem(enumerator, "usb"); - udev_enumerate_add_match_property(enumerator, "DEVTYPE", "usb_device"); - udev_enumerate_scan_devices(enumerator); - devices = udev_enumerate_get_list_entry(enumerator); - - udev_list_entry_foreach(entry, devices) { - const char *path = udev_list_entry_get_name(entry); - uint8_t busnum = 0, devaddr = 0; - - udev_dev = udev_device_new_from_syspath(udev_ctx, path); - - r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name); - if (r) { - udev_device_unref(udev_dev); - continue; - } - - linux_enumerate_device(ctx, busnum, devaddr, sys_name); - udev_device_unref(udev_dev); - } - - udev_enumerate_unref(enumerator); - - return LIBUSB_SUCCESS; -} - -void linux_udev_hotplug_poll(void) -{ - struct udev_device* udev_dev; - - usbi_mutex_static_lock(&linux_hotplug_lock); - do { - udev_dev = udev_monitor_receive_device(udev_monitor); - if (udev_dev) { - usbi_dbg("Handling hotplug event from hotplug_poll"); - udev_hotplug_event(udev_dev); - } - } while (udev_dev); - usbi_mutex_static_unlock(&linux_hotplug_lock); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_usbfs.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_usbfs.c deleted file mode 100644 index 6b89ba2889f..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_usbfs.c +++ /dev/null @@ -1,2738 +0,0 @@ -/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */ -/* - * Linux usbfs backend for libusb - * Copyright © 2007-2009 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * Copyright © 2013 Nathan Hjelm - * Copyright © 2012-2013 Hans de Goede - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "linux_usbfs.h" - -/* sysfs vs usbfs: - * opening a usbfs node causes the device to be resumed, so we attempt to - * avoid this during enumeration. - * - * sysfs allows us to read the kernel's in-memory copies of device descriptors - * and so forth, avoiding the need to open the device: - * - The binary "descriptors" file contains all config descriptors since - * 2.6.26, commit 217a9081d8e69026186067711131b77f0ce219ed - * - The binary "descriptors" file was added in 2.6.23, commit - * 69d42a78f935d19384d1f6e4f94b65bb162b36df, but it only contains the - * active config descriptors - * - The "busnum" file was added in 2.6.22, commit - * 83f7d958eab2fbc6b159ee92bf1493924e1d0f72 - * - The "devnum" file has been present since pre-2.6.18 - * - the "bConfigurationValue" file has been present since pre-2.6.18 - * - * If we have bConfigurationValue, busnum, and devnum, then we can determine - * the active configuration without having to open the usbfs node in RDWR mode. - * The busnum file is important as that is the only way we can relate sysfs - * devices to usbfs nodes. - * - * If we also have all descriptors, we can obtain the device descriptor and - * configuration without touching usbfs at all. - */ - -/* endianness for multi-byte fields: - * - * Descriptors exposed by usbfs have the multi-byte fields in the device - * descriptor as host endian. Multi-byte fields in the other descriptors are - * bus-endian. The kernel documentation says otherwise, but it is wrong. - * - * In sysfs all descriptors are bus-endian. - */ - -static const char *usbfs_path = NULL; - -/* use usbdev*.* device names in /dev instead of the usbfs bus directories */ -static int usbdev_names = 0; - -/* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically - * allows us to mark URBs as being part of a specific logical transfer when - * we submit them to the kernel. then, on any error except a cancellation, all - * URBs within that transfer will be cancelled and no more URBs will be - * accepted for the transfer, meaning that no more data can creep in. - * - * The BULK_CONTINUATION flag must be set on all URBs within a bulk transfer - * (in either direction) except the first. - * For IN transfers, we must also set SHORT_NOT_OK on all URBs except the - * last; it means that the kernel should treat a short reply as an error. - * For OUT transfers, SHORT_NOT_OK must not be set. it isn't needed (OUT - * transfers can't be short unless there's already some sort of error), and - * setting this flag is disallowed (a kernel with USB debugging enabled will - * reject such URBs). - */ -static int supports_flag_bulk_continuation = -1; - -/* Linux 2.6.31 fixes support for the zero length packet URB flag. This - * allows us to mark URBs that should be followed by a zero length data - * packet, which can be required by device- or class-specific protocols. - */ -static int supports_flag_zero_packet = -1; - -/* clock ID for monotonic clock, as not all clock sources are available on all - * systems. appropriate choice made at initialization time. */ -static clockid_t monotonic_clkid = -1; - -/* Linux 2.6.22 (commit 83f7d958eab2fbc6b159ee92bf1493924e1d0f72) adds a busnum - * to sysfs, so we can relate devices. This also implies that we can read - * the active configuration through bConfigurationValue */ -static int sysfs_can_relate_devices = -1; - -/* Linux 2.6.26 (commit 217a9081d8e69026186067711131b77f0ce219ed) adds all - * config descriptors (rather then just the active config) to the sysfs - * descriptors file, so from then on we can use them. */ -static int sysfs_has_descriptors = -1; - -/* how many times have we initted (and not exited) ? */ -static int init_count = 0; - -/* Serialize hotplug start/stop */ -static usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER; -/* Serialize scan-devices, event-thread, and poll */ -usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER; - -static int linux_start_event_monitor(void); -static int linux_stop_event_monitor(void); -static int linux_scan_devices(struct libusb_context *ctx); -static int sysfs_scan_device(struct libusb_context *ctx, const char *devname); -static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int); - -#if !defined(USE_UDEV) -static int linux_default_scan_devices (struct libusb_context *ctx); -#endif - -struct linux_device_priv { - char *sysfs_dir; - unsigned char *descriptors; - int descriptors_len; - int active_config; /* cache val for !sysfs_can_relate_devices */ -}; - -struct linux_device_handle_priv { - int fd; - int fd_removed; - uint32_t caps; -}; - -enum reap_action { - NORMAL = 0, - /* submission failed after the first URB, so await cancellation/completion - * of all the others */ - SUBMIT_FAILED, - - /* cancelled by user or timeout */ - CANCELLED, - - /* completed multi-URB transfer in non-final URB */ - COMPLETED_EARLY, - - /* one or more urbs encountered a low-level error */ - ERROR, -}; - -struct linux_transfer_priv { - union { - struct usbfs_urb *urbs; - struct usbfs_urb **iso_urbs; - }; - - enum reap_action reap_action; - int num_urbs; - int num_retired; - enum libusb_transfer_status reap_status; - - /* next iso packet in user-supplied transfer to be populated */ - int iso_packet_offset; -}; - -static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - char path[PATH_MAX]; - int fd; - int delay = 10000; - - if (usbdev_names) - snprintf(path, PATH_MAX, "%s/usbdev%d.%d", - usbfs_path, dev->bus_number, dev->device_address); - else - snprintf(path, PATH_MAX, "%s/%03d/%03d", - usbfs_path, dev->bus_number, dev->device_address); - - fd = open(path, mode); - if (fd != -1) - return fd; /* Success */ - - if (errno == ENOENT) { - if (!silent) - usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000); - - /* Wait 10ms for USB device path creation.*/ - nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); - - fd = open(path, mode); - if (fd != -1) - return fd; /* Success */ - } - - if (!silent) { - usbi_err(ctx, "libusb couldn't open USB device %s: %s", - path, strerror(errno)); - if (errno == EACCES && mode == O_RDWR) - usbi_err(ctx, "libusb requires write access to USB " - "device nodes."); - } - - if (errno == EACCES) - return LIBUSB_ERROR_ACCESS; - if (errno == ENOENT) - return LIBUSB_ERROR_NO_DEVICE; - return LIBUSB_ERROR_IO; -} - -static struct linux_device_priv *_device_priv(struct libusb_device *dev) -{ - return (struct linux_device_priv *) dev->os_priv; -} - -static struct linux_device_handle_priv *_device_handle_priv( - struct libusb_device_handle *handle) -{ - return (struct linux_device_handle_priv *) handle->os_priv; -} - -/* check dirent for a /dev/usbdev%d.%d name - * optionally return bus/device on success */ -static int _is_usbdev_entry(struct dirent *entry, int *bus_p, int *dev_p) -{ - int busnum, devnum; - - if (sscanf(entry->d_name, "usbdev%d.%d", &busnum, &devnum) != 2) - return 0; - - usbi_dbg("found: %s", entry->d_name); - if (bus_p != NULL) - *bus_p = busnum; - if (dev_p != NULL) - *dev_p = devnum; - return 1; -} - -static int check_usb_vfs(const char *dirname) -{ - DIR *dir; - struct dirent *entry; - int found = 0; - - dir = opendir(dirname); - if (!dir) - return 0; - - while ((entry = readdir(dir)) != NULL) { - if (entry->d_name[0] == '.') - continue; - - /* We assume if we find any files that it must be the right place */ - found = 1; - break; - } - - closedir(dir); - return found; -} - -static const char *find_usbfs_path(void) -{ - const char *path = "/dev/bus/usb"; - const char *ret = NULL; - - if (check_usb_vfs(path)) { - ret = path; - } else { - path = "/proc/bus/usb"; - if (check_usb_vfs(path)) - ret = path; - } - - /* look for /dev/usbdev*.* if the normal places fail */ - if (ret == NULL) { - struct dirent *entry; - DIR *dir; - - path = "/dev"; - dir = opendir(path); - if (dir != NULL) { - while ((entry = readdir(dir)) != NULL) { - if (_is_usbdev_entry(entry, NULL, NULL)) { - /* found one; that's enough */ - ret = path; - usbdev_names = 1; - break; - } - } - closedir(dir); - } - } - -/* On udev based systems without any usb-devices /dev/bus/usb will not - * exist. So if we've not found anything and we're using udev for hotplug - * simply assume /dev/bus/usb rather then making libusb_init fail. */ -#if defined(USE_UDEV) - if (ret == NULL) - ret = "/dev/bus/usb"; -#endif - - if (ret != NULL) - usbi_dbg("found usbfs at %s", ret); - - return ret; -} - -/* the monotonic clock is not usable on all systems (e.g. embedded ones often - * seem to lack it). fall back to REALTIME if we have to. */ -static clockid_t find_monotonic_clock(void) -{ -#ifdef CLOCK_MONOTONIC - struct timespec ts; - int r; - - /* Linux 2.6.28 adds CLOCK_MONOTONIC_RAW but we don't use it - * because it's not available through timerfd */ - r = clock_gettime(CLOCK_MONOTONIC, &ts); - if (r == 0) - return CLOCK_MONOTONIC; - usbi_dbg("monotonic clock doesn't work, errno %d", errno); -#endif - - return CLOCK_REALTIME; -} - -static int kernel_version_ge(int major, int minor, int sublevel) -{ - struct utsname uts; - int atoms, kmajor, kminor, ksublevel; - - if (uname(&uts) < 0) - return -1; - atoms = sscanf(uts.release, "%d.%d.%d", &kmajor, &kminor, &ksublevel); - if (atoms < 1) - return -1; - - if (kmajor > major) - return 1; - if (kmajor < major) - return 0; - - /* kmajor == major */ - if (atoms < 2) - return 0 == minor && 0 == sublevel; - if (kminor > minor) - return 1; - if (kminor < minor) - return 0; - - /* kminor == minor */ - if (atoms < 3) - return 0 == sublevel; - - return ksublevel >= sublevel; -} - -static int op_init(struct libusb_context *ctx) -{ - struct stat statbuf; - int r; - - usbfs_path = find_usbfs_path(); - if (!usbfs_path) { - usbi_err(ctx, "could not find usbfs"); - return LIBUSB_ERROR_OTHER; - } - - if (monotonic_clkid == -1) - monotonic_clkid = find_monotonic_clock(); - - if (supports_flag_bulk_continuation == -1) { - /* bulk continuation URB flag available from Linux 2.6.32 */ - supports_flag_bulk_continuation = kernel_version_ge(2,6,32); - if (supports_flag_bulk_continuation == -1) { - usbi_err(ctx, "error checking for bulk continuation support"); - return LIBUSB_ERROR_OTHER; - } - } - - if (supports_flag_bulk_continuation) - usbi_dbg("bulk continuation flag supported"); - - if (-1 == supports_flag_zero_packet) { - /* zero length packet URB flag fixed since Linux 2.6.31 */ - supports_flag_zero_packet = kernel_version_ge(2,6,31); - if (-1 == supports_flag_zero_packet) { - usbi_err(ctx, "error checking for zero length packet support"); - return LIBUSB_ERROR_OTHER; - } - } - - if (supports_flag_zero_packet) - usbi_dbg("zero length packet flag supported"); - - if (-1 == sysfs_has_descriptors) { - /* sysfs descriptors has all descriptors since Linux 2.6.26 */ - sysfs_has_descriptors = kernel_version_ge(2,6,26); - if (-1 == sysfs_has_descriptors) { - usbi_err(ctx, "error checking for sysfs descriptors"); - return LIBUSB_ERROR_OTHER; - } - } - - if (-1 == sysfs_can_relate_devices) { - /* sysfs has busnum since Linux 2.6.22 */ - sysfs_can_relate_devices = kernel_version_ge(2,6,22); - if (-1 == sysfs_can_relate_devices) { - usbi_err(ctx, "error checking for sysfs busnum"); - return LIBUSB_ERROR_OTHER; - } - } - - if (sysfs_can_relate_devices || sysfs_has_descriptors) { - r = stat(SYSFS_DEVICE_PATH, &statbuf); - if (r != 0 || !S_ISDIR(statbuf.st_mode)) { - usbi_warn(ctx, "sysfs not mounted"); - sysfs_can_relate_devices = 0; - sysfs_has_descriptors = 0; - } - } - - if (sysfs_can_relate_devices) - usbi_dbg("sysfs can relate devices"); - - if (sysfs_has_descriptors) - usbi_dbg("sysfs has complete descriptors"); - - usbi_mutex_static_lock(&linux_hotplug_startstop_lock); - r = LIBUSB_SUCCESS; - if (init_count == 0) { - /* start up hotplug event handler */ - r = linux_start_event_monitor(); - } - if (r == LIBUSB_SUCCESS) { - r = linux_scan_devices(ctx); - if (r == LIBUSB_SUCCESS) - init_count++; - else if (init_count == 0) - linux_stop_event_monitor(); - } else - usbi_err(ctx, "error starting hotplug event monitor"); - usbi_mutex_static_unlock(&linux_hotplug_startstop_lock); - - return r; -} - -static void op_exit(void) -{ - usbi_mutex_static_lock(&linux_hotplug_startstop_lock); - assert(init_count != 0); - if (!--init_count) { - /* tear down event handler */ - (void)linux_stop_event_monitor(); - } - usbi_mutex_static_unlock(&linux_hotplug_startstop_lock); -} - -static int linux_start_event_monitor(void) -{ -#if defined(USE_UDEV) - return linux_udev_start_event_monitor(); -#else - return linux_netlink_start_event_monitor(); -#endif -} - -static int linux_stop_event_monitor(void) -{ -#if defined(USE_UDEV) - return linux_udev_stop_event_monitor(); -#else - return linux_netlink_stop_event_monitor(); -#endif -} - -static int linux_scan_devices(struct libusb_context *ctx) -{ - int ret; - - usbi_mutex_static_lock(&linux_hotplug_lock); - -#if defined(USE_UDEV) - ret = linux_udev_scan_devices(ctx); -#else - ret = linux_default_scan_devices(ctx); -#endif - - usbi_mutex_static_unlock(&linux_hotplug_lock); - - return ret; -} - -static void op_hotplug_poll(void) -{ -#if defined(USE_UDEV) - linux_udev_hotplug_poll(); -#else - linux_netlink_hotplug_poll(); -#endif -} - -static int _open_sysfs_attr(struct libusb_device *dev, const char *attr) -{ - struct linux_device_priv *priv = _device_priv(dev); - char filename[PATH_MAX]; - int fd; - - snprintf(filename, PATH_MAX, "%s/%s/%s", - SYSFS_DEVICE_PATH, priv->sysfs_dir, attr); - fd = open(filename, O_RDONLY); - if (fd < 0) { - usbi_err(DEVICE_CTX(dev), - "open %s failed ret=%d errno=%d", filename, fd, errno); - return LIBUSB_ERROR_IO; - } - - return fd; -} - -/* Note only suitable for attributes which always read >= 0, < 0 is error */ -static int __read_sysfs_attr(struct libusb_context *ctx, - const char *devname, const char *attr) -{ - char filename[PATH_MAX]; - FILE *f; - int r, value; - - snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, - devname, attr); - f = fopen(filename, "r"); - if (f == NULL) { - if (errno == ENOENT) { - /* File doesn't exist. Assume the device has been - disconnected (see trac ticket #70). */ - return LIBUSB_ERROR_NO_DEVICE; - } - usbi_err(ctx, "open %s failed errno=%d", filename, errno); - return LIBUSB_ERROR_IO; - } - - r = fscanf(f, "%d", &value); - fclose(f); - if (r != 1) { - usbi_err(ctx, "fscanf %s returned %d, errno=%d", attr, r, errno); - return LIBUSB_ERROR_NO_DEVICE; /* For unplug race (trac #70) */ - } - if (value < 0) { - usbi_err(ctx, "%s contains a negative value", filename); - return LIBUSB_ERROR_IO; - } - - return value; -} - -static int op_get_device_descriptor(struct libusb_device *dev, - unsigned char *buffer, int *host_endian) -{ - struct linux_device_priv *priv = _device_priv(dev); - - *host_endian = sysfs_has_descriptors ? 0 : 1; - memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH); - - return 0; -} - -/* read the bConfigurationValue for a device */ -static int sysfs_get_active_config(struct libusb_device *dev, int *config) -{ - char *endptr; - char tmp[5] = {0, 0, 0, 0, 0}; - long num; - int fd; - ssize_t r; - - fd = _open_sysfs_attr(dev, "bConfigurationValue"); - if (fd < 0) - return fd; - - r = read(fd, tmp, sizeof(tmp)); - close(fd); - if (r < 0) { - usbi_err(DEVICE_CTX(dev), - "read bConfigurationValue failed ret=%d errno=%d", r, errno); - return LIBUSB_ERROR_IO; - } else if (r == 0) { - usbi_dbg("device unconfigured"); - *config = -1; - return 0; - } - - if (tmp[sizeof(tmp) - 1] != 0) { - usbi_err(DEVICE_CTX(dev), "not null-terminated?"); - return LIBUSB_ERROR_IO; - } else if (tmp[0] == 0) { - usbi_err(DEVICE_CTX(dev), "no configuration value?"); - return LIBUSB_ERROR_IO; - } - - num = strtol(tmp, &endptr, 10); - if (endptr == tmp) { - usbi_err(DEVICE_CTX(dev), "error converting '%s' to integer", tmp); - return LIBUSB_ERROR_IO; - } - - *config = (int) num; - return 0; -} - -int linux_get_device_address (struct libusb_context *ctx, int detached, - uint8_t *busnum, uint8_t *devaddr,const char *dev_node, - const char *sys_name) -{ - int sysfs_attr; - - usbi_dbg("getting address for device: %s detached: %d", sys_name, detached); - /* can't use sysfs to read the bus and device number if the - * device has been detached */ - if (!sysfs_can_relate_devices || detached || NULL == sys_name) { - if (NULL == dev_node) { - return LIBUSB_ERROR_OTHER; - } - - /* will this work with all supported kernel versions? */ - if (!strncmp(dev_node, "/dev/bus/usb", 12)) { - sscanf (dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr); - } else if (!strncmp(dev_node, "/proc/bus/usb", 13)) { - sscanf (dev_node, "/proc/bus/usb/%hhu/%hhu", busnum, devaddr); - } - - return LIBUSB_SUCCESS; - } - - usbi_dbg("scan %s", sys_name); - - sysfs_attr = __read_sysfs_attr(ctx, sys_name, "busnum"); - if (0 > sysfs_attr) - return sysfs_attr; - if (sysfs_attr > 255) - return LIBUSB_ERROR_INVALID_PARAM; - *busnum = (uint8_t) sysfs_attr; - - sysfs_attr = __read_sysfs_attr(ctx, sys_name, "devnum"); - if (0 > sysfs_attr) - return sysfs_attr; - if (sysfs_attr > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - *devaddr = (uint8_t) sysfs_attr; - - usbi_dbg("bus=%d dev=%d", *busnum, *devaddr); - - return LIBUSB_SUCCESS; -} - -/* Return offset of the next descriptor with the given type */ -static int seek_to_next_descriptor(struct libusb_context *ctx, - uint8_t descriptor_type, unsigned char *buffer, int size) -{ - struct usb_descriptor_header header; - int i; - - for (i = 0; size >= 0; i += header.bLength, size -= header.bLength) { - if (size == 0) - return LIBUSB_ERROR_NOT_FOUND; - - if (size < 2) { - usbi_err(ctx, "short descriptor read %d/2", size); - return LIBUSB_ERROR_IO; - } - usbi_parse_descriptor(buffer + i, "bb", &header, 0); - - if (i && header.bDescriptorType == descriptor_type) - return i; - } - usbi_err(ctx, "bLength overflow by %d bytes", -size); - return LIBUSB_ERROR_IO; -} - -/* Return offset to next config */ -static int seek_to_next_config(struct libusb_context *ctx, - unsigned char *buffer, int size) -{ - struct libusb_config_descriptor config; - - if (size == 0) - return LIBUSB_ERROR_NOT_FOUND; - - if (size < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "short descriptor read %d/%d", - size, LIBUSB_DT_CONFIG_SIZE); - return LIBUSB_ERROR_IO; - } - - usbi_parse_descriptor(buffer, "bbwbbbbb", &config, 0); - if (config.bDescriptorType != LIBUSB_DT_CONFIG) { - usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)", - config.bDescriptorType); - return LIBUSB_ERROR_IO; - } - - /* - * In usbfs the config descriptors are config.wTotalLength bytes apart, - * with any short reads from the device appearing as holes in the file. - * - * In sysfs wTotalLength is ignored, instead the kernel returns a - * config descriptor with verified bLength fields, with descriptors - * with an invalid bLength removed. - */ - if (sysfs_has_descriptors) { - int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG, - buffer, size); - if (next == LIBUSB_ERROR_NOT_FOUND) - next = size; - if (next < 0) - return next; - - if (next != config.wTotalLength) - usbi_warn(ctx, "config length mismatch wTotalLength " - "%d real %d", config.wTotalLength, next); - return next; - } else { - if (config.wTotalLength < LIBUSB_DT_CONFIG_SIZE) { - usbi_err(ctx, "invalid wTotalLength %d", - config.wTotalLength); - return LIBUSB_ERROR_IO; - } else if (config.wTotalLength > size) { - usbi_warn(ctx, "short descriptor read %d/%d", - size, config.wTotalLength); - return size; - } else - return config.wTotalLength; - } -} - -static int op_get_config_descriptor_by_value(struct libusb_device *dev, - uint8_t value, unsigned char **buffer, int *host_endian) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct linux_device_priv *priv = _device_priv(dev); - unsigned char *descriptors = priv->descriptors; - int size = priv->descriptors_len; - struct libusb_config_descriptor *config; - - *buffer = NULL; - /* Unlike the device desc. config descs. are always in raw format */ - *host_endian = 0; - - /* Skip device header */ - descriptors += DEVICE_DESC_LENGTH; - size -= DEVICE_DESC_LENGTH; - - /* Seek till the config is found, or till "EOF" */ - while (1) { - int next = seek_to_next_config(ctx, descriptors, size); - if (next < 0) - return next; - config = (struct libusb_config_descriptor *)descriptors; - if (config->bConfigurationValue == value) { - *buffer = descriptors; - return next; - } - size -= next; - descriptors += next; - } -} - -static int op_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buffer, size_t len, int *host_endian) -{ - int r, config; - unsigned char *config_desc; - - if (sysfs_can_relate_devices) { - r = sysfs_get_active_config(dev, &config); - if (r < 0) - return r; - } else { - /* Use cached bConfigurationValue */ - struct linux_device_priv *priv = _device_priv(dev); - config = priv->active_config; - } - if (config == -1) - return LIBUSB_ERROR_NOT_FOUND; - - r = op_get_config_descriptor_by_value(dev, config, &config_desc, - host_endian); - if (r < 0) - return r; - - len = MIN(len, r); - memcpy(buffer, config_desc, len); - return len; -} - -static int op_get_config_descriptor(struct libusb_device *dev, - uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - struct linux_device_priv *priv = _device_priv(dev); - unsigned char *descriptors = priv->descriptors; - int i, r, size = priv->descriptors_len; - - /* Unlike the device desc. config descs. are always in raw format */ - *host_endian = 0; - - /* Skip device header */ - descriptors += DEVICE_DESC_LENGTH; - size -= DEVICE_DESC_LENGTH; - - /* Seek till the config is found, or till "EOF" */ - for (i = 0; ; i++) { - r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size); - if (r < 0) - return r; - if (i == config_index) - break; - size -= r; - descriptors += r; - } - - len = MIN(len, r); - memcpy(buffer, descriptors, len); - return len; -} - -/* send a control message to retrieve active configuration */ -static int usbfs_get_active_config(struct libusb_device *dev, int fd) -{ - struct linux_device_priv *priv = _device_priv(dev); - unsigned char active_config = 0; - int r; - - struct usbfs_ctrltransfer ctrl = { - .bmRequestType = LIBUSB_ENDPOINT_IN, - .bRequest = LIBUSB_REQUEST_GET_CONFIGURATION, - .wValue = 0, - .wIndex = 0, - .wLength = 1, - .timeout = 1000, - .data = &active_config - }; - - r = ioctl(fd, IOCTL_USBFS_CONTROL, &ctrl); - if (r < 0) { - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - /* we hit this error path frequently with buggy devices :( */ - usbi_warn(DEVICE_CTX(dev), - "get_configuration failed ret=%d errno=%d", r, errno); - priv->active_config = -1; - } else { - if (active_config > 0) { - priv->active_config = active_config; - } else { - /* some buggy devices have a configuration 0, but we're - * reaching into the corner of a corner case here, so let's - * not support buggy devices in these circumstances. - * stick to the specs: a configuration value of 0 means - * unconfigured. */ - usbi_warn(DEVICE_CTX(dev), - "active cfg 0? assuming unconfigured device"); - priv->active_config = -1; - } - } - - return LIBUSB_SUCCESS; -} - -static int initialize_device(struct libusb_device *dev, uint8_t busnum, - uint8_t devaddr, const char *sysfs_dir) -{ - struct linux_device_priv *priv = _device_priv(dev); - struct libusb_context *ctx = DEVICE_CTX(dev); - int descriptors_size = 512; /* Begin with a 1024 byte alloc */ - int fd, speed; - ssize_t r; - - dev->bus_number = busnum; - dev->device_address = devaddr; - - if (sysfs_dir) { - priv->sysfs_dir = strdup(sysfs_dir); - if (!priv->sysfs_dir) - return LIBUSB_ERROR_NO_MEM; - - /* Note speed can contain 1.5, in this case __read_sysfs_attr - will stop parsing at the '.' and return 1 */ - speed = __read_sysfs_attr(DEVICE_CTX(dev), sysfs_dir, "speed"); - if (speed >= 0) { - switch (speed) { - case 1: dev->speed = LIBUSB_SPEED_LOW; break; - case 12: dev->speed = LIBUSB_SPEED_FULL; break; - case 480: dev->speed = LIBUSB_SPEED_HIGH; break; - case 5000: dev->speed = LIBUSB_SPEED_SUPER; break; - default: - usbi_warn(DEVICE_CTX(dev), "Unknown device speed: %d Mbps", speed); - } - } - } - - /* cache descriptors in memory */ - if (sysfs_has_descriptors) - fd = _open_sysfs_attr(dev, "descriptors"); - else - fd = _get_usbfs_fd(dev, O_RDONLY, 0); - if (fd < 0) - return fd; - - do { - descriptors_size *= 2; - priv->descriptors = usbi_reallocf(priv->descriptors, - descriptors_size); - if (!priv->descriptors) { - close(fd); - return LIBUSB_ERROR_NO_MEM; - } - /* usbfs has holes in the file */ - if (!sysfs_has_descriptors) { - memset(priv->descriptors + priv->descriptors_len, - 0, descriptors_size - priv->descriptors_len); - } - r = read(fd, priv->descriptors + priv->descriptors_len, - descriptors_size - priv->descriptors_len); - if (r < 0) { - usbi_err(ctx, "read descriptor failed ret=%d errno=%d", - fd, errno); - close(fd); - return LIBUSB_ERROR_IO; - } - priv->descriptors_len += r; - } while (priv->descriptors_len == descriptors_size); - - close(fd); - - if (priv->descriptors_len < DEVICE_DESC_LENGTH) { - usbi_err(ctx, "short descriptor read (%d)", - priv->descriptors_len); - return LIBUSB_ERROR_IO; - } - - if (sysfs_can_relate_devices) - return LIBUSB_SUCCESS; - - /* cache active config */ - fd = _get_usbfs_fd(dev, O_RDWR, 1); - if (fd < 0) { - /* cannot send a control message to determine the active - * config. just assume the first one is active. */ - usbi_warn(ctx, "Missing rw usbfs access; cannot determine " - "active configuration descriptor"); - if (priv->descriptors_len >= - (DEVICE_DESC_LENGTH + LIBUSB_DT_CONFIG_SIZE)) { - struct libusb_config_descriptor config; - usbi_parse_descriptor( - priv->descriptors + DEVICE_DESC_LENGTH, - "bbwbbbbb", &config, 0); - priv->active_config = config.bConfigurationValue; - } else - priv->active_config = -1; /* No config dt */ - - return LIBUSB_SUCCESS; - } - - r = usbfs_get_active_config(dev, fd); - close(fd); - - return r; -} - -static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir) -{ - struct libusb_context *ctx = DEVICE_CTX(dev); - struct libusb_device *it; - char *parent_sysfs_dir, *tmp; - int ret, add_parent = 1; - - /* XXX -- can we figure out the topology when using usbfs? */ - if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) { - /* either using usbfs or finding the parent of a root hub */ - return LIBUSB_SUCCESS; - } - - parent_sysfs_dir = strdup(sysfs_dir); - if (NULL == parent_sysfs_dir) { - return LIBUSB_ERROR_NO_MEM; - } - if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) || - NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) { - dev->port_number = atoi(tmp + 1); - *tmp = '\0'; - } else { - usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info", - parent_sysfs_dir); - free (parent_sysfs_dir); - return LIBUSB_SUCCESS; - } - - /* is the parent a root hub? */ - if (NULL == strchr(parent_sysfs_dir, '-')) { - tmp = parent_sysfs_dir; - ret = asprintf (&parent_sysfs_dir, "usb%s", tmp); - free (tmp); - if (0 > ret) { - return LIBUSB_ERROR_NO_MEM; - } - } - -retry: - /* find the parent in the context */ - usbi_mutex_lock(&ctx->usb_devs_lock); - list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) { - struct linux_device_priv *priv = _device_priv(it); - if (priv->sysfs_dir) { - if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) { - dev->parent_dev = libusb_ref_device(it); - break; - } - } - } - usbi_mutex_unlock(&ctx->usb_devs_lock); - - if (!dev->parent_dev && add_parent) { - usbi_dbg("parent_dev %s not enumerated yet, enumerating now", - parent_sysfs_dir); - sysfs_scan_device(ctx, parent_sysfs_dir); - add_parent = 0; - goto retry; - } - - usbi_dbg("Dev %p (%s) has parent %p (%s) port %d", dev, sysfs_dir, - dev->parent_dev, parent_sysfs_dir, dev->port_number); - - free (parent_sysfs_dir); - - return LIBUSB_SUCCESS; -} - -int linux_enumerate_device(struct libusb_context *ctx, - uint8_t busnum, uint8_t devaddr, const char *sysfs_dir) -{ - unsigned long session_id; - struct libusb_device *dev; - int r = 0; - - /* FIXME: session ID is not guaranteed unique as addresses can wrap and - * will be reused. instead we should add a simple sysfs attribute with - * a session ID. */ - session_id = busnum << 8 | devaddr; - usbi_dbg("busnum %d devaddr %d session_id %ld", busnum, devaddr, - session_id); - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev) { - /* device already exists in the context */ - usbi_dbg("session_id %ld already exists", session_id); - libusb_unref_device(dev); - return LIBUSB_SUCCESS; - } - - usbi_dbg("allocating new device for %d/%d (session %ld)", - busnum, devaddr, session_id); - dev = usbi_alloc_device(ctx, session_id); - if (!dev) - return LIBUSB_ERROR_NO_MEM; - - r = initialize_device(dev, busnum, devaddr, sysfs_dir); - if (r < 0) - goto out; - r = usbi_sanitize_device(dev); - if (r < 0) - goto out; - - r = linux_get_parent_info(dev, sysfs_dir); - if (r < 0) - goto out; -out: - if (r < 0) - libusb_unref_device(dev); - else - usbi_connect_device(dev); - - return r; -} - -void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name) -{ - struct libusb_context *ctx; - - usbi_mutex_static_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - linux_enumerate_device(ctx, busnum, devaddr, sys_name); - } - usbi_mutex_static_unlock(&active_contexts_lock); -} - -void linux_device_disconnected(uint8_t busnum, uint8_t devaddr) -{ - struct libusb_context *ctx; - struct libusb_device *dev; - unsigned long session_id = busnum << 8 | devaddr; - - usbi_mutex_static_lock(&active_contexts_lock); - list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { - dev = usbi_get_device_by_session_id (ctx, session_id); - if (NULL != dev) { - usbi_disconnect_device (dev); - libusb_unref_device(dev); - } else { - usbi_dbg("device not found for session %x", session_id); - } - } - usbi_mutex_static_unlock(&active_contexts_lock); -} - -#if !defined(USE_UDEV) -/* open a bus directory and adds all discovered devices to the context */ -static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum) -{ - DIR *dir; - char dirpath[PATH_MAX]; - struct dirent *entry; - int r = LIBUSB_ERROR_IO; - - snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum); - usbi_dbg("%s", dirpath); - dir = opendir(dirpath); - if (!dir) { - usbi_err(ctx, "opendir '%s' failed, errno=%d", dirpath, errno); - /* FIXME: should handle valid race conditions like hub unplugged - * during directory iteration - this is not an error */ - return r; - } - - while ((entry = readdir(dir))) { - int devaddr; - - if (entry->d_name[0] == '.') - continue; - - devaddr = atoi(entry->d_name); - if (devaddr == 0) { - usbi_dbg("unknown dir entry %s", entry->d_name); - continue; - } - - if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) { - usbi_dbg("failed to enumerate dir entry %s", entry->d_name); - continue; - } - - r = 0; - } - - closedir(dir); - return r; -} - -static int usbfs_get_device_list(struct libusb_context *ctx) -{ - struct dirent *entry; - DIR *buses = opendir(usbfs_path); - int r = 0; - - if (!buses) { - usbi_err(ctx, "opendir buses failed errno=%d", errno); - return LIBUSB_ERROR_IO; - } - - while ((entry = readdir(buses))) { - int busnum; - - if (entry->d_name[0] == '.') - continue; - - if (usbdev_names) { - int devaddr; - if (!_is_usbdev_entry(entry, &busnum, &devaddr)) - continue; - - r = linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL); - if (r < 0) { - usbi_dbg("failed to enumerate dir entry %s", entry->d_name); - continue; - } - } else { - busnum = atoi(entry->d_name); - if (busnum == 0) { - usbi_dbg("unknown dir entry %s", entry->d_name); - continue; - } - - r = usbfs_scan_busdir(ctx, busnum); - if (r < 0) - break; - } - } - - closedir(buses); - return r; - -} -#endif - -static int sysfs_scan_device(struct libusb_context *ctx, const char *devname) -{ - uint8_t busnum, devaddr; - int ret; - - ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname); - if (LIBUSB_SUCCESS != ret) { - return ret; - } - - return linux_enumerate_device(ctx, busnum & 0xff, devaddr & 0xff, - devname); -} - -#if !defined(USE_UDEV) -static int sysfs_get_device_list(struct libusb_context *ctx) -{ - DIR *devices = opendir(SYSFS_DEVICE_PATH); - struct dirent *entry; - int r = LIBUSB_ERROR_IO; - - if (!devices) { - usbi_err(ctx, "opendir devices failed errno=%d", errno); - return r; - } - - while ((entry = readdir(devices))) { - if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3)) - || strchr(entry->d_name, ':')) - continue; - - if (sysfs_scan_device(ctx, entry->d_name)) { - usbi_dbg("failed to enumerate dir entry %s", entry->d_name); - continue; - } - - r = 0; - } - - closedir(devices); - return r; -} - -static int linux_default_scan_devices (struct libusb_context *ctx) -{ - /* we can retrieve device list and descriptors from sysfs or usbfs. - * sysfs is preferable, because if we use usbfs we end up resuming - * any autosuspended USB devices. however, sysfs is not available - * everywhere, so we need a usbfs fallback too. - * - * as described in the "sysfs vs usbfs" comment at the top of this - * file, sometimes we have sysfs but not enough information to - * relate sysfs devices to usbfs nodes. op_init() determines the - * adequacy of sysfs and sets sysfs_can_relate_devices. - */ - if (sysfs_can_relate_devices != 0) - return sysfs_get_device_list(ctx); - else - return usbfs_get_device_list(ctx); -} -#endif - -static int op_open(struct libusb_device_handle *handle) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); - int r; - - hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0); - if (hpriv->fd < 0) { - if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) { - /* device will still be marked as attached if hotplug monitor thread - * hasn't processed remove event yet */ - usbi_mutex_static_lock(&linux_hotplug_lock); - if (handle->dev->attached) { - usbi_dbg("open failed with no device, but device still attached"); - linux_device_disconnected(handle->dev->bus_number, - handle->dev->device_address); - } - usbi_mutex_static_unlock(&linux_hotplug_lock); - } - return hpriv->fd; - } - - r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps); - if (r < 0) { - if (errno == ENOTTY) - usbi_dbg("getcap not available"); - else - usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno); - hpriv->caps = 0; - if (supports_flag_zero_packet) - hpriv->caps |= USBFS_CAP_ZERO_PACKET; - if (supports_flag_bulk_continuation) - hpriv->caps |= USBFS_CAP_BULK_CONTINUATION; - } - - r = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT); - if (r < 0) - close(hpriv->fd); - - return r; -} - -static void op_close(struct libusb_device_handle *dev_handle) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(dev_handle); - /* fd may have already been removed by POLLERR condition in op_handle_events() */ - if (!hpriv->fd_removed) - usbi_remove_pollfd(HANDLE_CTX(dev_handle), hpriv->fd); - close(hpriv->fd); -} - -static int op_get_configuration(struct libusb_device_handle *handle, - int *config) -{ - int r; - - if (sysfs_can_relate_devices) { - r = sysfs_get_active_config(handle->dev, config); - } else { - r = usbfs_get_active_config(handle->dev, - _device_handle_priv(handle)->fd); - if (r == LIBUSB_SUCCESS) - *config = _device_priv(handle->dev)->active_config; - } - if (r < 0) - return r; - - if (*config == -1) { - usbi_err(HANDLE_CTX(handle), "device unconfigured"); - *config = 0; - } - - return 0; -} - -static int op_set_configuration(struct libusb_device_handle *handle, int config) -{ - struct linux_device_priv *priv = _device_priv(handle->dev); - int fd = _device_handle_priv(handle)->fd; - int r = ioctl(fd, IOCTL_USBFS_SETCONFIG, &config); - if (r) { - if (errno == EINVAL) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EBUSY) - return LIBUSB_ERROR_BUSY; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), "failed, error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - /* update our cached active config descriptor */ - priv->active_config = config; - - return LIBUSB_SUCCESS; -} - -static int claim_interface(struct libusb_device_handle *handle, int iface) -{ - int fd = _device_handle_priv(handle)->fd; - int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface); - if (r) { - if (errno == ENOENT) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EBUSY) - return LIBUSB_ERROR_BUSY; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "claim interface failed, error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - return 0; -} - -static int release_interface(struct libusb_device_handle *handle, int iface) -{ - int fd = _device_handle_priv(handle)->fd; - int r = ioctl(fd, IOCTL_USBFS_RELEASEINTF, &iface); - if (r) { - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "release interface failed, error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - return 0; -} - -static int op_set_interface(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_setinterface setintf; - int r; - - setintf.interface = iface; - setintf.altsetting = altsetting; - r = ioctl(fd, IOCTL_USBFS_SETINTF, &setintf); - if (r) { - if (errno == EINVAL) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "setintf failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return 0; -} - -static int op_clear_halt(struct libusb_device_handle *handle, - unsigned char endpoint) -{ - int fd = _device_handle_priv(handle)->fd; - unsigned int _endpoint = endpoint; - int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint); - if (r) { - if (errno == ENOENT) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "clear_halt failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return 0; -} - -static int op_reset_device(struct libusb_device_handle *handle) -{ - int fd = _device_handle_priv(handle)->fd; - int i, r, ret = 0; - - /* Doing a device reset will cause the usbfs driver to get unbound - from any interfaces it is bound to. By voluntarily unbinding - the usbfs driver ourself, we stop the kernel from rebinding - the interface after reset (which would end up with the interface - getting bound to the in kernel driver if any). */ - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (handle->claimed_interfaces & (1L << i)) { - release_interface(handle, i); - } - } - - usbi_mutex_lock(&handle->lock); - r = ioctl(fd, IOCTL_USBFS_RESET, NULL); - if (r) { - if (errno == ENODEV) { - ret = LIBUSB_ERROR_NOT_FOUND; - goto out; - } - - usbi_err(HANDLE_CTX(handle), - "reset failed error %d errno %d", r, errno); - ret = LIBUSB_ERROR_OTHER; - goto out; - } - - /* And re-claim any interfaces which were claimed before the reset */ - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (handle->claimed_interfaces & (1L << i)) { - /* - * A driver may have completed modprobing during - * IOCTL_USBFS_RESET, and bound itself as soon as - * IOCTL_USBFS_RESET released the device lock - */ - r = detach_kernel_driver_and_claim(handle, i); - if (r) { - usbi_warn(HANDLE_CTX(handle), - "failed to re-claim interface %d after reset: %s", - i, libusb_error_name(r)); - handle->claimed_interfaces &= ~(1L << i); - ret = LIBUSB_ERROR_NOT_FOUND; - } - } - } -out: - usbi_mutex_unlock(&handle->lock); - return ret; -} - -static int do_streams_ioctl(struct libusb_device_handle *handle, long req, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints) -{ - int r, fd = _device_handle_priv(handle)->fd; - struct usbfs_streams *streams; - - if (num_endpoints > 30) /* Max 15 in + 15 out eps */ - return LIBUSB_ERROR_INVALID_PARAM; - - streams = malloc(sizeof(struct usbfs_streams) + num_endpoints); - if (!streams) - return LIBUSB_ERROR_NO_MEM; - - streams->num_streams = num_streams; - streams->num_eps = num_endpoints; - memcpy(streams->eps, endpoints, num_endpoints); - - r = ioctl(fd, req, streams); - - free(streams); - - if (r < 0) { - if (errno == ENOTTY) - return LIBUSB_ERROR_NOT_SUPPORTED; - else if (errno == EINVAL) - return LIBUSB_ERROR_INVALID_PARAM; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "streams-ioctl failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - return r; -} - -static int op_alloc_streams(struct libusb_device_handle *handle, - uint32_t num_streams, unsigned char *endpoints, int num_endpoints) -{ - return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS, - num_streams, endpoints, num_endpoints); -} - -static int op_free_streams(struct libusb_device_handle *handle, - unsigned char *endpoints, int num_endpoints) -{ - return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0, - endpoints, num_endpoints); -} - -static unsigned char *op_dev_mem_alloc(struct libusb_device_handle *handle, - size_t len) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); - unsigned char *buffer = (unsigned char *)mmap(NULL, len, - PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0); - if (buffer == MAP_FAILED) { - usbi_err(HANDLE_CTX(handle), "alloc dev mem failed errno %d", - errno); - return NULL; - } - return buffer; -} - -static int op_dev_mem_free(struct libusb_device_handle *handle, - unsigned char *buffer, size_t len) -{ - if (munmap(buffer, len) != 0) { - usbi_err(HANDLE_CTX(handle), "free dev mem failed errno %d", - errno); - return LIBUSB_ERROR_OTHER; - } else { - return LIBUSB_SUCCESS; - } -} - -static int op_kernel_driver_active(struct libusb_device_handle *handle, - int interface) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_getdriver getdrv; - int r; - - getdrv.interface = interface; - r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv); - if (r) { - if (errno == ENODATA) - return 0; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "get driver failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return (strcmp(getdrv.driver, "usbfs") == 0) ? 0 : 1; -} - -static int op_detach_kernel_driver(struct libusb_device_handle *handle, - int interface) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_ioctl command; - struct usbfs_getdriver getdrv; - int r; - - command.ifno = interface; - command.ioctl_code = IOCTL_USBFS_DISCONNECT; - command.data = NULL; - - getdrv.interface = interface; - r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv); - if (r == 0 && strcmp(getdrv.driver, "usbfs") == 0) - return LIBUSB_ERROR_NOT_FOUND; - - r = ioctl(fd, IOCTL_USBFS_IOCTL, &command); - if (r) { - if (errno == ENODATA) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EINVAL) - return LIBUSB_ERROR_INVALID_PARAM; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), - "detach failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } - - return 0; -} - -static int op_attach_kernel_driver(struct libusb_device_handle *handle, - int interface) -{ - int fd = _device_handle_priv(handle)->fd; - struct usbfs_ioctl command; - int r; - - command.ifno = interface; - command.ioctl_code = IOCTL_USBFS_CONNECT; - command.data = NULL; - - r = ioctl(fd, IOCTL_USBFS_IOCTL, &command); - if (r < 0) { - if (errno == ENODATA) - return LIBUSB_ERROR_NOT_FOUND; - else if (errno == EINVAL) - return LIBUSB_ERROR_INVALID_PARAM; - else if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - else if (errno == EBUSY) - return LIBUSB_ERROR_BUSY; - - usbi_err(HANDLE_CTX(handle), - "attach failed error %d errno %d", r, errno); - return LIBUSB_ERROR_OTHER; - } else if (r == 0) { - return LIBUSB_ERROR_NOT_FOUND; - } - - return 0; -} - -static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle, - int interface) -{ - struct usbfs_disconnect_claim dc; - int r, fd = _device_handle_priv(handle)->fd; - - dc.interface = interface; - strcpy(dc.driver, "usbfs"); - dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER; - r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc); - if (r == 0 || (r != 0 && errno != ENOTTY)) { - if (r == 0) - return 0; - - switch (errno) { - case EBUSY: - return LIBUSB_ERROR_BUSY; - case EINVAL: - return LIBUSB_ERROR_INVALID_PARAM; - case ENODEV: - return LIBUSB_ERROR_NO_DEVICE; - } - usbi_err(HANDLE_CTX(handle), - "disconnect-and-claim failed errno %d", errno); - return LIBUSB_ERROR_OTHER; - } - - /* Fallback code for kernels which don't support the - disconnect-and-claim ioctl */ - r = op_detach_kernel_driver(handle, interface); - if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND) - return r; - - return claim_interface(handle, interface); -} - -static int op_claim_interface(struct libusb_device_handle *handle, int iface) -{ - if (handle->auto_detach_kernel_driver) - return detach_kernel_driver_and_claim(handle, iface); - else - return claim_interface(handle, iface); -} - -static int op_release_interface(struct libusb_device_handle *handle, int iface) -{ - int r; - - r = release_interface(handle, iface); - if (r) - return r; - - if (handle->auto_detach_kernel_driver) - op_attach_kernel_driver(handle, iface); - - return 0; -} - -static void op_destroy_device(struct libusb_device *dev) -{ - struct linux_device_priv *priv = _device_priv(dev); - if (priv->descriptors) - free(priv->descriptors); - if (priv->sysfs_dir) - free(priv->sysfs_dir); -} - -/* URBs are discarded in reverse order of submission to avoid races. */ -static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = - usbi_transfer_get_os_priv(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - int i, ret = 0; - struct usbfs_urb *urb; - - for (i = last_plus_one - 1; i >= first; i--) { - if (LIBUSB_TRANSFER_TYPE_ISOCHRONOUS == transfer->type) - urb = tpriv->iso_urbs[i]; - else - urb = &tpriv->urbs[i]; - - if (0 == ioctl(dpriv->fd, IOCTL_USBFS_DISCARDURB, urb)) - continue; - - if (EINVAL == errno) { - usbi_dbg("URB not found --> assuming ready to be reaped"); - if (i == (last_plus_one - 1)) - ret = LIBUSB_ERROR_NOT_FOUND; - } else if (ENODEV == errno) { - usbi_dbg("Device not found for URB --> assuming ready to be reaped"); - ret = LIBUSB_ERROR_NO_DEVICE; - } else { - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised discard errno %d", errno); - ret = LIBUSB_ERROR_OTHER; - } - } - return ret; -} - -static void free_iso_urbs(struct linux_transfer_priv *tpriv) -{ - int i; - for (i = 0; i < tpriv->num_urbs; i++) { - struct usbfs_urb *urb = tpriv->iso_urbs[i]; - if (!urb) - break; - free(urb); - } - - free(tpriv->iso_urbs); - tpriv->iso_urbs = NULL; -} - -static int submit_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - struct usbfs_urb *urbs; - int is_out = (transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) - == LIBUSB_ENDPOINT_OUT; - int bulk_buffer_len, use_bulk_continuation; - int r; - int i; - - if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) && - !(dpriv->caps & USBFS_CAP_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; - - /* - * Older versions of usbfs place a 16kb limit on bulk URBs. We work - * around this by splitting large transfers into 16k blocks, and then - * submit all urbs at once. it would be simpler to submit one urb at - * a time, but there is a big performance gain doing it this way. - * - * Newer versions lift the 16k limit (USBFS_CAP_NO_PACKET_SIZE_LIM), - * using arbritary large transfers can still be a bad idea though, as - * the kernel needs to allocate physical contiguous memory for this, - * which may fail for large buffers. - * - * The kernel solves this problem by splitting the transfer into - * blocks itself when the host-controller is scatter-gather capable - * (USBFS_CAP_BULK_SCATTER_GATHER), which most controllers are. - * - * Last, there is the issue of short-transfers when splitting, for - * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION - * is needed, but this is not always available. - */ - if (dpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) { - /* Good! Just submit everything in one go */ - bulk_buffer_len = transfer->length ? transfer->length : 1; - use_bulk_continuation = 0; - } else if (dpriv->caps & USBFS_CAP_BULK_CONTINUATION) { - /* Split the transfers and use bulk-continuation to - avoid issues with short-transfers */ - bulk_buffer_len = MAX_BULK_BUFFER_LENGTH; - use_bulk_continuation = 1; - } else if (dpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) { - /* Don't split, assume the kernel can alloc the buffer - (otherwise the submit will fail with -ENOMEM) */ - bulk_buffer_len = transfer->length ? transfer->length : 1; - use_bulk_continuation = 0; - } else { - /* Bad, splitting without bulk-continuation, short transfers - which end before the last urb will not work reliable! */ - /* Note we don't warn here as this is "normal" on kernels < - 2.6.32 and not a problem for most applications */ - bulk_buffer_len = MAX_BULK_BUFFER_LENGTH; - use_bulk_continuation = 0; - } - - int num_urbs = transfer->length / bulk_buffer_len; - int last_urb_partial = 0; - - if (transfer->length == 0) { - num_urbs = 1; - } else if ((transfer->length % bulk_buffer_len) > 0) { - last_urb_partial = 1; - num_urbs++; - } - usbi_dbg("need %d urbs for new transfer with length %d", num_urbs, - transfer->length); - urbs = calloc(num_urbs, sizeof(struct usbfs_urb)); - if (!urbs) - return LIBUSB_ERROR_NO_MEM; - tpriv->urbs = urbs; - tpriv->num_urbs = num_urbs; - tpriv->num_retired = 0; - tpriv->reap_action = NORMAL; - tpriv->reap_status = LIBUSB_TRANSFER_COMPLETED; - - for (i = 0; i < num_urbs; i++) { - struct usbfs_urb *urb = &urbs[i]; - urb->usercontext = itransfer; - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_BULK: - urb->type = USBFS_URB_TYPE_BULK; - urb->stream_id = 0; - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - urb->type = USBFS_URB_TYPE_BULK; - urb->stream_id = itransfer->stream_id; - break; - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - urb->type = USBFS_URB_TYPE_INTERRUPT; - break; - } - urb->endpoint = transfer->endpoint; - urb->buffer = transfer->buffer + (i * bulk_buffer_len); - /* don't set the short not ok flag for the last URB */ - if (use_bulk_continuation && !is_out && (i < num_urbs - 1)) - urb->flags = USBFS_URB_SHORT_NOT_OK; - if (i == num_urbs - 1 && last_urb_partial) - urb->buffer_length = transfer->length % bulk_buffer_len; - else if (transfer->length == 0) - urb->buffer_length = 0; - else - urb->buffer_length = bulk_buffer_len; - - if (i > 0 && use_bulk_continuation) - urb->flags |= USBFS_URB_BULK_CONTINUATION; - - /* we have already checked that the flag is supported */ - if (is_out && i == num_urbs - 1 && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) - urb->flags |= USBFS_URB_ZERO_PACKET; - - r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); - if (r < 0) { - if (errno == ENODEV) { - r = LIBUSB_ERROR_NO_DEVICE; - } else { - usbi_err(TRANSFER_CTX(transfer), - "submiturb failed error %d errno=%d", r, errno); - r = LIBUSB_ERROR_IO; - } - - /* if the first URB submission fails, we can simply free up and - * return failure immediately. */ - if (i == 0) { - usbi_dbg("first URB failed, easy peasy"); - free(urbs); - tpriv->urbs = NULL; - return r; - } - - /* if it's not the first URB that failed, the situation is a bit - * tricky. we may need to discard all previous URBs. there are - * complications: - * - discarding is asynchronous - discarded urbs will be reaped - * later. the user must not have freed the transfer when the - * discarded URBs are reaped, otherwise libusb will be using - * freed memory. - * - the earlier URBs may have completed successfully and we do - * not want to throw away any data. - * - this URB failing may be no error; EREMOTEIO means that - * this transfer simply didn't need all the URBs we submitted - * so, we report that the transfer was submitted successfully and - * in case of error we discard all previous URBs. later when - * the final reap completes we can report error to the user, - * or success if an earlier URB was completed successfully. - */ - tpriv->reap_action = EREMOTEIO == errno ? COMPLETED_EARLY : SUBMIT_FAILED; - - /* The URBs we haven't submitted yet we count as already - * retired. */ - tpriv->num_retired += num_urbs - i; - - /* If we completed short then don't try to discard. */ - if (COMPLETED_EARLY == tpriv->reap_action) - return 0; - - discard_urbs(itransfer, 0, i); - - usbi_dbg("reporting successful submission but waiting for %d " - "discards before reporting error", i); - return 0; - } - } - - return 0; -} - -static int submit_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - struct usbfs_urb **urbs; - size_t alloc_size; - int num_packets = transfer->num_iso_packets; - int i; - int this_urb_len = 0; - int num_urbs = 1; - int packet_offset = 0; - unsigned int packet_len; - unsigned char *urb_buffer = transfer->buffer; - - /* usbfs places arbitrary limits on iso URBs. this limit has changed - * at least three times, and it's difficult to accurately detect which - * limit this running kernel might impose. so we attempt to submit - * whatever the user has provided. if the kernel rejects the request - * due to its size, we return an error indicating such to the user. - */ - - /* calculate how many URBs we need */ - for (i = 0; i < num_packets; i++) { - unsigned int space_remaining = MAX_ISO_BUFFER_LENGTH - this_urb_len; - packet_len = transfer->iso_packet_desc[i].length; - - if (packet_len > space_remaining) { - num_urbs++; - this_urb_len = packet_len; - /* check that we can actually support this packet length */ - if (this_urb_len > MAX_ISO_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - } else { - this_urb_len += packet_len; - } - } - usbi_dbg("need %d %dk URBs for transfer", num_urbs, MAX_ISO_BUFFER_LENGTH / 1024); - - urbs = calloc(num_urbs, sizeof(*urbs)); - if (!urbs) - return LIBUSB_ERROR_NO_MEM; - - tpriv->iso_urbs = urbs; - tpriv->num_urbs = num_urbs; - tpriv->num_retired = 0; - tpriv->reap_action = NORMAL; - tpriv->iso_packet_offset = 0; - - /* allocate + initialize each URB with the correct number of packets */ - for (i = 0; i < num_urbs; i++) { - struct usbfs_urb *urb; - unsigned int space_remaining_in_urb = MAX_ISO_BUFFER_LENGTH; - int urb_packet_offset = 0; - unsigned char *urb_buffer_orig = urb_buffer; - int j; - int k; - - /* swallow up all the packets we can fit into this URB */ - while (packet_offset < transfer->num_iso_packets) { - packet_len = transfer->iso_packet_desc[packet_offset].length; - if (packet_len <= space_remaining_in_urb) { - /* throw it in */ - urb_packet_offset++; - packet_offset++; - space_remaining_in_urb -= packet_len; - urb_buffer += packet_len; - } else { - /* it can't fit, save it for the next URB */ - break; - } - } - - alloc_size = sizeof(*urb) - + (urb_packet_offset * sizeof(struct usbfs_iso_packet_desc)); - urb = calloc(1, alloc_size); - if (!urb) { - free_iso_urbs(tpriv); - return LIBUSB_ERROR_NO_MEM; - } - urbs[i] = urb; - - /* populate packet lengths */ - for (j = 0, k = packet_offset - urb_packet_offset; - k < packet_offset; k++, j++) { - packet_len = transfer->iso_packet_desc[k].length; - urb->iso_frame_desc[j].length = packet_len; - } - - urb->usercontext = itransfer; - urb->type = USBFS_URB_TYPE_ISO; - /* FIXME: interface for non-ASAP data? */ - urb->flags = USBFS_URB_ISO_ASAP; - urb->endpoint = transfer->endpoint; - urb->number_of_packets = urb_packet_offset; - urb->buffer = urb_buffer_orig; - } - - /* submit URBs */ - for (i = 0; i < num_urbs; i++) { - int r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]); - if (r < 0) { - if (errno == ENODEV) { - r = LIBUSB_ERROR_NO_DEVICE; - } else if (errno == EINVAL) { - usbi_warn(TRANSFER_CTX(transfer), - "submiturb failed, transfer too large"); - r = LIBUSB_ERROR_INVALID_PARAM; - } else { - usbi_err(TRANSFER_CTX(transfer), - "submiturb failed error %d errno=%d", r, errno); - r = LIBUSB_ERROR_IO; - } - - /* if the first URB submission fails, we can simply free up and - * return failure immediately. */ - if (i == 0) { - usbi_dbg("first URB failed, easy peasy"); - free_iso_urbs(tpriv); - return r; - } - - /* if it's not the first URB that failed, the situation is a bit - * tricky. we must discard all previous URBs. there are - * complications: - * - discarding is asynchronous - discarded urbs will be reaped - * later. the user must not have freed the transfer when the - * discarded URBs are reaped, otherwise libusb will be using - * freed memory. - * - the earlier URBs may have completed successfully and we do - * not want to throw away any data. - * so, in this case we discard all the previous URBs BUT we report - * that the transfer was submitted successfully. then later when - * the final discard completes we can report error to the user. - */ - tpriv->reap_action = SUBMIT_FAILED; - - /* The URBs we haven't submitted yet we count as already - * retired. */ - tpriv->num_retired = num_urbs - i; - discard_urbs(itransfer, 0, i); - - usbi_dbg("reporting successful submission but waiting for %d " - "discards before reporting error", i); - return 0; - } - } - - return 0; -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_device_handle_priv *dpriv = - _device_handle_priv(transfer->dev_handle); - struct usbfs_urb *urb; - int r; - - if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - urb = calloc(1, sizeof(struct usbfs_urb)); - if (!urb) - return LIBUSB_ERROR_NO_MEM; - tpriv->urbs = urb; - tpriv->num_urbs = 1; - tpriv->reap_action = NORMAL; - - urb->usercontext = itransfer; - urb->type = USBFS_URB_TYPE_CONTROL; - urb->endpoint = transfer->endpoint; - urb->buffer = transfer->buffer; - urb->buffer_length = transfer->length; - - r = ioctl(dpriv->fd, IOCTL_USBFS_SUBMITURB, urb); - if (r < 0) { - free(urb); - tpriv->urbs = NULL; - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(TRANSFER_CTX(transfer), - "submiturb failed error %d errno=%d", r, errno); - return LIBUSB_ERROR_IO; - } - return 0; -} - -static int op_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); - default: - usbi_err(TRANSFER_CTX(transfer), - "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int op_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int r; - - if (!tpriv->urbs) - return LIBUSB_ERROR_NOT_FOUND; - - r = discard_urbs(itransfer, 0, tpriv->num_urbs); - if (r != 0) - return r; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - if (tpriv->reap_action == ERROR) - break; - /* else, fall through */ - default: - tpriv->reap_action = CANCELLED; - } - - return 0; -} - -static void op_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - - /* urbs can be freed also in submit_transfer so lock mutex first */ - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (tpriv->urbs) { - free(tpriv->urbs); - tpriv->urbs = NULL; - } - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - if (tpriv->iso_urbs) { - free_iso_urbs(tpriv); - tpriv->iso_urbs = NULL; - } - break; - default: - usbi_err(TRANSFER_CTX(transfer), - "unknown endpoint type %d", transfer->type); - } -} - -static int handle_bulk_completion(struct usbi_transfer *itransfer, - struct usbfs_urb *urb) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - int urb_idx = urb - tpriv->urbs; - - usbi_mutex_lock(&itransfer->lock); - usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status, - urb_idx + 1, tpriv->num_urbs); - - tpriv->num_retired++; - - if (tpriv->reap_action != NORMAL) { - /* cancelled, submit_fail, or completed early */ - usbi_dbg("abnormal reap: urb status %d", urb->status); - - /* even though we're in the process of cancelling, it's possible that - * we may receive some data in these URBs that we don't want to lose. - * examples: - * 1. while the kernel is cancelling all the packets that make up an - * URB, a few of them might complete. so we get back a successful - * cancellation *and* some data. - * 2. we receive a short URB which marks the early completion condition, - * so we start cancelling the remaining URBs. however, we're too - * slow and another URB completes (or at least completes partially). - * (this can't happen since we always use BULK_CONTINUATION.) - * - * When this happens, our objectives are not to lose any "surplus" data, - * and also to stick it at the end of the previously-received data - * (closing any holes), so that libusb reports the total amount of - * transferred data and presents it in a contiguous chunk. - */ - if (urb->actual_length > 0) { - unsigned char *target = transfer->buffer + itransfer->transferred; - usbi_dbg("received %d bytes of surplus data", urb->actual_length); - if (urb->buffer != target) { - usbi_dbg("moving surplus data from offset %d to offset %d", - (unsigned char *) urb->buffer - transfer->buffer, - target - transfer->buffer); - memmove(target, urb->buffer, urb->actual_length); - } - itransfer->transferred += urb->actual_length; - } - - if (tpriv->num_retired == tpriv->num_urbs) { - usbi_dbg("abnormal reap: last URB handled, reporting"); - if (tpriv->reap_action != COMPLETED_EARLY && - tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) - tpriv->reap_status = LIBUSB_TRANSFER_ERROR; - goto completed; - } - goto out_unlock; - } - - itransfer->transferred += urb->actual_length; - - /* Many of these errors can occur on *any* urb of a multi-urb - * transfer. When they do, we tear down the rest of the transfer. - */ - switch (urb->status) { - case 0: - break; - case -EREMOTEIO: /* short transfer */ - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: - break; - case -ENODEV: - case -ESHUTDOWN: - usbi_dbg("device removed"); - tpriv->reap_status = LIBUSB_TRANSFER_NO_DEVICE; - goto cancel_remaining; - case -EPIPE: - usbi_dbg("detected endpoint stall"); - if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) - tpriv->reap_status = LIBUSB_TRANSFER_STALL; - goto cancel_remaining; - case -EOVERFLOW: - /* overflow can only ever occur in the last urb */ - usbi_dbg("overflow, actual_length=%d", urb->actual_length); - if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED) - tpriv->reap_status = LIBUSB_TRANSFER_OVERFLOW; - goto completed; - case -ETIME: - case -EPROTO: - case -EILSEQ: - case -ECOMM: - case -ENOSR: - usbi_dbg("low level error %d", urb->status); - tpriv->reap_action = ERROR; - goto cancel_remaining; - default: - usbi_warn(ITRANSFER_CTX(itransfer), - "unrecognised urb status %d", urb->status); - tpriv->reap_action = ERROR; - goto cancel_remaining; - } - - /* if we're the last urb or we got less data than requested then we're - * done */ - if (urb_idx == tpriv->num_urbs - 1) { - usbi_dbg("last URB in transfer --> complete!"); - goto completed; - } else if (urb->actual_length < urb->buffer_length) { - usbi_dbg("short transfer %d/%d --> complete!", - urb->actual_length, urb->buffer_length); - if (tpriv->reap_action == NORMAL) - tpriv->reap_action = COMPLETED_EARLY; - } else - goto out_unlock; - -cancel_remaining: - if (ERROR == tpriv->reap_action && LIBUSB_TRANSFER_COMPLETED == tpriv->reap_status) - tpriv->reap_status = LIBUSB_TRANSFER_ERROR; - - if (tpriv->num_retired == tpriv->num_urbs) /* nothing to cancel */ - goto completed; - - /* cancel remaining urbs and wait for their completion before - * reporting results */ - discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs); - -out_unlock: - usbi_mutex_unlock(&itransfer->lock); - return 0; - -completed: - free(tpriv->urbs); - tpriv->urbs = NULL; - usbi_mutex_unlock(&itransfer->lock); - return CANCELLED == tpriv->reap_action ? - usbi_handle_transfer_cancellation(itransfer) : - usbi_handle_transfer_completion(itransfer, tpriv->reap_status); -} - -static int handle_iso_completion(struct usbi_transfer *itransfer, - struct usbfs_urb *urb) -{ - struct libusb_transfer *transfer = - USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int num_urbs = tpriv->num_urbs; - int urb_idx = 0; - int i; - enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; - - usbi_mutex_lock(&itransfer->lock); - for (i = 0; i < num_urbs; i++) { - if (urb == tpriv->iso_urbs[i]) { - urb_idx = i + 1; - break; - } - } - if (urb_idx == 0) { - usbi_err(TRANSFER_CTX(transfer), "could not locate urb!"); - usbi_mutex_unlock(&itransfer->lock); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("handling completion status %d of iso urb %d/%d", urb->status, - urb_idx, num_urbs); - - /* copy isochronous results back in */ - - for (i = 0; i < urb->number_of_packets; i++) { - struct usbfs_iso_packet_desc *urb_desc = &urb->iso_frame_desc[i]; - struct libusb_iso_packet_descriptor *lib_desc = - &transfer->iso_packet_desc[tpriv->iso_packet_offset++]; - lib_desc->status = LIBUSB_TRANSFER_COMPLETED; - switch (urb_desc->status) { - case 0: - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: - break; - case -ENODEV: - case -ESHUTDOWN: - usbi_dbg("device removed"); - lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE; - break; - case -EPIPE: - usbi_dbg("detected endpoint stall"); - lib_desc->status = LIBUSB_TRANSFER_STALL; - break; - case -EOVERFLOW: - usbi_dbg("overflow error"); - lib_desc->status = LIBUSB_TRANSFER_OVERFLOW; - break; - case -ETIME: - case -EPROTO: - case -EILSEQ: - case -ECOMM: - case -ENOSR: - case -EXDEV: - usbi_dbg("low-level USB error %d", urb_desc->status); - lib_desc->status = LIBUSB_TRANSFER_ERROR; - break; - default: - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised urb status %d", urb_desc->status); - lib_desc->status = LIBUSB_TRANSFER_ERROR; - break; - } - lib_desc->actual_length = urb_desc->actual_length; - } - - tpriv->num_retired++; - - if (tpriv->reap_action != NORMAL) { /* cancelled or submit_fail */ - usbi_dbg("CANCEL: urb status %d", urb->status); - - if (tpriv->num_retired == num_urbs) { - usbi_dbg("CANCEL: last URB handled, reporting"); - free_iso_urbs(tpriv); - if (tpriv->reap_action == CANCELLED) { - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_cancellation(itransfer); - } else { - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, - LIBUSB_TRANSFER_ERROR); - } - } - goto out; - } - - switch (urb->status) { - case 0: - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: - break; - case -ESHUTDOWN: - usbi_dbg("device removed"); - status = LIBUSB_TRANSFER_NO_DEVICE; - break; - default: - usbi_warn(TRANSFER_CTX(transfer), - "unrecognised urb status %d", urb->status); - status = LIBUSB_TRANSFER_ERROR; - break; - } - - /* if we're the last urb then we're done */ - if (urb_idx == num_urbs) { - usbi_dbg("last URB in transfer --> complete!"); - free_iso_urbs(tpriv); - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, status); - } - -out: - usbi_mutex_unlock(&itransfer->lock); - return 0; -} - -static int handle_control_completion(struct usbi_transfer *itransfer, - struct usbfs_urb *urb) -{ - struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); - int status; - - usbi_mutex_lock(&itransfer->lock); - usbi_dbg("handling completion status %d", urb->status); - - itransfer->transferred += urb->actual_length; - - if (tpriv->reap_action == CANCELLED) { - if (urb->status != 0 && urb->status != -ENOENT) - usbi_warn(ITRANSFER_CTX(itransfer), - "cancel: unrecognised urb status %d", urb->status); - free(tpriv->urbs); - tpriv->urbs = NULL; - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_cancellation(itransfer); - } - - switch (urb->status) { - case 0: - status = LIBUSB_TRANSFER_COMPLETED; - break; - case -ENOENT: /* cancelled */ - status = LIBUSB_TRANSFER_CANCELLED; - break; - case -ENODEV: - case -ESHUTDOWN: - usbi_dbg("device removed"); - status = LIBUSB_TRANSFER_NO_DEVICE; - break; - case -EPIPE: - usbi_dbg("unsupported control request"); - status = LIBUSB_TRANSFER_STALL; - break; - case -EOVERFLOW: - usbi_dbg("control overflow error"); - status = LIBUSB_TRANSFER_OVERFLOW; - break; - case -ETIME: - case -EPROTO: - case -EILSEQ: - case -ECOMM: - case -ENOSR: - usbi_dbg("low-level bus error occurred"); - status = LIBUSB_TRANSFER_ERROR; - break; - default: - usbi_warn(ITRANSFER_CTX(itransfer), - "unrecognised urb status %d", urb->status); - status = LIBUSB_TRANSFER_ERROR; - break; - } - - free(tpriv->urbs); - tpriv->urbs = NULL; - usbi_mutex_unlock(&itransfer->lock); - return usbi_handle_transfer_completion(itransfer, status); -} - -static int reap_for_handle(struct libusb_device_handle *handle) -{ - struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); - int r; - struct usbfs_urb *urb; - struct usbi_transfer *itransfer; - struct libusb_transfer *transfer; - - r = ioctl(hpriv->fd, IOCTL_USBFS_REAPURBNDELAY, &urb); - if (r == -1 && errno == EAGAIN) - return 1; - if (r < 0) { - if (errno == ENODEV) - return LIBUSB_ERROR_NO_DEVICE; - - usbi_err(HANDLE_CTX(handle), "reap failed error %d errno=%d", - r, errno); - return LIBUSB_ERROR_IO; - } - - itransfer = urb->usercontext; - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status, - urb->actual_length); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return handle_iso_completion(itransfer, urb); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return handle_bulk_completion(itransfer, urb); - case LIBUSB_TRANSFER_TYPE_CONTROL: - return handle_control_completion(itransfer, urb); - default: - usbi_err(HANDLE_CTX(handle), "unrecognised endpoint type %x", - transfer->type); - return LIBUSB_ERROR_OTHER; - } -} - -static int op_handle_events(struct libusb_context *ctx, - struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - int r; - unsigned int i = 0; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - struct pollfd *pollfd = &fds[i]; - struct libusb_device_handle *handle; - struct linux_device_handle_priv *hpriv = NULL; - - if (!pollfd->revents) - continue; - - num_ready--; - list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { - hpriv = _device_handle_priv(handle); - if (hpriv->fd == pollfd->fd) - break; - } - - if (!hpriv || hpriv->fd != pollfd->fd) { - usbi_err(ctx, "cannot find handle for fd %d", - pollfd->fd); - continue; - } - - if (pollfd->revents & POLLERR) { - /* remove the fd from the pollfd set so that it doesn't continuously - * trigger an event, and flag that it has been removed so op_close() - * doesn't try to remove it a second time */ - usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd); - hpriv->fd_removed = 1; - - /* device will still be marked as attached if hotplug monitor thread - * hasn't processed remove event yet */ - usbi_mutex_static_lock(&linux_hotplug_lock); - if (handle->dev->attached) - linux_device_disconnected(handle->dev->bus_number, - handle->dev->device_address); - usbi_mutex_static_unlock(&linux_hotplug_lock); - - if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) { - do { - r = reap_for_handle(handle); - } while (r == 0); - } - - usbi_handle_disconnect(handle); - continue; - } - - do { - r = reap_for_handle(handle); - } while (r == 0); - if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE) - continue; - else if (r < 0) - goto out; - } - - r = 0; -out: - usbi_mutex_unlock(&ctx->open_devs_lock); - return r; -} - -static int op_clock_gettime(int clk_id, struct timespec *tp) -{ - switch (clk_id) { - case USBI_CLOCK_MONOTONIC: - return clock_gettime(monotonic_clkid, tp); - case USBI_CLOCK_REALTIME: - return clock_gettime(CLOCK_REALTIME, tp); - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -#ifdef USBI_TIMERFD_AVAILABLE -static clockid_t op_get_timerfd_clockid(void) -{ - return monotonic_clkid; - -} -#endif - -const struct usbi_os_backend linux_usbfs_backend = { - .name = "Linux usbfs", - .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, - .init = op_init, - .exit = op_exit, - .get_device_list = NULL, - .hotplug_poll = op_hotplug_poll, - .get_device_descriptor = op_get_device_descriptor, - .get_active_config_descriptor = op_get_active_config_descriptor, - .get_config_descriptor = op_get_config_descriptor, - .get_config_descriptor_by_value = op_get_config_descriptor_by_value, - - .open = op_open, - .close = op_close, - .get_configuration = op_get_configuration, - .set_configuration = op_set_configuration, - .claim_interface = op_claim_interface, - .release_interface = op_release_interface, - - .set_interface_altsetting = op_set_interface, - .clear_halt = op_clear_halt, - .reset_device = op_reset_device, - - .alloc_streams = op_alloc_streams, - .free_streams = op_free_streams, - - .dev_mem_alloc = op_dev_mem_alloc, - .dev_mem_free = op_dev_mem_free, - - .kernel_driver_active = op_kernel_driver_active, - .detach_kernel_driver = op_detach_kernel_driver, - .attach_kernel_driver = op_attach_kernel_driver, - - .destroy_device = op_destroy_device, - - .submit_transfer = op_submit_transfer, - .cancel_transfer = op_cancel_transfer, - .clear_transfer_priv = op_clear_transfer_priv, - - .handle_events = op_handle_events, - - .clock_gettime = op_clock_gettime, - -#ifdef USBI_TIMERFD_AVAILABLE - .get_timerfd_clockid = op_get_timerfd_clockid, -#endif - - .device_priv_size = sizeof(struct linux_device_priv), - .device_handle_priv_size = sizeof(struct linux_device_handle_priv), - .transfer_priv_size = sizeof(struct linux_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_usbfs.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_usbfs.h deleted file mode 100644 index 8bd3ebcb163..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/linux_usbfs.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * usbfs header structures - * Copyright © 2007 Daniel Drake - * Copyright © 2001 Johannes Erdfelt - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_USBFS_H -#define LIBUSB_USBFS_H - -#include - -#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices" - -struct usbfs_ctrltransfer { - /* keep in sync with usbdevice_fs.h:usbdevfs_ctrltransfer */ - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - - uint32_t timeout; /* in milliseconds */ - - /* pointer to data */ - void *data; -}; - -struct usbfs_bulktransfer { - /* keep in sync with usbdevice_fs.h:usbdevfs_bulktransfer */ - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - - /* pointer to data */ - void *data; -}; - -struct usbfs_setinterface { - /* keep in sync with usbdevice_fs.h:usbdevfs_setinterface */ - unsigned int interface; - unsigned int altsetting; -}; - -#define USBFS_MAXDRIVERNAME 255 - -struct usbfs_getdriver { - unsigned int interface; - char driver[USBFS_MAXDRIVERNAME + 1]; -}; - -#define USBFS_URB_SHORT_NOT_OK 0x01 -#define USBFS_URB_ISO_ASAP 0x02 -#define USBFS_URB_BULK_CONTINUATION 0x04 -#define USBFS_URB_QUEUE_BULK 0x10 -#define USBFS_URB_ZERO_PACKET 0x40 - -enum usbfs_urb_type { - USBFS_URB_TYPE_ISO = 0, - USBFS_URB_TYPE_INTERRUPT = 1, - USBFS_URB_TYPE_CONTROL = 2, - USBFS_URB_TYPE_BULK = 3, -}; - -struct usbfs_iso_packet_desc { - unsigned int length; - unsigned int actual_length; - unsigned int status; -}; - -#define MAX_ISO_BUFFER_LENGTH 49152 * 128 -#define MAX_BULK_BUFFER_LENGTH 16384 -#define MAX_CTRL_BUFFER_LENGTH 4096 - -struct usbfs_urb { - unsigned char type; - unsigned char endpoint; - int status; - unsigned int flags; - void *buffer; - int buffer_length; - int actual_length; - int start_frame; - union { - int number_of_packets; /* Only used for isoc urbs */ - unsigned int stream_id; /* Only used with bulk streams */ - }; - int error_count; - unsigned int signr; - void *usercontext; - struct usbfs_iso_packet_desc iso_frame_desc[0]; -}; - -struct usbfs_connectinfo { - unsigned int devnum; - unsigned char slow; -}; - -struct usbfs_ioctl { - int ifno; /* interface 0..N ; negative numbers reserved */ - int ioctl_code; /* MUST encode size + direction of data so the - * macros in give correct values */ - void *data; /* param buffer (in, or out) */ -}; - -struct usbfs_hub_portinfo { - unsigned char numports; - unsigned char port[127]; /* port to device num mapping */ -}; - -#define USBFS_CAP_ZERO_PACKET 0x01 -#define USBFS_CAP_BULK_CONTINUATION 0x02 -#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04 -#define USBFS_CAP_BULK_SCATTER_GATHER 0x08 -#define USBFS_CAP_REAP_AFTER_DISCONNECT 0x10 - -#define USBFS_DISCONNECT_CLAIM_IF_DRIVER 0x01 -#define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02 - -struct usbfs_disconnect_claim { - unsigned int interface; - unsigned int flags; - char driver[USBFS_MAXDRIVERNAME + 1]; -}; - -struct usbfs_streams { - unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */ - unsigned int num_eps; - unsigned char eps[0]; -}; - -#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer) -#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer) -#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int) -#define IOCTL_USBFS_SETINTF _IOR('U', 4, struct usbfs_setinterface) -#define IOCTL_USBFS_SETCONFIG _IOR('U', 5, unsigned int) -#define IOCTL_USBFS_GETDRIVER _IOW('U', 8, struct usbfs_getdriver) -#define IOCTL_USBFS_SUBMITURB _IOR('U', 10, struct usbfs_urb) -#define IOCTL_USBFS_DISCARDURB _IO('U', 11) -#define IOCTL_USBFS_REAPURB _IOW('U', 12, void *) -#define IOCTL_USBFS_REAPURBNDELAY _IOW('U', 13, void *) -#define IOCTL_USBFS_CLAIMINTF _IOR('U', 15, unsigned int) -#define IOCTL_USBFS_RELEASEINTF _IOR('U', 16, unsigned int) -#define IOCTL_USBFS_CONNECTINFO _IOW('U', 17, struct usbfs_connectinfo) -#define IOCTL_USBFS_IOCTL _IOWR('U', 18, struct usbfs_ioctl) -#define IOCTL_USBFS_HUB_PORTINFO _IOR('U', 19, struct usbfs_hub_portinfo) -#define IOCTL_USBFS_RESET _IO('U', 20) -#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int) -#define IOCTL_USBFS_DISCONNECT _IO('U', 22) -#define IOCTL_USBFS_CONNECT _IO('U', 23) -#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int) -#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int) -#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32) -#define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim) -#define IOCTL_USBFS_ALLOC_STREAMS _IOR('U', 28, struct usbfs_streams) -#define IOCTL_USBFS_FREE_STREAMS _IOR('U', 29, struct usbfs_streams) - -extern usbi_mutex_static_t linux_hotplug_lock; - -#if defined(HAVE_LIBUDEV) -int linux_udev_start_event_monitor(void); -int linux_udev_stop_event_monitor(void); -int linux_udev_scan_devices(struct libusb_context *ctx); -void linux_udev_hotplug_poll(void); -#else -int linux_netlink_start_event_monitor(void); -int linux_netlink_stop_event_monitor(void); -void linux_netlink_hotplug_poll(void); -#endif - -void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name); -void linux_device_disconnected(uint8_t busnum, uint8_t devaddr); - -int linux_get_device_address (struct libusb_context *ctx, int detached, - uint8_t *busnum, uint8_t *devaddr, const char *dev_node, - const char *sys_name); -int linux_enumerate_device(struct libusb_context *ctx, - uint8_t busnum, uint8_t devaddr, const char *sysfs_dir); - -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/netbsd_usb.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/netbsd_usb.c deleted file mode 100644 index ad1ede73e10..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/netbsd_usb.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright © 2011 Martin Pieuchot - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "libusbi.h" - -struct device_priv { - char devnode[16]; - int fd; - - unsigned char *cdesc; /* active config descriptor */ - usb_device_descriptor_t ddesc; /* usb device descriptor */ -}; - -struct handle_priv { - int endpoints[USB_MAX_ENDPOINTS]; -}; - -/* - * Backend functions - */ -static int netbsd_get_device_list(struct libusb_context *, - struct discovered_devs **); -static int netbsd_open(struct libusb_device_handle *); -static void netbsd_close(struct libusb_device_handle *); - -static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *, - int *); -static int netbsd_get_active_config_descriptor(struct libusb_device *, - unsigned char *, size_t, int *); -static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t, - unsigned char *, size_t, int *); - -static int netbsd_get_configuration(struct libusb_device_handle *, int *); -static int netbsd_set_configuration(struct libusb_device_handle *, int); - -static int netbsd_claim_interface(struct libusb_device_handle *, int); -static int netbsd_release_interface(struct libusb_device_handle *, int); - -static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int, - int); -static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char); -static int netbsd_reset_device(struct libusb_device_handle *); -static void netbsd_destroy_device(struct libusb_device *); - -static int netbsd_submit_transfer(struct usbi_transfer *); -static int netbsd_cancel_transfer(struct usbi_transfer *); -static void netbsd_clear_transfer_priv(struct usbi_transfer *); -static int netbsd_handle_transfer_completion(struct usbi_transfer *); -static int netbsd_clock_gettime(int, struct timespec *); - -/* - * Private functions - */ -static int _errno_to_libusb(int); -static int _cache_active_config_descriptor(struct libusb_device *, int); -static int _sync_control_transfer(struct usbi_transfer *); -static int _sync_gen_transfer(struct usbi_transfer *); -static int _access_endpoint(struct libusb_transfer *); - -const struct usbi_os_backend netbsd_backend = { - "Synchronous NetBSD backend", - 0, - NULL, /* init() */ - NULL, /* exit() */ - netbsd_get_device_list, - NULL, /* hotplug_poll */ - netbsd_open, - netbsd_close, - - netbsd_get_device_descriptor, - netbsd_get_active_config_descriptor, - netbsd_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ - - netbsd_get_configuration, - netbsd_set_configuration, - - netbsd_claim_interface, - netbsd_release_interface, - - netbsd_set_interface_altsetting, - netbsd_clear_halt, - netbsd_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc() */ - NULL, /* dev_mem_free() */ - - NULL, /* kernel_driver_active() */ - NULL, /* detach_kernel_driver() */ - NULL, /* attach_kernel_driver() */ - - netbsd_destroy_device, - - netbsd_submit_transfer, - netbsd_cancel_transfer, - netbsd_clear_transfer_priv, - - NULL, /* handle_events() */ - netbsd_handle_transfer_completion, - - netbsd_clock_gettime, - sizeof(struct device_priv), - sizeof(struct handle_priv), - 0, /* transfer_priv_size */ -}; - -int -netbsd_get_device_list(struct libusb_context * ctx, - struct discovered_devs **discdevs) -{ - struct libusb_device *dev; - struct device_priv *dpriv; - struct usb_device_info di; - unsigned long session_id; - char devnode[16]; - int fd, err, i; - - usbi_dbg(""); - - /* Only ugen(4) is supported */ - for (i = 0; i < USB_MAX_DEVICES; i++) { - /* Control endpoint is always .00 */ - snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i); - - if ((fd = open(devnode, O_RDONLY)) < 0) { - if (errno != ENOENT && errno != ENXIO) - usbi_err(ctx, "could not open %s", devnode); - continue; - } - - if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0) - continue; - - session_id = (di.udi_bus << 8 | di.udi_addr); - dev = usbi_get_device_by_session_id(ctx, session_id); - - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) - return (LIBUSB_ERROR_NO_MEM); - - dev->bus_number = di.udi_bus; - dev->device_address = di.udi_addr; - dev->speed = di.udi_speed; - - dpriv = (struct device_priv *)dev->os_priv; - strlcpy(dpriv->devnode, devnode, sizeof(devnode)); - dpriv->fd = -1; - - if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) { - err = errno; - goto error; - } - - dpriv->cdesc = NULL; - if (_cache_active_config_descriptor(dev, fd)) { - err = errno; - goto error; - } - - if ((err = usbi_sanitize_device(dev))) - goto error; - } - close(fd); - - if (discovered_devs_append(*discdevs, dev) == NULL) - return (LIBUSB_ERROR_NO_MEM); - - libusb_unref_device(dev); - } - - return (LIBUSB_SUCCESS); - -error: - close(fd); - libusb_unref_device(dev); - return _errno_to_libusb(err); -} - -int -netbsd_open(struct libusb_device_handle *handle) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - dpriv->fd = open(dpriv->devnode, O_RDWR); - if (dpriv->fd < 0) { - dpriv->fd = open(dpriv->devnode, O_RDONLY); - if (dpriv->fd < 0) - return _errno_to_libusb(errno); - } - - usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); - - return (LIBUSB_SUCCESS); -} - -void -netbsd_close(struct libusb_device_handle *handle) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - usbi_dbg("close: fd %d", dpriv->fd); - - close(dpriv->fd); - dpriv->fd = -1; -} - -int -netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, - int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); - - *host_endian = 0; - - return (LIBUSB_SUCCESS); -} - -int -netbsd_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buf, size_t len, int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - usb_config_descriptor_t *ucd; - - ucd = (usb_config_descriptor_t *) dpriv->cdesc; - len = MIN(len, UGETW(ucd->wTotalLength)); - - usbi_dbg("len %d", len); - - memcpy(buf, dpriv->cdesc, len); - - *host_endian = 0; - - return len; -} - -int -netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, - unsigned char *buf, size_t len, int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - struct usb_full_desc ufd; - int fd, err; - - usbi_dbg("index %d, len %d", idx, len); - - /* A config descriptor may be requested before opening the device */ - if (dpriv->fd >= 0) { - fd = dpriv->fd; - } else { - fd = open(dpriv->devnode, O_RDONLY); - if (fd < 0) - return _errno_to_libusb(errno); - } - - ufd.ufd_config_index = idx; - ufd.ufd_size = len; - ufd.ufd_data = buf; - - if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { - err = errno; - if (dpriv->fd < 0) - close(fd); - return _errno_to_libusb(err); - } - - if (dpriv->fd < 0) - close(fd); - - *host_endian = 0; - - return len; -} - -int -netbsd_get_configuration(struct libusb_device_handle *handle, int *config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - usbi_dbg(""); - - if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0) - return _errno_to_libusb(errno); - - usbi_dbg("configuration %d", *config); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_set_configuration(struct libusb_device_handle *handle, int config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - usbi_dbg("configuration %d", config); - - if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) - return _errno_to_libusb(errno); - - return _cache_active_config_descriptor(handle->dev, dpriv->fd); -} - -int -netbsd_claim_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - hpriv->endpoints[i] = -1; - - return (LIBUSB_SUCCESS); -} - -int -netbsd_release_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - if (hpriv->endpoints[i] >= 0) - close(hpriv->endpoints[i]); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - struct usb_alt_interface intf; - - usbi_dbg("iface %d, setting %d", iface, altsetting); - - memset(&intf, 0, sizeof(intf)); - - intf.uai_interface_index = iface; - intf.uai_alt_no = altsetting; - - if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) - return _errno_to_libusb(errno); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - struct usb_ctl_request req; - - usbi_dbg(""); - - req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; - req.ucr_request.bRequest = UR_CLEAR_FEATURE; - USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); - USETW(req.ucr_request.wIndex, endpoint); - USETW(req.ucr_request.wLength, 0); - - if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0) - return _errno_to_libusb(errno); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_reset_device(struct libusb_device_handle *handle) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -netbsd_destroy_device(struct libusb_device *dev) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - free(dpriv->cdesc); -} - -int -netbsd_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct handle_priv *hpriv; - int err = 0; - - usbi_dbg(""); - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - err = _sync_control_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - if (IS_XFEROUT(transfer)) { - /* Isochronous write is not supported */ - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - if (err) - return (err); - - usbi_signal_transfer_completion(itransfer); - - return (LIBUSB_SUCCESS); -} - -int -netbsd_cancel_transfer(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -netbsd_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - /* Nothing to do */ -} - -int -netbsd_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); -} - -int -netbsd_clock_gettime(int clkid, struct timespec *tp) -{ - usbi_dbg("clock %d", clkid); - - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -int -_errno_to_libusb(int err) -{ - switch (err) { - case EIO: - return (LIBUSB_ERROR_IO); - case EACCES: - return (LIBUSB_ERROR_ACCESS); - case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); - case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); - } - - usbi_dbg("error: %s", strerror(err)); - - return (LIBUSB_ERROR_OTHER); -} - -int -_cache_active_config_descriptor(struct libusb_device *dev, int fd) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - struct usb_config_desc ucd; - struct usb_full_desc ufd; - unsigned char* buf; - int len; - - usbi_dbg("fd %d", fd); - - ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX; - - if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0) - return _errno_to_libusb(errno); - - usbi_dbg("active bLength %d", ucd.ucd_desc.bLength); - - len = UGETW(ucd.ucd_desc.wTotalLength); - buf = malloc(len); - if (buf == NULL) - return (LIBUSB_ERROR_NO_MEM); - - ufd.ufd_config_index = ucd.ucd_config_index; - ufd.ufd_size = len; - ufd.ufd_data = buf; - - usbi_dbg("index %d, len %d", ufd.ufd_config_index, len); - - if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) { - free(buf); - return _errno_to_libusb(errno); - } - - if (dpriv->cdesc) - free(dpriv->cdesc); - dpriv->cdesc = buf; - - return (0); -} - -int -_sync_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct libusb_control_setup *setup; - struct device_priv *dpriv; - struct usb_ctl_request req; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - setup = (struct libusb_control_setup *)transfer->buffer; - - usbi_dbg("type %d request %d value %d index %d length %d timeout %d", - setup->bmRequestType, setup->bRequest, - libusb_le16_to_cpu(setup->wValue), - libusb_le16_to_cpu(setup->wIndex), - libusb_le16_to_cpu(setup->wLength), transfer->timeout); - - req.ucr_request.bmRequestType = setup->bmRequestType; - req.ucr_request.bRequest = setup->bRequest; - /* Don't use USETW, libusb already deals with the endianness */ - (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; - (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; - (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; - req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - req.ucr_flags = USBD_SHORT_XFER_OK; - - if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) - return _errno_to_libusb(errno); - - itransfer->transferred = req.ucr_actlen; - - usbi_dbg("transferred %d", itransfer->transferred); - - return (0); -} - -int -_access_endpoint(struct libusb_transfer *transfer) -{ - struct handle_priv *hpriv; - struct device_priv *dpriv; - char *s, devnode[16]; - int fd, endpt; - mode_t mode; - - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - - endpt = UE_GET_ADDR(transfer->endpoint); - mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; - - usbi_dbg("endpoint %d mode %d", endpt, mode); - - if (hpriv->endpoints[endpt] < 0) { - /* Pick the right node given the control one */ - strlcpy(devnode, dpriv->devnode, sizeof(devnode)); - s = strchr(devnode, '.'); - snprintf(s, 4, ".%02d", endpt); - - /* We may need to read/write to the same endpoint later. */ - if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) - if ((fd = open(devnode, mode)) < 0) - return (-1); - - hpriv->endpoints[endpt] = fd; - } - - return (hpriv->endpoints[endpt]); -} - -int -_sync_gen_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - int fd, nr = 1; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - /* - * Bulk, Interrupt or Isochronous transfer depends on the - * endpoint and thus the node to open. - */ - if ((fd = _access_endpoint(transfer)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if (IS_XFERIN(transfer)) { - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) - return _errno_to_libusb(errno); - - nr = read(fd, transfer->buffer, transfer->length); - } else { - nr = write(fd, transfer->buffer, transfer->length); - } - - if (nr < 0) - return _errno_to_libusb(errno); - - itransfer->transferred = nr; - - return (0); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/openbsd_usb.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/openbsd_usb.c deleted file mode 100644 index c660257114b..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/openbsd_usb.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * Copyright © 2011-2013 Martin Pieuchot - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "libusbi.h" - -struct device_priv { - char *devname; /* name of the ugen(4) node */ - int fd; /* device file descriptor */ - - unsigned char *cdesc; /* active config descriptor */ - usb_device_descriptor_t ddesc; /* usb device descriptor */ -}; - -struct handle_priv { - int endpoints[USB_MAX_ENDPOINTS]; -}; - -/* - * Backend functions - */ -static int obsd_get_device_list(struct libusb_context *, - struct discovered_devs **); -static int obsd_open(struct libusb_device_handle *); -static void obsd_close(struct libusb_device_handle *); - -static int obsd_get_device_descriptor(struct libusb_device *, unsigned char *, - int *); -static int obsd_get_active_config_descriptor(struct libusb_device *, - unsigned char *, size_t, int *); -static int obsd_get_config_descriptor(struct libusb_device *, uint8_t, - unsigned char *, size_t, int *); - -static int obsd_get_configuration(struct libusb_device_handle *, int *); -static int obsd_set_configuration(struct libusb_device_handle *, int); - -static int obsd_claim_interface(struct libusb_device_handle *, int); -static int obsd_release_interface(struct libusb_device_handle *, int); - -static int obsd_set_interface_altsetting(struct libusb_device_handle *, int, - int); -static int obsd_clear_halt(struct libusb_device_handle *, unsigned char); -static int obsd_reset_device(struct libusb_device_handle *); -static void obsd_destroy_device(struct libusb_device *); - -static int obsd_submit_transfer(struct usbi_transfer *); -static int obsd_cancel_transfer(struct usbi_transfer *); -static void obsd_clear_transfer_priv(struct usbi_transfer *); -static int obsd_handle_transfer_completion(struct usbi_transfer *); -static int obsd_clock_gettime(int, struct timespec *); - -/* - * Private functions - */ -static int _errno_to_libusb(int); -static int _cache_active_config_descriptor(struct libusb_device *); -static int _sync_control_transfer(struct usbi_transfer *); -static int _sync_gen_transfer(struct usbi_transfer *); -static int _access_endpoint(struct libusb_transfer *); - -static int _bus_open(int); - - -const struct usbi_os_backend openbsd_backend = { - "Synchronous OpenBSD backend", - 0, - NULL, /* init() */ - NULL, /* exit() */ - obsd_get_device_list, - NULL, /* hotplug_poll */ - obsd_open, - obsd_close, - - obsd_get_device_descriptor, - obsd_get_active_config_descriptor, - obsd_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ - - obsd_get_configuration, - obsd_set_configuration, - - obsd_claim_interface, - obsd_release_interface, - - obsd_set_interface_altsetting, - obsd_clear_halt, - obsd_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc() */ - NULL, /* dev_mem_free() */ - - NULL, /* kernel_driver_active() */ - NULL, /* detach_kernel_driver() */ - NULL, /* attach_kernel_driver() */ - - obsd_destroy_device, - - obsd_submit_transfer, - obsd_cancel_transfer, - obsd_clear_transfer_priv, - - NULL, /* handle_events() */ - obsd_handle_transfer_completion, - - obsd_clock_gettime, - sizeof(struct device_priv), - sizeof(struct handle_priv), - 0, /* transfer_priv_size */ -}; - -#define DEVPATH "/dev/" -#define USBDEV DEVPATH "usb" - -int -obsd_get_device_list(struct libusb_context * ctx, - struct discovered_devs **discdevs) -{ - struct discovered_devs *ddd; - struct libusb_device *dev; - struct device_priv *dpriv; - struct usb_device_info di; - struct usb_device_ddesc dd; - unsigned long session_id; - char devices[USB_MAX_DEVICES]; - char busnode[16]; - char *udevname; - int fd, addr, i, j; - - usbi_dbg(""); - - for (i = 0; i < 8; i++) { - snprintf(busnode, sizeof(busnode), USBDEV "%d", i); - - if ((fd = open(busnode, O_RDWR)) < 0) { - if (errno != ENOENT && errno != ENXIO) - usbi_err(ctx, "could not open %s", busnode); - continue; - } - - bzero(devices, sizeof(devices)); - for (addr = 1; addr < USB_MAX_DEVICES; addr++) { - if (devices[addr]) - continue; - - di.udi_addr = addr; - if (ioctl(fd, USB_DEVICEINFO, &di) < 0) - continue; - - /* - * XXX If ugen(4) is attached to the USB device - * it will be used. - */ - udevname = NULL; - for (j = 0; j < USB_MAX_DEVNAMES; j++) - if (!strncmp("ugen", di.udi_devnames[j], 4)) { - udevname = strdup(di.udi_devnames[j]); - break; - } - - session_id = (di.udi_bus << 8 | di.udi_addr); - dev = usbi_get_device_by_session_id(ctx, session_id); - - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) { - close(fd); - return (LIBUSB_ERROR_NO_MEM); - } - - dev->bus_number = di.udi_bus; - dev->device_address = di.udi_addr; - dev->speed = di.udi_speed; - - dpriv = (struct device_priv *)dev->os_priv; - dpriv->fd = -1; - dpriv->cdesc = NULL; - dpriv->devname = udevname; - - dd.udd_bus = di.udi_bus; - dd.udd_addr = di.udi_addr; - if (ioctl(fd, USB_DEVICE_GET_DDESC, &dd) < 0) { - libusb_unref_device(dev); - continue; - } - dpriv->ddesc = dd.udd_desc; - - if (_cache_active_config_descriptor(dev)) { - libusb_unref_device(dev); - continue; - } - - if (usbi_sanitize_device(dev)) { - libusb_unref_device(dev); - continue; - } - } - - ddd = discovered_devs_append(*discdevs, dev); - if (ddd == NULL) { - close(fd); - return (LIBUSB_ERROR_NO_MEM); - } - libusb_unref_device(dev); - - *discdevs = ddd; - devices[addr] = 1; - } - - close(fd); - } - - return (LIBUSB_SUCCESS); -} - -int -obsd_open(struct libusb_device_handle *handle) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - char devnode[16]; - - if (dpriv->devname) { - /* - * Only open ugen(4) attached devices read-write, all - * read-only operations are done through the bus node. - */ - snprintf(devnode, sizeof(devnode), DEVPATH "%s.00", - dpriv->devname); - dpriv->fd = open(devnode, O_RDWR); - if (dpriv->fd < 0) - return _errno_to_libusb(errno); - - usbi_dbg("open %s: fd %d", devnode, dpriv->fd); - } - - return (LIBUSB_SUCCESS); -} - -void -obsd_close(struct libusb_device_handle *handle) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - if (dpriv->devname) { - usbi_dbg("close: fd %d", dpriv->fd); - - close(dpriv->fd); - dpriv->fd = -1; - } -} - -int -obsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf, - int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH); - - *host_endian = 0; - - return (LIBUSB_SUCCESS); -} - -int -obsd_get_active_config_descriptor(struct libusb_device *dev, - unsigned char *buf, size_t len, int *host_endian) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; - - len = MIN(len, UGETW(ucd->wTotalLength)); - - usbi_dbg("len %d", len); - - memcpy(buf, dpriv->cdesc, len); - - *host_endian = 0; - - return (len); -} - -int -obsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx, - unsigned char *buf, size_t len, int *host_endian) -{ - struct usb_device_fdesc udf; - int fd, err; - - if ((fd = _bus_open(dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - udf.udf_bus = dev->bus_number; - udf.udf_addr = dev->device_address; - udf.udf_config_index = idx; - udf.udf_size = len; - udf.udf_data = buf; - - usbi_dbg("index %d, len %d", udf.udf_config_index, len); - - if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(err); - } - close(fd); - - *host_endian = 0; - - return (len); -} - -int -obsd_get_configuration(struct libusb_device_handle *handle, int *config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - usb_config_descriptor_t *ucd = (usb_config_descriptor_t *)dpriv->cdesc; - - *config = ucd->bConfigurationValue; - - usbi_dbg("bConfigurationValue %d", *config); - - return (LIBUSB_SUCCESS); -} - -int -obsd_set_configuration(struct libusb_device_handle *handle, int config) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - - if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - usbi_dbg("bConfigurationValue %d", config); - - if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0) - return _errno_to_libusb(errno); - - return _cache_active_config_descriptor(handle->dev); -} - -int -obsd_claim_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - hpriv->endpoints[i] = -1; - - return (LIBUSB_SUCCESS); -} - -int -obsd_release_interface(struct libusb_device_handle *handle, int iface) -{ - struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; - int i; - - for (i = 0; i < USB_MAX_ENDPOINTS; i++) - if (hpriv->endpoints[i] >= 0) - close(hpriv->endpoints[i]); - - return (LIBUSB_SUCCESS); -} - -int -obsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; - struct usb_alt_interface intf; - - if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - usbi_dbg("iface %d, setting %d", iface, altsetting); - - memset(&intf, 0, sizeof(intf)); - - intf.uai_interface_index = iface; - intf.uai_alt_no = altsetting; - - if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0) - return _errno_to_libusb(errno); - - return (LIBUSB_SUCCESS); -} - -int -obsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint) -{ - struct usb_ctl_request req; - int fd, err; - - if ((fd = _bus_open(handle->dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - usbi_dbg(""); - - req.ucr_addr = handle->dev->device_address; - req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT; - req.ucr_request.bRequest = UR_CLEAR_FEATURE; - USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT); - USETW(req.ucr_request.wIndex, endpoint); - USETW(req.ucr_request.wLength, 0); - - if (ioctl(fd, USB_REQUEST, &req) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(err); - } - close(fd); - - return (LIBUSB_SUCCESS); -} - -int -obsd_reset_device(struct libusb_device_handle *handle) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -obsd_destroy_device(struct libusb_device *dev) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - - usbi_dbg(""); - - free(dpriv->cdesc); - free(dpriv->devname); -} - -int -obsd_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct handle_priv *hpriv; - int err = 0; - - usbi_dbg(""); - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - err = _sync_control_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - if (IS_XFEROUT(transfer)) { - /* Isochronous write is not supported */ - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && - transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - err = _sync_gen_transfer(itransfer); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - if (err) - return (err); - - usbi_signal_transfer_completion(itransfer); - - return (LIBUSB_SUCCESS); -} - -int -obsd_cancel_transfer(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -obsd_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - /* Nothing to do */ -} - -int -obsd_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); -} - -int -obsd_clock_gettime(int clkid, struct timespec *tp) -{ - usbi_dbg("clock %d", clkid); - - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -int -_errno_to_libusb(int err) -{ - usbi_dbg("error: %s (%d)", strerror(err), err); - - switch (err) { - case EIO: - return (LIBUSB_ERROR_IO); - case EACCES: - return (LIBUSB_ERROR_ACCESS); - case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); - case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); - case ETIMEDOUT: - return (LIBUSB_ERROR_TIMEOUT); - } - - return (LIBUSB_ERROR_OTHER); -} - -int -_cache_active_config_descriptor(struct libusb_device *dev) -{ - struct device_priv *dpriv = (struct device_priv *)dev->os_priv; - struct usb_device_cdesc udc; - struct usb_device_fdesc udf; - unsigned char* buf; - int fd, len, err; - - if ((fd = _bus_open(dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - usbi_dbg("fd %d, addr %d", fd, dev->device_address); - - udc.udc_bus = dev->bus_number; - udc.udc_addr = dev->device_address; - udc.udc_config_index = USB_CURRENT_CONFIG_INDEX; - if (ioctl(fd, USB_DEVICE_GET_CDESC, &udc) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(errno); - } - - usbi_dbg("active bLength %d", udc.udc_desc.bLength); - - len = UGETW(udc.udc_desc.wTotalLength); - buf = malloc(len); - if (buf == NULL) - return (LIBUSB_ERROR_NO_MEM); - - udf.udf_bus = dev->bus_number; - udf.udf_addr = dev->device_address; - udf.udf_config_index = udc.udc_config_index; - udf.udf_size = len; - udf.udf_data = buf; - - usbi_dbg("index %d, len %d", udf.udf_config_index, len); - - if (ioctl(fd, USB_DEVICE_GET_FDESC, &udf) < 0) { - err = errno; - close(fd); - free(buf); - return _errno_to_libusb(err); - } - close(fd); - - if (dpriv->cdesc) - free(dpriv->cdesc); - dpriv->cdesc = buf; - - return (LIBUSB_SUCCESS); -} - -int -_sync_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct libusb_control_setup *setup; - struct device_priv *dpriv; - struct usb_ctl_request req; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - setup = (struct libusb_control_setup *)transfer->buffer; - - usbi_dbg("type %x request %x value %x index %d length %d timeout %d", - setup->bmRequestType, setup->bRequest, - libusb_le16_to_cpu(setup->wValue), - libusb_le16_to_cpu(setup->wIndex), - libusb_le16_to_cpu(setup->wLength), transfer->timeout); - - req.ucr_addr = transfer->dev_handle->dev->device_address; - req.ucr_request.bmRequestType = setup->bmRequestType; - req.ucr_request.bRequest = setup->bRequest; - /* Don't use USETW, libusb already deals with the endianness */ - (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; - (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; - (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; - req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; - - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - req.ucr_flags = USBD_SHORT_XFER_OK; - - if (dpriv->devname == NULL) { - /* - * XXX If the device is not attached to ugen(4) it is - * XXX still possible to submit a control transfer but - * XXX with the default timeout only. - */ - int fd, err; - - if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(fd, USB_REQUEST, &req)) < 0) { - err = errno; - close(fd); - return _errno_to_libusb(err); - } - close(fd); - } else { - if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) - return _errno_to_libusb(errno); - } - - itransfer->transferred = req.ucr_actlen; - - usbi_dbg("transferred %d", itransfer->transferred); - - return (0); -} - -int -_access_endpoint(struct libusb_transfer *transfer) -{ - struct handle_priv *hpriv; - struct device_priv *dpriv; - char devnode[16]; - int fd, endpt; - mode_t mode; - - hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - - endpt = UE_GET_ADDR(transfer->endpoint); - mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY; - - usbi_dbg("endpoint %d mode %d", endpt, mode); - - if (hpriv->endpoints[endpt] < 0) { - /* Pick the right endpoint node */ - snprintf(devnode, sizeof(devnode), DEVPATH "%s.%02d", - dpriv->devname, endpt); - - /* We may need to read/write to the same endpoint later. */ - if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO)) - if ((fd = open(devnode, mode)) < 0) - return (-1); - - hpriv->endpoints[endpt] = fd; - } - - return (hpriv->endpoints[endpt]); -} - -int -_sync_gen_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct device_priv *dpriv; - int fd, nr = 1; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; - - if (dpriv->devname == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - /* - * Bulk, Interrupt or Isochronous transfer depends on the - * endpoint and thus the node to open. - */ - if ((fd = _access_endpoint(transfer)) < 0) - return _errno_to_libusb(errno); - - if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) - return _errno_to_libusb(errno); - - if (IS_XFERIN(transfer)) { - if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) - if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) - return _errno_to_libusb(errno); - - nr = read(fd, transfer->buffer, transfer->length); - } else { - nr = write(fd, transfer->buffer, transfer->length); - } - - if (nr < 0) - return _errno_to_libusb(errno); - - itransfer->transferred = nr; - - return (0); -} - -int -_bus_open(int number) -{ - char busnode[16]; - - snprintf(busnode, sizeof(busnode), USBDEV "%d", number); - - return open(busnode, O_RDWR); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_posix.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_posix.c deleted file mode 100644 index e2f55a57a14..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_posix.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * poll_posix: poll compatibility wrapper for POSIX systems - * Copyright © 2013 RealVNC Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -#include -#include -#include -#include - -#include "libusbi.h" - -int usbi_pipe(int pipefd[2]) -{ - int ret = pipe(pipefd); - if (ret != 0) { - return ret; - } - ret = fcntl(pipefd[1], F_GETFL); - if (ret == -1) { - usbi_dbg("Failed to get pipe fd flags: %d", errno); - goto err_close_pipe; - } - ret = fcntl(pipefd[1], F_SETFL, ret | O_NONBLOCK); - if (ret != 0) { - usbi_dbg("Failed to set non-blocking on new pipe: %d", errno); - goto err_close_pipe; - } - - return 0; - -err_close_pipe: - usbi_close(pipefd[0]); - usbi_close(pipefd[1]); - return ret; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_posix.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_posix.h deleted file mode 100644 index 5b4b2c905e7..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_posix.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef LIBUSB_POLL_POSIX_H -#define LIBUSB_POLL_POSIX_H - -#define usbi_write write -#define usbi_read read -#define usbi_close close -#define usbi_poll poll - -int usbi_pipe(int pipefd[2]); - -#endif /* LIBUSB_POLL_POSIX_H */ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_windows.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_windows.c deleted file mode 100644 index 98256075121..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_windows.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * poll_windows: poll compatibility wrapper for Windows - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* - * poll() and pipe() Windows compatibility layer for libusb 1.0 - * - * The way this layer works is by using OVERLAPPED with async I/O transfers, as - * OVERLAPPED have an associated event which is flagged for I/O completion. - * - * For USB pollable async I/O, you would typically: - * - obtain a Windows HANDLE to a file or device that has been opened in - * OVERLAPPED mode - * - call usbi_create_fd with this handle to obtain a custom fd. - * Note that if you need simultaneous R/W access, you need to call create_fd - * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate - * pollable fds - * - leave the core functions call the poll routine and flag POLLIN/POLLOUT - * - * The pipe pollable synchronous I/O works using the overlapped event associated - * with a fake pipe. The read/write functions are only meant to be used in that - * context. - */ -#include - -#include -#include -#include - -#include "libusbi.h" - -// Uncomment to debug the polling layer -//#define DEBUG_POLL_WINDOWS -#if defined(DEBUG_POLL_WINDOWS) -#define poll_dbg usbi_dbg -#else -// MSVC++ < 2005 cannot use a variadic argument and non MSVC -// compilers produce warnings if parenthesis are omitted. -#if defined(_MSC_VER) && (_MSC_VER < 1400) -#define poll_dbg -#else -#define poll_dbg(...) -#endif -#endif - -#if defined(_PREFAST_) -#pragma warning(disable:28719) -#endif - -#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) - -// public fd data -const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE}; -struct winfd poll_fd[MAX_FDS]; -// internal fd data -struct { - CRITICAL_SECTION mutex; // lock for fds - // Additional variables for XP CancelIoEx partial emulation - HANDLE original_handle; - DWORD thread_id; -} _poll_fd[MAX_FDS]; - -// globals -BOOLEAN is_polling_set = FALSE; -LONG pipe_number = 0; -static volatile LONG compat_spinlock = 0; - -#if !defined(_WIN32_WCE) -// CancelIoEx, available on Vista and later only, provides the ability to cancel -// a single transfer (OVERLAPPED) when used. As it may not be part of any of the -// platform headers, we hook into the Kernel32 system DLL directly to seek it. -static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; -#define Use_Duplicate_Handles (pCancelIoEx == NULL) - -static inline void setup_cancel_io(void) -{ - HMODULE hKernel32 = GetModuleHandleA("KERNEL32"); - if (hKernel32 != NULL) { - pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) - GetProcAddress(hKernel32, "CancelIoEx"); - } - usbi_dbg("Will use CancelIo%s for I/O cancellation", - Use_Duplicate_Handles?"":"Ex"); -} - -static inline BOOL cancel_io(int _index) -{ - if ((_index < 0) || (_index >= MAX_FDS)) { - return FALSE; - } - - if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { - return TRUE; - } - if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { - // Cancel outstanding transfer via the specific callback - (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); - return TRUE; - } - if (pCancelIoEx != NULL) { - return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped); - } - if (_poll_fd[_index].thread_id == GetCurrentThreadId()) { - return CancelIo(poll_fd[_index].handle); - } - usbi_warn(NULL, "Unable to cancel I/O that was started from another thread"); - return FALSE; -} -#else -#define Use_Duplicate_Handles FALSE - -static __inline void setup_cancel_io() -{ - // No setup needed on WinCE -} - -static __inline BOOL cancel_io(int _index) -{ - if ((_index < 0) || (_index >= MAX_FDS)) { - return FALSE; - } - if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) - || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { - return TRUE; - } - if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { - // Cancel outstanding transfer via the specific callback - (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); - } - return TRUE; -} -#endif - -// Init -void init_polling(void) -{ - int i; - - while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { - SleepEx(0, TRUE); - } - if (!is_polling_set) { - setup_cancel_io(); - for (i=0; ihEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if(overlapped->hEvent == NULL) { - free (overlapped); - return NULL; - } - return overlapped; -} - -static void free_overlapped(OVERLAPPED *overlapped) -{ - if (overlapped == NULL) - return; - - if ( (overlapped->hEvent != 0) - && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) { - CloseHandle(overlapped->hEvent); - } - free(overlapped); -} - -void exit_polling(void) -{ - int i; - - while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { - SleepEx(0, TRUE); - } - if (is_polling_set) { - is_polling_set = FALSE; - - for (i=0; iInternal = STATUS_PENDING; - overlapped->InternalHigh = 0; - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[i].mutex); - continue; - } - - // Use index as the unique fd number - poll_fd[i].fd = i; - // Read end of the "pipe" - filedes[0] = poll_fd[i].fd; - // We can use the same handle for both ends - filedes[1] = filedes[0]; - - poll_fd[i].handle = DUMMY_HANDLE; - poll_fd[i].overlapped = overlapped; - // There's no polling on the write end, so we just use READ for our needs - poll_fd[i].rw = RW_READ; - _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; - LeaveCriticalSection(&_poll_fd[i].mutex); - return 0; - } - } - free_overlapped(overlapped); - return -1; -} - -/* - * Create both an fd and an OVERLAPPED from an open Windows handle, so that - * it can be used with our polling function - * The handle MUST support overlapped transfers (usually requires CreateFile - * with FILE_FLAG_OVERLAPPED) - * Return a pollable file descriptor struct, or INVALID_WINFD on error - * - * Note that the fd returned by this function is a per-transfer fd, rather - * than a per-session fd and cannot be used for anything else but our - * custom functions (the fd itself points to the NUL: device) - * if you plan to do R/W on the same handle, you MUST create 2 fds: one for - * read and one for write. Using a single R/W fd is unsupported and will - * produce unexpected results - */ -struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn) -{ - int i; - struct winfd wfd = INVALID_WINFD; - OVERLAPPED* overlapped = NULL; - - CHECK_INIT_POLLING; - - if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) { - return INVALID_WINFD; - } - - wfd.itransfer = itransfer; - wfd.cancel_fn = cancel_fn; - - if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) { - usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. " - "If you want to poll for R/W simultaneously, create multiple fds from the same handle."); - return INVALID_WINFD; - } - if (access_mode == RW_READ) { - wfd.rw = RW_READ; - } else { - wfd.rw = RW_WRITE; - } - - overlapped = create_overlapped(); - if(overlapped == NULL) { - return INVALID_WINFD; - } - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[i].mutex); - continue; - } - // Use index as the unique fd number - wfd.fd = i; - // Attempt to emulate some of the CancelIoEx behaviour on platforms - // that don't have it - if (Use_Duplicate_Handles) { - _poll_fd[i].thread_id = GetCurrentThreadId(); - if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), - &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - usbi_dbg("could not duplicate handle for CancelIo - using original one"); - wfd.handle = handle; - // Make sure we won't close the original handle on fd deletion then - _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; - } else { - _poll_fd[i].original_handle = handle; - } - } else { - wfd.handle = handle; - } - wfd.overlapped = overlapped; - memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); - LeaveCriticalSection(&_poll_fd[i].mutex); - return wfd; - } - } - free_overlapped(overlapped); - return INVALID_WINFD; -} - -static void _free_index(int _index) -{ - // Cancel any async IO (Don't care about the validity of our handles for this) - cancel_io(_index); - // close the duplicate handle (if we have an actual duplicate) - if (Use_Duplicate_Handles) { - if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) { - CloseHandle(poll_fd[_index].handle); - } - _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE; - _poll_fd[_index].thread_id = 0; - } - free_overlapped(poll_fd[_index].overlapped); - poll_fd[_index] = INVALID_WINFD; -} - -/* - * Release a pollable file descriptor. - * - * Note that the associated Windows handle is not closed by this call - */ -void usbi_free_fd(struct winfd *wfd) -{ - int _index; - - CHECK_INIT_POLLING; - - _index = _fd_to_index_and_lock(wfd->fd); - if (_index < 0) { - return; - } - _free_index(_index); - *wfd = INVALID_WINFD; - LeaveCriticalSection(&_poll_fd[_index].mutex); -} - -/* - * The functions below perform various conversions between fd, handle and OVERLAPPED - */ -struct winfd fd_to_winfd(int fd) -{ - int i; - struct winfd wfd; - - CHECK_INIT_POLLING; - - if (fd < 0) - return INVALID_WINFD; - - for (i=0; i= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - usbi_warn(NULL, "invalid fd"); - triggered = -1; - goto poll_exit; - } - - // IN or OUT must match our fd direction - if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - usbi_warn(NULL, "attempted POLLIN on fd without READ access"); - LeaveCriticalSection(&_poll_fd[_index].mutex); - triggered = -1; - goto poll_exit; - } - - if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) { - fds[i].revents |= POLLNVAL | POLLERR; - errno = EBADF; - usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access"); - LeaveCriticalSection(&_poll_fd[_index].mutex); - triggered = -1; - goto poll_exit; - } - - // The following macro only works if overlapped I/O was reported pending - if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped)) - || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) { - poll_dbg(" completed"); - // checks above should ensure this works: - fds[i].revents = fds[i].events; - triggered++; - } else { - handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent; - handle_to_index[nb_handles_to_wait_on] = i; - nb_handles_to_wait_on++; - } - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - - // If nothing was triggered, wait on all fds that require it - if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) { - if (timeout < 0) { - poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on); - } else { - poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on); - } - ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, - FALSE, (timeout<0)?INFINITE:(DWORD)timeout); - object_index = ret-WAIT_OBJECT_0; - if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) { - poll_dbg(" completed after wait"); - i = handle_to_index[object_index]; - _index = _fd_to_index_and_lock(fds[i].fd); - fds[i].revents = fds[i].events; - triggered++; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - } else if (ret == WAIT_TIMEOUT) { - poll_dbg(" timed out"); - triggered = 0; // 0 = timeout - } else { - errno = EIO; - triggered = -1; // error - } - } - -poll_exit: - if (handles_to_wait_on != NULL) { - free(handles_to_wait_on); - } - if (handle_to_index != NULL) { - free(handle_to_index); - } - return triggered; -} - -/* - * close a fake pipe fd - */ -int usbi_close(int fd) -{ - int _index; - int r = -1; - - CHECK_INIT_POLLING; - - _index = _fd_to_index_and_lock(fd); - - if (_index < 0) { - errno = EBADF; - } else { - free_overlapped(poll_fd[_index].overlapped); - poll_fd[_index] = INVALID_WINFD; - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - return r; -} - -/* - * synchronous write for fake "pipe" signaling - */ -ssize_t usbi_write(int fd, const void *buf, size_t count) -{ - int _index; - UNUSED(buf); - - CHECK_INIT_POLLING; - - if (count != sizeof(unsigned char)) { - usbi_err(NULL, "this function should only used for signaling"); - return -1; - } - - _index = _fd_to_index_and_lock(fd); - - if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) { - errno = EBADF; - if (_index >= 0) { - LeaveCriticalSection(&_poll_fd[_index].mutex); - } - return -1; - } - - poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); - SetEvent(poll_fd[_index].overlapped->hEvent); - poll_fd[_index].overlapped->Internal = STATUS_WAIT_0; - // If two threads write on the pipe at the same time, we need to - // process two separate reads => use the overlapped as a counter - poll_fd[_index].overlapped->InternalHigh++; - - LeaveCriticalSection(&_poll_fd[_index].mutex); - return sizeof(unsigned char); -} - -/* - * synchronous read for fake "pipe" signaling - */ -ssize_t usbi_read(int fd, void *buf, size_t count) -{ - int _index; - ssize_t r = -1; - UNUSED(buf); - - CHECK_INIT_POLLING; - - if (count != sizeof(unsigned char)) { - usbi_err(NULL, "this function should only used for signaling"); - return -1; - } - - _index = _fd_to_index_and_lock(fd); - - if (_index < 0) { - errno = EBADF; - return -1; - } - - if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { - usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError()); - errno = EIO; - goto out; - } - - poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); - poll_fd[_index].overlapped->InternalHigh--; - // Don't reset unless we don't have any more events to process - if (poll_fd[_index].overlapped->InternalHigh <= 0) { - ResetEvent(poll_fd[_index].overlapped->hEvent); - poll_fd[_index].overlapped->Internal = STATUS_PENDING; - } - - r = sizeof(unsigned char); - -out: - LeaveCriticalSection(&_poll_fd[_index].mutex); - return r; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_windows.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_windows.h deleted file mode 100644 index aa4c985daec..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/poll_windows.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Windows compat: POSIX compatibility wrapper - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ -#pragma once - -#if defined(_MSC_VER) -// disable /W4 MSVC warnings that are benign -#pragma warning(disable:4127) // conditional expression is constant -#endif - -// Handle synchronous completion through the overlapped structure -#if !defined(STATUS_REPARSE) // reuse the REPARSE status code -#define STATUS_REPARSE ((LONG)0x00000104L) -#endif -#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE -#if defined(_WIN32_WCE) -// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it -#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING) -#endif -#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY) - -#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) - -/* Windows versions */ -enum windows_version { - WINDOWS_CE = -2, - WINDOWS_UNDEFINED = -1, - WINDOWS_UNSUPPORTED = 0, - WINDOWS_XP = 0x51, - WINDOWS_2003 = 0x52, // Also XP x64 - WINDOWS_VISTA = 0x60, - WINDOWS_7 = 0x61, - WINDOWS_8 = 0x62, - WINDOWS_8_1_OR_LATER = 0x63, - WINDOWS_MAX -}; -extern int windows_version; - -#define MAX_FDS 256 - -#define POLLIN 0x0001 /* There is data to read */ -#define POLLPRI 0x0002 /* There is urgent data to read */ -#define POLLOUT 0x0004 /* Writing now will not block */ -#define POLLERR 0x0008 /* Error condition */ -#define POLLHUP 0x0010 /* Hung up */ -#define POLLNVAL 0x0020 /* Invalid request: fd not open */ - -struct pollfd { - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ -}; - -// access modes -enum rw_type { - RW_NONE, - RW_READ, - RW_WRITE, -}; - -// fd struct that can be used for polling on Windows -typedef int cancel_transfer(struct usbi_transfer *itransfer); - -struct winfd { - int fd; // what's exposed to libusb core - HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it - OVERLAPPED* overlapped; // what will report our I/O status - struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed - cancel_transfer *cancel_fn; // Function pointer to cancel transfer API - enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH) -}; -extern const struct winfd INVALID_WINFD; - -int usbi_pipe(int pipefd[2]); -int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); -ssize_t usbi_write(int fd, const void *buf, size_t count); -ssize_t usbi_read(int fd, void *buf, size_t count); -int usbi_close(int fd); - -void init_polling(void); -void exit_polling(void); -struct winfd usbi_create_fd(HANDLE handle, int access_mode, - struct usbi_transfer *transfer, cancel_transfer *cancel_fn); -void usbi_free_fd(struct winfd* winfd); -struct winfd fd_to_winfd(int fd); -struct winfd handle_to_winfd(HANDLE handle); -struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); - -/* - * Timeval operations - */ -#if defined(DDKBUILD) -#include // defines timeval functions on DDK -#endif - -#if !defined(TIMESPEC_TO_TIMEVAL) -#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ - (tv)->tv_sec = (long)(ts)->tv_sec; \ - (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \ -} -#endif -#if !defined(timersub) -#define timersub(a, b, result) \ -do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ -} while (0) -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/sunos_usb.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/sunos_usb.c deleted file mode 100644 index cb608976b64..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/sunos_usb.c +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * - * Copyright (c) 2016, Oracle and/or its affiliates. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "sunos_usb.h" - -/* - * Backend functions - */ -static int sunos_init(struct libusb_context *); -static void sunos_exit(void); -static int sunos_get_device_list(struct libusb_context *, - struct discovered_devs **); -static int sunos_open(struct libusb_device_handle *); -static void sunos_close(struct libusb_device_handle *); -static int sunos_get_device_descriptor(struct libusb_device *, - uint8_t*, int *); -static int sunos_get_active_config_descriptor(struct libusb_device *, - uint8_t*, size_t, int *); -static int sunos_get_config_descriptor(struct libusb_device *, uint8_t, - uint8_t*, size_t, int *); -static int sunos_get_configuration(struct libusb_device_handle *, int *); -static int sunos_set_configuration(struct libusb_device_handle *, int); -static int sunos_claim_interface(struct libusb_device_handle *, int); -static int sunos_release_interface(struct libusb_device_handle *, int); -static int sunos_set_interface_altsetting(struct libusb_device_handle *, - int, int); -static int sunos_clear_halt(struct libusb_device_handle *, uint8_t); -static int sunos_reset_device(struct libusb_device_handle *); -static void sunos_destroy_device(struct libusb_device *); -static int sunos_submit_transfer(struct usbi_transfer *); -static int sunos_cancel_transfer(struct usbi_transfer *); -static void sunos_clear_transfer_priv(struct usbi_transfer *); -static int sunos_handle_transfer_completion(struct usbi_transfer *); -static int sunos_clock_gettime(int, struct timespec *); - -/* - * Private functions - */ -static int _errno_to_libusb(int); -static int sunos_usb_get_status(int fd); - -static int sunos_init(struct libusb_context *ctx) -{ - return (LIBUSB_SUCCESS); -} - -static void sunos_exit(void) -{ - usbi_dbg(""); -} - -static int -sunos_fill_in_dev_info(di_node_t node, struct libusb_device *dev) -{ - int proplen; - int n, *addr, *port_prop; - char *phypath; - uint8_t *rdata; - struct libusb_device_descriptor *descr; - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - - /* Device descriptors */ - proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, - "usb-dev-descriptor", &rdata); - if (proplen <= 0) { - - return (LIBUSB_ERROR_IO); - } - - descr = (struct libusb_device_descriptor *)rdata; - bcopy(descr, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); - dpriv->dev_descr.bcdUSB = libusb_cpu_to_le16(descr->bcdUSB); - dpriv->dev_descr.idVendor = libusb_cpu_to_le16(descr->idVendor); - dpriv->dev_descr.idProduct = libusb_cpu_to_le16(descr->idProduct); - dpriv->dev_descr.bcdDevice = libusb_cpu_to_le16(descr->bcdDevice); - - /* Raw configuration descriptors */ - proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, - "usb-raw-cfg-descriptors", &rdata); - if (proplen <= 0) { - usbi_dbg("can't find raw config descriptors"); - - return (LIBUSB_ERROR_IO); - } - dpriv->raw_cfgdescr = calloc(1, proplen); - if (dpriv->raw_cfgdescr == NULL) { - return (LIBUSB_ERROR_NO_MEM); - } else { - bcopy(rdata, dpriv->raw_cfgdescr, proplen); - dpriv->cfgvalue = ((struct libusb_config_descriptor *) - rdata)->bConfigurationValue; - } - - n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", &port_prop); - - if ((n != 1) || (*port_prop <= 0)) { - return (LIBUSB_ERROR_IO); - } - dev->port_number = *port_prop; - - /* device physical path */ - phypath = di_devfs_path(node); - if (phypath) { - dpriv->phypath = strdup(phypath); - di_devfs_path_free(phypath); - } else { - free(dpriv->raw_cfgdescr); - - return (LIBUSB_ERROR_IO); - } - - /* address */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "assigned-address", &addr); - if (n != 1 || *addr == 0) { - usbi_dbg("can't get address"); - } else { - dev->device_address = *addr; - } - - /* speed */ - if (di_prop_exists(DDI_DEV_T_ANY, node, "low-speed") == 1) { - dev->speed = LIBUSB_SPEED_LOW; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "high-speed") == 1) { - dev->speed = LIBUSB_SPEED_HIGH; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "full-speed") == 1) { - dev->speed = LIBUSB_SPEED_FULL; - } else if (di_prop_exists(DDI_DEV_T_ANY, node, "super-speed") == 1) { - dev->speed = LIBUSB_SPEED_SUPER; - } - - usbi_dbg("vid=%x pid=%x, path=%s, bus_nmber=0x%x, port_number=%d, " - "speed=%d", dpriv->dev_descr.idVendor, dpriv->dev_descr.idProduct, - dpriv->phypath, dev->bus_number, dev->port_number, dev->speed); - - return (LIBUSB_SUCCESS); -} - - -static int -sunos_add_devices(di_devlink_t link, void *arg) -{ - struct devlink_cbarg *largs = (struct devlink_cbarg *)arg; - struct node_args *nargs; - di_node_t myself, pnode; - uint64_t session_id = 0; - uint16_t bdf = 0; - struct libusb_device *dev; - sunos_dev_priv_t *devpriv; - const char *path, *newpath; - int n, i; - int *addr_prop; - uint8_t bus_number = 0; - - nargs = (struct node_args *)largs->nargs; - myself = largs->myself; - if (nargs->last_ugenpath) { - /* the same node's links */ - return (DI_WALK_CONTINUE); - } - - /* - * Construct session ID. - * session ID = ...parent hub addr|hub addr|dev addr. - */ - pnode = myself; - i = 0; - while (pnode != DI_NODE_NIL) { - if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) { - /* walk to root */ - uint32_t *regbuf = NULL; - uint32_t reg; - - n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg", - (int **)®buf); - reg = regbuf[0]; - bdf = (PCI_REG_BUS_G(reg) << 8) | - (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - session_id |= (bdf << i * 8); - - /* same as 'unit-address' property */ - bus_number = - (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg); - - usbi_dbg("device bus address=%s:%x", - di_bus_addr(pnode), bus_number); - - break; - } - - /* usb_addr */ - n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, - "assigned-address", &addr_prop); - if ((n != 1) || (addr_prop[0] == 0)) { - usbi_dbg("cannot get valid usb_addr"); - - return (DI_WALK_CONTINUE); - } - - session_id |= ((addr_prop[0] & 0xff) << i * 8); - if (++i > 7) - break; - - pnode = di_parent_node(pnode); - } - - path = di_devlink_path(link); - dev = usbi_get_device_by_session_id(nargs->ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(nargs->ctx, session_id); - if (dev == NULL) { - usbi_dbg("can't alloc device"); - - return (DI_WALK_TERMINATE); - } - devpriv = (sunos_dev_priv_t *)dev->os_priv; - if ((newpath = strrchr(path, '/')) == NULL) { - libusb_unref_device(dev); - - return (DI_WALK_TERMINATE); - } - devpriv->ugenpath = strndup(path, strlen(path) - - strlen(newpath)); - dev->bus_number = bus_number; - - if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - - return (DI_WALK_TERMINATE); - } - if (usbi_sanitize_device(dev) < 0) { - libusb_unref_device(dev); - usbi_dbg("sanatize failed: "); - return (DI_WALK_TERMINATE); - } - } else { - usbi_dbg("Dev %s exists", path); - } - - devpriv = (sunos_dev_priv_t *)dev->os_priv; - if (nargs->last_ugenpath == NULL) { - /* first device */ - nargs->last_ugenpath = devpriv->ugenpath; - - if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) { - usbi_dbg("cannot append device"); - } - - /* - * we alloc and hence ref this dev. We don't need to ref it - * hereafter. Front end or app should take care of their ref. - */ - libusb_unref_device(dev); - } - - usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x", - devpriv->ugenpath, path, (uint64_t)session_id, - (*nargs->discdevs)->len, bdf); - - return (DI_WALK_CONTINUE); -} - -static int -sunos_walk_minor_node_link(di_node_t node, void *args) -{ - di_minor_t minor = DI_MINOR_NIL; - char *minor_path; - struct devlink_cbarg arg; - struct node_args *nargs = (struct node_args *)args; - di_devlink_handle_t devlink_hdl = nargs->dlink_hdl; - - /* walk each minor to find ugen devices */ - while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { - minor_path = di_devfs_minor_path(minor); - arg.nargs = args; - arg.myself = node; - arg.minor = minor; - (void) di_devlink_walk(devlink_hdl, - "^usb/[0-9a-f]+[.][0-9a-f]+", minor_path, - DI_PRIMARY_LINK, (void *)&arg, sunos_add_devices); - di_devfs_path_free(minor_path); - } - - /* switch to a different node */ - nargs->last_ugenpath = NULL; - - return (DI_WALK_CONTINUE); -} - -int -sunos_get_device_list(struct libusb_context * ctx, - struct discovered_devs **discdevs) -{ - di_node_t root_node; - struct node_args args; - di_devlink_handle_t devlink_hdl; - - args.ctx = ctx; - args.discdevs = discdevs; - args.last_ugenpath = NULL; - if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { - usbi_dbg("di_int() failed: %s", strerror(errno)); - return (LIBUSB_ERROR_IO); - } - - if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { - di_fini(root_node); - usbi_dbg("di_devlink_init() failed: %s", strerror(errno)); - - return (LIBUSB_ERROR_IO); - } - args.dlink_hdl = devlink_hdl; - - /* walk each node to find USB devices */ - if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args, - sunos_walk_minor_node_link) == -1) { - usbi_dbg("di_walk_node() failed: %s", strerror(errno)); - di_fini(root_node); - - return (LIBUSB_ERROR_IO); - } - - di_fini(root_node); - di_devlink_fini(&devlink_hdl); - - usbi_dbg("%d devices", (*discdevs)->len); - - return ((*discdevs)->len); -} - -static int -sunos_usb_open_ep0(sunos_dev_handle_priv_t *hpriv, sunos_dev_priv_t *dpriv) -{ - char filename[PATH_MAX + 1]; - - if (hpriv->eps[0].datafd > 0) { - - return (LIBUSB_SUCCESS); - } - snprintf(filename, PATH_MAX, "%s/cntrl0", dpriv->ugenpath); - - usbi_dbg("opening %s", filename); - hpriv->eps[0].datafd = open(filename, O_RDWR); - if (hpriv->eps[0].datafd < 0) { - return(_errno_to_libusb(errno)); - } - - snprintf(filename, PATH_MAX, "%s/cntrl0stat", dpriv->ugenpath); - hpriv->eps[0].statfd = open(filename, O_RDONLY); - if (hpriv->eps[0].statfd < 0) { - close(hpriv->eps[0].datafd); - hpriv->eps[0].datafd = -1; - - return(_errno_to_libusb(errno)); - } - - return (LIBUSB_SUCCESS); -} - -static void -sunos_usb_close_all_eps(sunos_dev_handle_priv_t *hdev) -{ - int i; - - /* not close ep0 */ - for (i = 1; i < USB_MAXENDPOINTS; i++) { - if (hdev->eps[i].datafd != -1) { - (void) close(hdev->eps[i].datafd); - hdev->eps[i].datafd = -1; - } - if (hdev->eps[i].statfd != -1) { - (void) close(hdev->eps[i].statfd); - hdev->eps[i].statfd = -1; - } - } -} - -static void -sunos_usb_close_ep0(sunos_dev_handle_priv_t *hdev, sunos_dev_priv_t *dpriv) -{ - if (hdev->eps[0].datafd >= 0) { - close(hdev->eps[0].datafd); - close(hdev->eps[0].statfd); - hdev->eps[0].datafd = -1; - hdev->eps[0].statfd = -1; - } -} - -static uchar_t -sunos_usb_ep_index(uint8_t ep_addr) -{ - return ((ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK) + - ((ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? 16 : 0)); -} - -static int -sunos_find_interface(struct libusb_device_handle *hdev, - uint8_t endpoint, uint8_t *interface) -{ - struct libusb_config_descriptor *config; - int r; - int iface_idx; - - r = libusb_get_active_config_descriptor(hdev->dev, &config); - if (r < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - - for (iface_idx = 0; iface_idx < config->bNumInterfaces; iface_idx++) { - const struct libusb_interface *iface = - &config->interface[iface_idx]; - int altsetting_idx; - - for (altsetting_idx = 0; altsetting_idx < iface->num_altsetting; - altsetting_idx++) { - const struct libusb_interface_descriptor *altsetting = - &iface->altsetting[altsetting_idx]; - int ep_idx; - - for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; - ep_idx++) { - const struct libusb_endpoint_descriptor *ep = - &altsetting->endpoint[ep_idx]; - if (ep->bEndpointAddress == endpoint) { - *interface = iface_idx; - libusb_free_config_descriptor(config); - - return (LIBUSB_SUCCESS); - } - } - } - } - libusb_free_config_descriptor(config); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -static int -sunos_check_device_and_status_open(struct libusb_device_handle *hdl, - uint8_t ep_addr, int ep_type) -{ - char filename[PATH_MAX + 1], statfilename[PATH_MAX + 1]; - char cfg_num[16], alt_num[16]; - int fd, fdstat, mode; - uint8_t ifc = 0; - uint8_t ep_index; - sunos_dev_handle_priv_t *hpriv; - - usbi_dbg("open ep 0x%02x", ep_addr); - hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; - ep_index = sunos_usb_ep_index(ep_addr); - /* ep already opened */ - if ((hpriv->eps[ep_index].datafd > 0) && - (hpriv->eps[ep_index].statfd > 0)) { - usbi_dbg("ep 0x%02x already opened, return success", - ep_addr); - - return (0); - } - - if (sunos_find_interface(hdl, ep_addr, &ifc) < 0) { - usbi_dbg("can't find interface for endpoint 0x%02x", - ep_addr); - - return (LIBUSB_ERROR_ACCESS); - } - - /* create filename */ - if (hpriv->config_index > 0) { - (void) snprintf(cfg_num, sizeof (cfg_num), "cfg%d", - hpriv->config_index + 1); - } else { - bzero(cfg_num, sizeof (cfg_num)); - } - - if (hpriv->altsetting[ifc] > 0) { - (void) snprintf(alt_num, sizeof (alt_num), ".%d", - hpriv->altsetting[ifc]); - } else { - bzero(alt_num, sizeof (alt_num)); - } - - (void) snprintf(filename, PATH_MAX, "%s/%sif%d%s%s%d", - hpriv->dpriv->ugenpath, cfg_num, ifc, alt_num, - (ep_addr & LIBUSB_ENDPOINT_DIR_MASK) ? "in" : - "out", (ep_addr & LIBUSB_ENDPOINT_ADDRESS_MASK)); - (void) snprintf(statfilename, PATH_MAX, "%sstat", filename); - - /* - * for interrupt IN endpoints, we need to enable one xfer - * mode before opening the endpoint - */ - if ((ep_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) && - (ep_addr & LIBUSB_ENDPOINT_IN)) { - char control = USB_EP_INTR_ONE_XFER; - int count; - - /* open the status device node for the ep first RDWR */ - if ((fdstat = open(statfilename, O_RDWR)) == -1) { - usbi_dbg("can't open %s RDWR: %d", - statfilename, errno); - } else { - count = write(fdstat, &control, sizeof (control)); - if (count != 1) { - /* this should have worked */ - usbi_dbg("can't write to %s: %d", - statfilename, errno); - (void) close(fdstat); - - return (errno); - } - /* close status node and open xfer node first */ - close (fdstat); - } - } - - /* open the xfer node first in case alt needs to be changed */ - if (ep_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - mode = O_RDWR; - } else if (ep_addr & LIBUSB_ENDPOINT_IN) { - mode = O_RDONLY; - } else { - mode = O_WRONLY; - } - - /* - * IMPORTANT: must open data xfer node first and then open stat node - * Otherwise, it will fail on multi-config or multi-altsetting devices - * with "Device Busy" error. See ugen_epxs_switch_cfg_alt() and - * ugen_epxs_check_alt_switch() in ugen driver source code. - */ - if ((fd = open(filename, mode)) == -1) { - usbi_dbg("can't open %s: %d(%s)", filename, errno, - strerror(errno)); - - return (errno); - } - /* open the status node */ - if ((fdstat = open(statfilename, O_RDONLY)) == -1) { - usbi_dbg("can't open %s: %d", statfilename, errno); - - (void) close(fd); - - return (errno); - } - - hpriv->eps[ep_index].datafd = fd; - hpriv->eps[ep_index].statfd = fdstat; - usbi_dbg("ep=0x%02x datafd=%d, statfd=%d", ep_addr, fd, fdstat); - - return (0); -} - -int -sunos_open(struct libusb_device_handle *handle) -{ - sunos_dev_handle_priv_t *hpriv; - sunos_dev_priv_t *dpriv; - int i; - int ret; - - hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; - dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - hpriv->dpriv = dpriv; - - /* set all file descriptors to "closed" */ - for (i = 0; i < USB_MAXENDPOINTS; i++) { - hpriv->eps[i].datafd = -1; - hpriv->eps[i].statfd = -1; - } - - if ((ret = sunos_usb_open_ep0(hpriv, dpriv)) != LIBUSB_SUCCESS) { - usbi_dbg("fail: %d", ret); - return (ret); - } - - return (LIBUSB_SUCCESS); -} - -void -sunos_close(struct libusb_device_handle *handle) -{ - sunos_dev_handle_priv_t *hpriv; - sunos_dev_priv_t *dpriv; - - usbi_dbg(""); - if (!handle) { - return; - } - - hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; - if (!hpriv) { - return; - } - dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - if (!dpriv) { - return; - } - - sunos_usb_close_all_eps(hpriv); - sunos_usb_close_ep0(hpriv, dpriv); -} - -int -sunos_get_device_descriptor(struct libusb_device *dev, uint8_t *buf, - int *host_endian) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - - memcpy(buf, &dpriv->dev_descr, LIBUSB_DT_DEVICE_SIZE); - *host_endian = 0; - - return (LIBUSB_SUCCESS); -} - -int -sunos_get_active_config_descriptor(struct libusb_device *dev, - uint8_t *buf, size_t len, int *host_endian) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - struct libusb_config_descriptor *cfg; - int proplen; - di_node_t node; - uint8_t *rdata; - - /* - * Keep raw configuration descriptors updated, in case config - * has ever been changed through setCfg. - */ - if ((node = di_init(dpriv->phypath, DINFOCPYALL)) == DI_NODE_NIL) { - usbi_dbg("di_int() failed: %s", strerror(errno)); - return (LIBUSB_ERROR_IO); - } - proplen = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, - "usb-raw-cfg-descriptors", &rdata); - if (proplen <= 0) { - usbi_dbg("can't find raw config descriptors"); - - return (LIBUSB_ERROR_IO); - } - dpriv->raw_cfgdescr = realloc(dpriv->raw_cfgdescr, proplen); - if (dpriv->raw_cfgdescr == NULL) { - return (LIBUSB_ERROR_NO_MEM); - } else { - bcopy(rdata, dpriv->raw_cfgdescr, proplen); - dpriv->cfgvalue = ((struct libusb_config_descriptor *) - rdata)->bConfigurationValue; - } - di_fini(node); - - cfg = (struct libusb_config_descriptor *)dpriv->raw_cfgdescr; - len = MIN(len, libusb_le16_to_cpu(cfg->wTotalLength)); - memcpy(buf, dpriv->raw_cfgdescr, len); - *host_endian = 0; - usbi_dbg("path:%s len %d", dpriv->phypath, len); - - return (len); -} - -int -sunos_get_config_descriptor(struct libusb_device *dev, uint8_t idx, - uint8_t *buf, size_t len, int *host_endian) -{ - /* XXX */ - return(sunos_get_active_config_descriptor(dev, buf, len, host_endian)); -} - -int -sunos_get_configuration(struct libusb_device_handle *handle, int *config) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - - *config = dpriv->cfgvalue; - - usbi_dbg("bConfigurationValue %d", *config); - - return (LIBUSB_SUCCESS); -} - -int -sunos_set_configuration(struct libusb_device_handle *handle, int config) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - sunos_dev_handle_priv_t *hpriv; - - usbi_dbg("bConfigurationValue %d", config); - hpriv = (sunos_dev_handle_priv_t *)handle->os_priv; - - if (dpriv->ugenpath == NULL) - return (LIBUSB_ERROR_NOT_SUPPORTED); - - if (config < 1 || config > dpriv->dev_descr.bNumConfigurations) - return (LIBUSB_ERROR_INVALID_PARAM); - - dpriv->cfgvalue = config; - hpriv->config_index = config - 1; - - return (LIBUSB_SUCCESS); -} - -int -sunos_claim_interface(struct libusb_device_handle *handle, int iface) -{ - usbi_dbg("iface %d", iface); - if (iface < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - - return (LIBUSB_SUCCESS); -} - -int -sunos_release_interface(struct libusb_device_handle *handle, int iface) -{ - sunos_dev_handle_priv_t *hpriv = - (sunos_dev_handle_priv_t *)handle->os_priv; - - usbi_dbg("iface %d", iface); - if (iface < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - - /* XXX: can we release it? */ - hpriv->altsetting[iface] = 0; - - return (LIBUSB_SUCCESS); -} - -int -sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface, - int altsetting) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)handle->dev->os_priv; - sunos_dev_handle_priv_t *hpriv = - (sunos_dev_handle_priv_t *)handle->os_priv; - - usbi_dbg("iface %d, setting %d", iface, altsetting); - - if (iface < 0 || altsetting < 0) { - return (LIBUSB_ERROR_INVALID_PARAM); - } - if (dpriv->ugenpath == NULL) - return (LIBUSB_ERROR_NOT_FOUND); - - /* XXX: can we switch altsetting? */ - hpriv->altsetting[iface] = altsetting; - - return (LIBUSB_SUCCESS); -} - -static void -usb_dump_data(unsigned char *data, size_t size) -{ - int i; - - if (getenv("LIBUSB_DEBUG") == NULL) { - return; - } - - (void) fprintf(stderr, "data dump:"); - for (i = 0; i < size; i++) { - if (i % 16 == 0) { - (void) fprintf(stderr, "\n%08x ", i); - } - (void) fprintf(stderr, "%02x ", (uchar_t)data[i]); - } - (void) fprintf(stderr, "\n"); -} - -static void -sunos_async_callback(union sigval arg) -{ - struct sunos_transfer_priv *tpriv = - (struct sunos_transfer_priv *)arg.sival_ptr; - struct libusb_transfer *xfer = tpriv->transfer; - struct aiocb *aiocb = &tpriv->aiocb; - int ret; - sunos_dev_handle_priv_t *hpriv; - uint8_t ep; - - hpriv = (sunos_dev_handle_priv_t *)xfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(xfer->endpoint); - - ret = aio_error(aiocb); - if (ret != 0) { - xfer->status = sunos_usb_get_status(hpriv->eps[ep].statfd); - } else { - xfer->actual_length = - LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)->transferred = - aio_return(aiocb); - } - - usb_dump_data(xfer->buffer, xfer->actual_length); - - usbi_dbg("ret=%d, len=%d, actual_len=%d", ret, xfer->length, - xfer->actual_length); - - /* async notification */ - usbi_signal_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(xfer)); -} - -static int -sunos_do_async_io(struct libusb_transfer *transfer) -{ - int ret = -1; - struct aiocb *aiocb; - sunos_dev_handle_priv_t *hpriv; - uint8_t ep; - struct sunos_transfer_priv *tpriv; - - usbi_dbg(""); - - tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)); - hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(transfer->endpoint); - - tpriv->transfer = transfer; - aiocb = &tpriv->aiocb; - bzero(aiocb, sizeof (*aiocb)); - aiocb->aio_fildes = hpriv->eps[ep].datafd; - aiocb->aio_buf = transfer->buffer; - aiocb->aio_nbytes = transfer->length; - aiocb->aio_lio_opcode = - ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) == - LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE; - aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD; - aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv; - aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback; - - if (aiocb->aio_lio_opcode == LIO_READ) { - ret = aio_read(aiocb); - } else { - ret = aio_write(aiocb); - } - - return (ret); -} - -/* return the number of bytes read/written */ -static int -usb_do_io(int fd, int stat_fd, char *data, size_t size, int flag, int *status) -{ - int error; - int ret = -1; - - usbi_dbg("usb_do_io(): datafd=%d statfd=%d size=0x%x flag=%s", - fd, stat_fd, size, flag? "WRITE":"READ"); - - switch (flag) { - case READ: - errno = 0; - ret = read(fd, data, size); - usb_dump_data(data, size); - break; - case WRITE: - usb_dump_data(data, size); - errno = 0; - ret = write(fd, data, size); - break; - } - - usbi_dbg("usb_do_io(): amount=%d", ret); - - if (ret < 0) { - int save_errno = errno; - - usbi_dbg("TID=%x io %s errno=%d(%s) ret=%d", pthread_self(), - flag?"WRITE":"READ", errno, strerror(errno), ret); - - /* sunos_usb_get_status will do a read and overwrite errno */ - error = sunos_usb_get_status(stat_fd); - usbi_dbg("io status=%d errno=%d(%s)", error, - save_errno, strerror(save_errno)); - - if (status) { - *status = save_errno; - } - - return (save_errno); - - } else if (status) { - *status = 0; - } - - return (ret); -} - -static int -solaris_submit_ctrl_on_default(struct libusb_transfer *transfer) -{ - int ret = -1, setup_ret; - int status; - sunos_dev_handle_priv_t *hpriv; - struct libusb_device_handle *hdl = transfer->dev_handle; - uint16_t wLength; - uint8_t *data = transfer->buffer; - - hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; - wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - if (hpriv->eps[0].datafd == -1) { - usbi_dbg("ep0 not opened"); - - return (LIBUSB_ERROR_NOT_FOUND); - } - - if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { - usbi_dbg("IN request"); - ret = usb_do_io(hpriv->eps[0].datafd, - hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE, - WRITE, (int *)&status); - } else { - usbi_dbg("OUT request"); - ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, - transfer->buffer, transfer->length, WRITE, - (int *)&transfer->status); - } - - setup_ret = ret; - if (ret < LIBUSB_CONTROL_SETUP_SIZE) { - usbi_dbg("error sending control msg: %d", ret); - - return (LIBUSB_ERROR_IO); - } - - ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - /* Read the remaining bytes for IN request */ - if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == - LIBUSB_ENDPOINT_IN)) { - usbi_dbg("DATA: %d", transfer->length - setup_ret); - ret = usb_do_io(hpriv->eps[0].datafd, - hpriv->eps[0].statfd, - (char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, - wLength, READ, (int *)&transfer->status); - } - - if (ret >= 0) { - transfer->actual_length = ret; - LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret; - } - usbi_dbg("Done: ctrl data bytes %d", ret); - - /* sync transfer handling */ - ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer), - transfer->status); - - return (ret); -} - -int -sunos_clear_halt(struct libusb_device_handle *handle, uint8_t endpoint) -{ - int ret; - - usbi_dbg("endpoint=0x%02x", endpoint); - - ret = libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT | - LIBUSB_RECIPIENT_ENDPOINT | LIBUSB_REQUEST_TYPE_STANDARD, - LIBUSB_REQUEST_CLEAR_FEATURE, 0, endpoint, NULL, 0, 1000); - - usbi_dbg("ret=%d", ret); - - return (ret); -} - -int -sunos_reset_device(struct libusb_device_handle *handle) -{ - usbi_dbg(""); - - return (LIBUSB_ERROR_NOT_SUPPORTED); -} - -void -sunos_destroy_device(struct libusb_device *dev) -{ - sunos_dev_priv_t *dpriv = (sunos_dev_priv_t *)dev->os_priv; - - usbi_dbg(""); - - free(dpriv->raw_cfgdescr); - free(dpriv->ugenpath); - free(dpriv->phypath); -} - -int -sunos_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer; - struct libusb_device_handle *hdl; - int err = 0; - - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hdl = transfer->dev_handle; - - err = sunos_check_device_and_status_open(hdl, - transfer->endpoint, transfer->type); - if (err < 0) { - - return (_errno_to_libusb(err)); - } - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - /* sync transfer */ - usbi_dbg("CTRL transfer: %d", transfer->length); - err = solaris_submit_ctrl_on_default(transfer); - break; - - case LIBUSB_TRANSFER_TYPE_BULK: - /* fallthru */ - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK) - usbi_dbg("BULK transfer: %d", transfer->length); - else - usbi_dbg("INTR transfer: %d", transfer->length); - err = sunos_do_async_io(transfer); - break; - - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - /* Isochronous/Stream is not supported */ - - /* fallthru */ - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) - usbi_dbg("ISOC transfer: %d", transfer->length); - else - usbi_dbg("BULK STREAM transfer: %d", transfer->length); - err = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - return (err); -} - -int -sunos_cancel_transfer(struct usbi_transfer *itransfer) -{ - sunos_xfer_priv_t *tpriv; - sunos_dev_handle_priv_t *hpriv; - struct libusb_transfer *transfer; - struct aiocb *aiocb; - uint8_t ep; - int ret; - - tpriv = usbi_transfer_get_os_priv(itransfer); - aiocb = &tpriv->aiocb; - transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; - ep = sunos_usb_ep_index(transfer->endpoint); - - ret = aio_cancel(hpriv->eps[ep].datafd, aiocb); - - usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes, - hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)? - strerror(0):strerror(errno)); - - if (ret != AIO_CANCELED) { - ret = _errno_to_libusb(errno); - } else { - /* - * we don't need to call usbi_handle_transfer_cancellation(), - * because we'll handle everything in sunos_async_callback. - */ - ret = LIBUSB_SUCCESS; - } - - return (ret); -} - -void -sunos_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - usbi_dbg(""); - - /* Nothing to do */ -} - -int -sunos_handle_transfer_completion(struct usbi_transfer *itransfer) -{ - return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); -} - -int -sunos_clock_gettime(int clkid, struct timespec *tp) -{ - usbi_dbg("clock %d", clkid); - - if (clkid == USBI_CLOCK_REALTIME) - return clock_gettime(CLOCK_REALTIME, tp); - - if (clkid == USBI_CLOCK_MONOTONIC) - return clock_gettime(CLOCK_MONOTONIC, tp); - - return (LIBUSB_ERROR_INVALID_PARAM); -} - -int -_errno_to_libusb(int err) -{ - usbi_dbg("error: %s (%d)", strerror(err), err); - - switch (err) { - case EIO: - return (LIBUSB_ERROR_IO); - case EACCES: - return (LIBUSB_ERROR_ACCESS); - case ENOENT: - return (LIBUSB_ERROR_NO_DEVICE); - case ENOMEM: - return (LIBUSB_ERROR_NO_MEM); - case ETIMEDOUT: - return (LIBUSB_ERROR_TIMEOUT); - } - - return (LIBUSB_ERROR_OTHER); -} - -/* - * sunos_usb_get_status: - * gets status of endpoint - * - * Returns: ugen's last cmd status - */ -static int -sunos_usb_get_status(int fd) -{ - int status, ret; - - usbi_dbg("sunos_usb_get_status(): fd=%d", fd); - - ret = read(fd, &status, sizeof (status)); - if (ret == sizeof (status)) { - switch (status) { - case USB_LC_STAT_NOERROR: - usbi_dbg("No Error"); - break; - case USB_LC_STAT_CRC: - usbi_dbg("CRC Timeout Detected\n"); - break; - case USB_LC_STAT_BITSTUFFING: - usbi_dbg("Bit Stuffing Violation\n"); - break; - case USB_LC_STAT_DATA_TOGGLE_MM: - usbi_dbg("Data Toggle Mismatch\n"); - break; - case USB_LC_STAT_STALL: - usbi_dbg("End Point Stalled\n"); - break; - case USB_LC_STAT_DEV_NOT_RESP: - usbi_dbg("Device is Not Responding\n"); - break; - case USB_LC_STAT_PID_CHECKFAILURE: - usbi_dbg("PID Check Failure\n"); - break; - case USB_LC_STAT_UNEXP_PID: - usbi_dbg("Unexpected PID\n"); - break; - case USB_LC_STAT_DATA_OVERRUN: - usbi_dbg("Data Exceeded Size\n"); - break; - case USB_LC_STAT_DATA_UNDERRUN: - usbi_dbg("Less data received\n"); - break; - case USB_LC_STAT_BUFFER_OVERRUN: - usbi_dbg("Buffer Size Exceeded\n"); - break; - case USB_LC_STAT_BUFFER_UNDERRUN: - usbi_dbg("Buffer Underrun\n"); - break; - case USB_LC_STAT_TIMEOUT: - usbi_dbg("Command Timed Out\n"); - break; - case USB_LC_STAT_NOT_ACCESSED: - usbi_dbg("Not Accessed by h/w\n"); - break; - case USB_LC_STAT_UNSPECIFIED_ERR: - usbi_dbg("Unspecified Error\n"); - break; - case USB_LC_STAT_NO_BANDWIDTH: - usbi_dbg("No Bandwidth\n"); - break; - case USB_LC_STAT_HW_ERR: - usbi_dbg("Host Controller h/w Error\n"); - break; - case USB_LC_STAT_SUSPENDED: - usbi_dbg("Device was Suspended\n"); - break; - case USB_LC_STAT_DISCONNECTED: - usbi_dbg("Device was Disconnected\n"); - break; - case USB_LC_STAT_INTR_BUF_FULL: - usbi_dbg("Interrupt buffer was full\n"); - break; - case USB_LC_STAT_INVALID_REQ: - usbi_dbg("Request was Invalid\n"); - break; - case USB_LC_STAT_INTERRUPTED: - usbi_dbg("Request was Interrupted\n"); - break; - case USB_LC_STAT_NO_RESOURCES: - usbi_dbg("No resources available for " - "request\n"); - break; - case USB_LC_STAT_INTR_POLLING_FAILED: - usbi_dbg("Failed to Restart Poll"); - break; - default: - usbi_dbg("Error Not Determined %d\n", - status); - break; - } - } else { - usbi_dbg("read stat error: %s",strerror(errno)); - status = -1; - } - - return (status); -} - -const struct usbi_os_backend sunos_backend = { - .name = "Solaris", - .caps = 0, - .init = sunos_init, - .exit = sunos_exit, - .get_device_list = sunos_get_device_list, - .get_device_descriptor = sunos_get_device_descriptor, - .get_active_config_descriptor = sunos_get_active_config_descriptor, - .get_config_descriptor = sunos_get_config_descriptor, - .hotplug_poll = NULL, - .open = sunos_open, - .close = sunos_close, - .get_configuration = sunos_get_configuration, - .set_configuration = sunos_set_configuration, - - .claim_interface = sunos_claim_interface, - .release_interface = sunos_release_interface, - .set_interface_altsetting = sunos_set_interface_altsetting, - .clear_halt = sunos_clear_halt, - .reset_device = sunos_reset_device, /* TODO */ - .alloc_streams = NULL, - .free_streams = NULL, - .kernel_driver_active = NULL, - .detach_kernel_driver = NULL, - .attach_kernel_driver = NULL, - .destroy_device = sunos_destroy_device, - .submit_transfer = sunos_submit_transfer, - .cancel_transfer = sunos_cancel_transfer, - .handle_events = NULL, - .clear_transfer_priv = sunos_clear_transfer_priv, - .handle_transfer_completion = sunos_handle_transfer_completion, - .clock_gettime = sunos_clock_gettime, - .device_priv_size = sizeof(sunos_dev_priv_t), - .device_handle_priv_size = sizeof(sunos_dev_handle_priv_t), - .transfer_priv_size = sizeof(sunos_xfer_priv_t), -}; diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/sunos_usb.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/sunos_usb.h deleted file mode 100644 index 57416603199..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/sunos_usb.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Copyright (c) 2016, Oracle and/or its affiliates. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_SUNOS_H -#define LIBUSB_SUNOS_H - -#include -#include -#include "libusbi.h" - -#define READ 0 -#define WRITE 1 - -typedef struct sunos_device_priv { - uint8_t cfgvalue; /* active config value */ - uint8_t *raw_cfgdescr; /* active config descriptor */ - struct libusb_device_descriptor dev_descr; /* usb device descriptor */ - char *ugenpath; /* name of the ugen(4) node */ - char *phypath; /* physical path */ -} sunos_dev_priv_t; - -typedef struct endpoint { - int datafd; /* data file */ - int statfd; /* state file */ -} sunos_ep_priv_t; - -typedef struct sunos_device_handle_priv { - uint8_t altsetting[USB_MAXINTERFACES]; /* a interface's alt */ - uint8_t config_index; - sunos_ep_priv_t eps[USB_MAXENDPOINTS]; - sunos_dev_priv_t *dpriv; /* device private */ -} sunos_dev_handle_priv_t; - -typedef struct sunos_transfer_priv { - struct aiocb aiocb; - struct libusb_transfer *transfer; -} sunos_xfer_priv_t; - -struct node_args { - struct libusb_context *ctx; - struct discovered_devs **discdevs; - const char *last_ugenpath; - di_devlink_handle_t dlink_hdl; -}; - -struct devlink_cbarg { - struct node_args *nargs; /* di node walk arguments */ - di_node_t myself; /* the di node */ - di_minor_t minor; -}; - -/* AIO callback args */ -struct aio_callback_args{ - struct libusb_transfer *transfer; - struct aiocb aiocb; -}; - -#endif /* LIBUSB_SUNOS_H */ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_posix.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_posix.c deleted file mode 100644 index a4f270bbe5b..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_posix.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * libusb synchronization using POSIX Threads - * - * Copyright © 2011 Vitali Lovich - * Copyright © 2011 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#if defined(__linux__) || defined(__OpenBSD__) -# if defined(__OpenBSD__) -# define _BSD_SOURCE -# endif -# include -# include -#elif defined(__APPLE__) -# include -#elif defined(__CYGWIN__) -# include -#endif - -#include "threads_posix.h" -#include "libusbi.h" - -int usbi_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mutex, const struct timeval *tv) -{ - struct timespec timeout; - int r; - - r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout); - if (r < 0) - return r; - - timeout.tv_sec += tv->tv_sec; - timeout.tv_nsec += tv->tv_usec * 1000; - while (timeout.tv_nsec >= 1000000000L) { - timeout.tv_nsec -= 1000000000L; - timeout.tv_sec++; - } - - return pthread_cond_timedwait(cond, mutex, &timeout); -} - -int usbi_get_tid(void) -{ - int ret = -1; -#if defined(__ANDROID__) - ret = gettid(); -#elif defined(__linux__) - ret = syscall(SYS_gettid); -#elif defined(__OpenBSD__) - /* The following only works with OpenBSD > 5.1 as it requires - real thread support. For 5.1 and earlier, -1 is returned. */ - ret = syscall(SYS_getthrid); -#elif defined(__APPLE__) - ret = mach_thread_self(); - mach_port_deallocate(mach_task_self(), ret); -#elif defined(__CYGWIN__) - ret = GetCurrentThreadId(); -#endif -/* TODO: NetBSD thread ID support */ - return ret; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_posix.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_posix.h deleted file mode 100644 index 4c1514ea612..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_posix.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * libusb synchronization using POSIX Threads - * - * Copyright © 2010 Peter Stuge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_THREADS_POSIX_H -#define LIBUSB_THREADS_POSIX_H - -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#define usbi_mutex_static_t pthread_mutex_t -#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -#define usbi_mutex_static_lock pthread_mutex_lock -#define usbi_mutex_static_unlock pthread_mutex_unlock - -#define usbi_mutex_t pthread_mutex_t -#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL) -#define usbi_mutex_lock pthread_mutex_lock -#define usbi_mutex_unlock pthread_mutex_unlock -#define usbi_mutex_trylock pthread_mutex_trylock -#define usbi_mutex_destroy pthread_mutex_destroy - -#define usbi_cond_t pthread_cond_t -#define usbi_cond_init(cond) pthread_cond_init((cond), NULL) -#define usbi_cond_wait pthread_cond_wait -#define usbi_cond_broadcast pthread_cond_broadcast -#define usbi_cond_destroy pthread_cond_destroy - -#define usbi_tls_key_t pthread_key_t -#define usbi_tls_key_create(key) pthread_key_create((key), NULL) -#define usbi_tls_key_get pthread_getspecific -#define usbi_tls_key_set pthread_setspecific -#define usbi_tls_key_delete pthread_key_delete - -int usbi_get_tid(void); - -#endif /* LIBUSB_THREADS_POSIX_H */ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_windows.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_windows.c deleted file mode 100644 index 7c2e52dba6a..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_windows.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * libusb synchronization on Microsoft Windows - * - * Copyright © 2010 Michael Plante - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include "libusbi.h" - -struct usbi_cond_perthread { - struct list_head list; - DWORD tid; - HANDLE event; -}; - -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) -{ - if (!mutex) - return EINVAL; - while (InterlockedExchange(mutex, 1) == 1) - SleepEx(0, TRUE); - return 0; -} - -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) -{ - if (!mutex) - return EINVAL; - InterlockedExchange(mutex, 0); - return 0; -} - -int usbi_mutex_init(usbi_mutex_t *mutex) -{ - if (!mutex) - return EINVAL; - *mutex = CreateMutex(NULL, FALSE, NULL); - if (!*mutex) - return ENOMEM; - return 0; -} - -int usbi_mutex_lock(usbi_mutex_t *mutex) -{ - DWORD result; - - if (!mutex) - return EINVAL; - result = WaitForSingleObject(*mutex, INFINITE); - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - else - return EINVAL; // don't know how this would happen - // so don't know proper errno -} - -int usbi_mutex_unlock(usbi_mutex_t *mutex) -{ - if (!mutex) - return EINVAL; - if (ReleaseMutex(*mutex)) - return 0; - else - return EPERM; -} - -int usbi_mutex_trylock(usbi_mutex_t *mutex) -{ - DWORD result; - - if (!mutex) - return EINVAL; - result = WaitForSingleObject(*mutex, 0); - if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) - return 0; // acquired (ToDo: check that abandoned is ok) - else if (result == WAIT_TIMEOUT) - return EBUSY; - else - return EINVAL; // don't know how this would happen - // so don't know proper error -} - -int usbi_mutex_destroy(usbi_mutex_t *mutex) -{ - // It is not clear if CloseHandle failure is due to failure to unlock. - // If so, this should be errno=EBUSY. - if (!mutex || !CloseHandle(*mutex)) - return EINVAL; - *mutex = NULL; - return 0; -} - -int usbi_cond_init(usbi_cond_t *cond) -{ - if (!cond) - return EINVAL; - list_init(&cond->waiters); - list_init(&cond->not_waiting); - return 0; -} - -int usbi_cond_destroy(usbi_cond_t *cond) -{ - // This assumes no one is using this anymore. The check MAY NOT BE safe. - struct usbi_cond_perthread *pos, *next_pos; - - if(!cond) - return EINVAL; - if (!list_empty(&cond->waiters)) - return EBUSY; // (!see above!) - list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) { - CloseHandle(pos->event); - list_del(&pos->list); - free(pos); - } - return 0; -} - -int usbi_cond_broadcast(usbi_cond_t *cond) -{ - // Assumes mutex is locked; this is not in keeping with POSIX spec, but - // libusb does this anyway, so we simplify by not adding more sync - // primitives to the CV definition! - int fail = 0; - struct usbi_cond_perthread *pos; - - if (!cond) - return EINVAL; - list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) { - if (!SetEvent(pos->event)) - fail = 1; - } - // The wait function will remove its respective item from the list. - return fail ? EINVAL : 0; -} - -__inline static int usbi_cond_intwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, DWORD timeout_ms) -{ - struct usbi_cond_perthread *pos; - int r, found = 0; - DWORD r2, tid = GetCurrentThreadId(); - - if (!cond || !mutex) - return EINVAL; - list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { - if(tid == pos->tid) { - found = 1; - break; - } - } - - if (!found) { - pos = calloc(1, sizeof(struct usbi_cond_perthread)); - if (!pos) - return ENOMEM; // This errno is not POSIX-allowed. - pos->tid = tid; - pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. - if (!pos->event) { - free(pos); - return ENOMEM; - } - list_add(&pos->list, &cond->not_waiting); - } - - list_del(&pos->list); // remove from not_waiting list. - list_add(&pos->list, &cond->waiters); - - r = usbi_mutex_unlock(mutex); - if (r) - return r; - - r2 = WaitForSingleObject(pos->event, timeout_ms); - r = usbi_mutex_lock(mutex); - if (r) - return r; - - list_del(&pos->list); - list_add(&pos->list, &cond->not_waiting); - - if (r2 == WAIT_OBJECT_0) - return 0; - else if (r2 == WAIT_TIMEOUT) - return ETIMEDOUT; - else - return EINVAL; -} -// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) -{ - return usbi_cond_intwait(cond, mutex, INFINITE); -} - -int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timeval *tv) -{ - DWORD millis; - - millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); - /* round up to next millisecond */ - if (tv->tv_usec % 1000) - millis++; - return usbi_cond_intwait(cond, mutex, millis); -} - -int usbi_tls_key_create(usbi_tls_key_t *key) -{ - if (!key) - return EINVAL; - *key = TlsAlloc(); - if (*key == TLS_OUT_OF_INDEXES) - return ENOMEM; - else - return 0; -} - -void *usbi_tls_key_get(usbi_tls_key_t key) -{ - return TlsGetValue(key); -} - -int usbi_tls_key_set(usbi_tls_key_t key, void *value) -{ - if (TlsSetValue(key, value)) - return 0; - else - return EINVAL; -} - -int usbi_tls_key_delete(usbi_tls_key_t key) -{ - if (TlsFree(key)) - return 0; - else - return EINVAL; -} - -int usbi_get_tid(void) -{ - return (int)GetCurrentThreadId(); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_windows.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_windows.h deleted file mode 100644 index e97ee787572..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/threads_windows.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * libusb synchronization on Microsoft Windows - * - * Copyright © 2010 Michael Plante - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBUSB_THREADS_WINDOWS_H -#define LIBUSB_THREADS_WINDOWS_H - -#define usbi_mutex_static_t volatile LONG -#define USBI_MUTEX_INITIALIZER 0 - -#define usbi_mutex_t HANDLE - -typedef struct usbi_cond { - // Every time a thread touches the CV, it winds up in one of these lists. - // It stays there until the CV is destroyed, even if the thread terminates. - struct list_head waiters; - struct list_head not_waiting; -} usbi_cond_t; - -// We *were* getting timespec from pthread.h: -#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) -#define HAVE_STRUCT_TIMESPEC 1 -#define _TIMESPEC_DEFINED 1 -struct timespec { - long tv_sec; - long tv_nsec; -}; -#endif /* HAVE_STRUCT_TIMESPEC | _TIMESPEC_DEFINED */ - -// We *were* getting ETIMEDOUT from pthread.h: -#ifndef ETIMEDOUT -# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ -#endif - -#define usbi_tls_key_t DWORD - -int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); -int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); - -int usbi_mutex_init(usbi_mutex_t *mutex); -int usbi_mutex_lock(usbi_mutex_t *mutex); -int usbi_mutex_unlock(usbi_mutex_t *mutex); -int usbi_mutex_trylock(usbi_mutex_t *mutex); -int usbi_mutex_destroy(usbi_mutex_t *mutex); - -int usbi_cond_init(usbi_cond_t *cond); -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); -int usbi_cond_timedwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, const struct timeval *tv); -int usbi_cond_broadcast(usbi_cond_t *cond); -int usbi_cond_destroy(usbi_cond_t *cond); - -int usbi_tls_key_create(usbi_tls_key_t *key); -void *usbi_tls_key_get(usbi_tls_key_t key); -int usbi_tls_key_set(usbi_tls_key_t key, void *value); -int usbi_tls_key_delete(usbi_tls_key_t key); - -int usbi_get_tid(void); - -#endif /* LIBUSB_THREADS_WINDOWS_H */ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/wince_usb.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/wince_usb.c deleted file mode 100644 index 0d466b8c9c9..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/wince_usb.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Windows CE backend for libusb 1.0 - * Copyright © 2011-2013 RealVNC Ltd. - * Large portions taken from Windows backend, which is - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include - -#include "libusbi.h" -#include "wince_usb.h" - -// Global variables -int windows_version = WINDOWS_CE; -static uint64_t hires_frequency, hires_ticks_to_ps; -static HANDLE driver_handle = INVALID_HANDLE_VALUE; -static int concurrent_usage = -1; - -/* - * Converts a windows error to human readable string - * uses retval as errorcode, or, if 0, use GetLastError() - */ -#if defined(ENABLE_LOGGING) -static const char *windows_error_str(DWORD error_code) -{ - static TCHAR wErr_string[ERR_BUFFER_SIZE]; - static char err_string[ERR_BUFFER_SIZE]; - - DWORD size; - int len; - - if (error_code == 0) - error_code = GetLastError(); - - len = sprintf(err_string, "[%u] ", (unsigned int)error_code); - - size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - wErr_string, ERR_BUFFER_SIZE, NULL); - if (size == 0) { - DWORD format_error = GetLastError(); - if (format_error) - snprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", - (unsigned int)error_code, (unsigned int)format_error); - else - snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); - } else { - // Remove CR/LF terminators, if present - size_t pos = size - 2; - if (wErr_string[pos] == 0x0D) - wErr_string[pos] = 0; - - if (!WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, &err_string[len], ERR_BUFFER_SIZE - len, NULL, NULL)) - strcpy(err_string, "Unable to convert error string"); - } - - return err_string; -} -#endif - -static struct wince_device_priv *_device_priv(struct libusb_device *dev) -{ - return (struct wince_device_priv *)dev->os_priv; -} - -// ceusbkwrapper to libusb error code mapping -static int translate_driver_error(DWORD error) -{ - switch (error) { - case ERROR_INVALID_PARAMETER: - return LIBUSB_ERROR_INVALID_PARAM; - case ERROR_CALL_NOT_IMPLEMENTED: - case ERROR_NOT_SUPPORTED: - return LIBUSB_ERROR_NOT_SUPPORTED; - case ERROR_NOT_ENOUGH_MEMORY: - return LIBUSB_ERROR_NO_MEM; - case ERROR_INVALID_HANDLE: - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_BUSY: - return LIBUSB_ERROR_BUSY; - - // Error codes that are either unexpected, or have - // no suitable LIBUSB_ERROR equivalent. - case ERROR_CANCELLED: - case ERROR_INTERNAL_ERROR: - default: - return LIBUSB_ERROR_OTHER; - } -} - -static int init_dllimports(void) -{ - DLL_GET_HANDLE(ceusbkwrapper); - DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceList, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseDeviceList, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceAddress, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetDeviceDescriptor, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfigDescriptor, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwCloseDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwCancelTransfer, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueControlTransfer, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwClaimInterface, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwReleaseInterface, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwSetInterfaceAlternateSetting, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltHost, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwClearHaltDevice, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwGetConfig, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwSetConfig, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwResetDevice, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwKernelDriverActive, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwAttachKernelDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwDetachKernelDriver, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE); - DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE); - - return LIBUSB_SUCCESS; -} - -static void exit_dllimports(void) -{ - DLL_FREE_HANDLE(ceusbkwrapper); -} - -static int init_device( - struct libusb_device *dev, UKW_DEVICE drv_dev, - unsigned char bus_addr, unsigned char dev_addr) -{ - struct wince_device_priv *priv = _device_priv(dev); - int r = LIBUSB_SUCCESS; - - dev->bus_number = bus_addr; - dev->device_address = dev_addr; - priv->dev = drv_dev; - - if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) - r = translate_driver_error(GetLastError()); - - return r; -} - -// Internal API functions -static int wince_init(struct libusb_context *ctx) -{ - int r = LIBUSB_ERROR_OTHER; - HANDLE semaphore; - LARGE_INTEGER li_frequency; - TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphore(NULL, 1, 1, sem_name); - if (semaphore == NULL) { - usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_MEM; - } - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore's release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); - CloseHandle(semaphore); - return LIBUSB_ERROR_NO_MEM; - } - - // NB: concurrent usage supposes that init calls are equally balanced with - // exit calls. If init is called more than exit, we will not exit properly - if ( ++concurrent_usage == 0 ) { // First init? - // Initialize pollable file descriptors - init_polling(); - - // Load DLL imports - if (init_dllimports() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - // try to open a handle to the driver - driver_handle = UkwOpenDriver(); - if (driver_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not connect to driver"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - // find out if we have access to a monotonic (hires) timer - if (QueryPerformanceFrequency(&li_frequency)) { - hires_frequency = li_frequency.QuadPart; - // The hires frequency can go as high as 4 GHz, so we'll use a conversion - // to picoseconds to compute the tv_nsecs part in clock_gettime - hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; - usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); - } else { - usbi_dbg("no hires timer available on this platform"); - hires_frequency = 0; - hires_ticks_to_ps = UINT64_C(0); - } - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: // Holds semaphore here. - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - exit_dllimports(); - exit_polling(); - - if (driver_handle != INVALID_HANDLE_VALUE) { - UkwCloseDriver(driver_handle); - driver_handle = INVALID_HANDLE_VALUE; - } - } - - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); - return r; -} - -static void wince_exit(void) -{ - HANDLE semaphore; - TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphore(NULL, 1, 1, sem_name); - if (semaphore == NULL) - return; - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - CloseHandle(semaphore); - return; - } - - // Only works if exits and inits are balanced exactly - if (--concurrent_usage < 0) { // Last exit - exit_dllimports(); - exit_polling(); - - if (driver_handle != INVALID_HANDLE_VALUE) { - UkwCloseDriver(driver_handle); - driver_handle = INVALID_HANDLE_VALUE; - } - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); -} - -static int wince_get_device_list( - struct libusb_context *ctx, - struct discovered_devs **discdevs) -{ - UKW_DEVICE devices[MAX_DEVICE_COUNT]; - struct discovered_devs *new_devices = *discdevs; - DWORD count = 0, i; - struct libusb_device *dev = NULL; - unsigned char bus_addr, dev_addr; - unsigned long session_id; - BOOL success; - DWORD release_list_offset = 0; - int r = LIBUSB_SUCCESS; - - success = UkwGetDeviceList(driver_handle, devices, MAX_DEVICE_COUNT, &count); - if (!success) { - int libusbErr = translate_driver_error(GetLastError()); - usbi_err(ctx, "could not get devices: %s", windows_error_str(0)); - return libusbErr; - } - - for (i = 0; i < count; ++i) { - release_list_offset = i; - success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id); - if (!success) { - r = translate_driver_error(GetLastError()); - usbi_err(ctx, "could not get device address for %u: %s", (unsigned int)i, windows_error_str(0)); - goto err_out; - } - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev) { - usbi_dbg("using existing device for %u/%u (session %lu)", - bus_addr, dev_addr, session_id); - // Release just this element in the device list (as we already hold a - // reference to it). - UkwReleaseDeviceList(driver_handle, &devices[i], 1); - release_list_offset++; - } else { - usbi_dbg("allocating new device for %u/%u (session %lu)", - bus_addr, dev_addr, session_id); - dev = usbi_alloc_device(ctx, session_id); - if (!dev) { - r = LIBUSB_ERROR_NO_MEM; - goto err_out; - } - - r = init_device(dev, devices[i], bus_addr, dev_addr); - if (r < 0) - goto err_out; - - r = usbi_sanitize_device(dev); - if (r < 0) - goto err_out; - } - - new_devices = discovered_devs_append(new_devices, dev); - if (!discdevs) { - r = LIBUSB_ERROR_NO_MEM; - goto err_out; - } - - libusb_unref_device(dev); - } - - *discdevs = new_devices; - return r; -err_out: - *discdevs = new_devices; - libusb_unref_device(dev); - // Release the remainder of the unprocessed device list. - // The devices added to new_devices already will still be passed up to libusb, - // which can dispose of them at its leisure. - UkwReleaseDeviceList(driver_handle, &devices[release_list_offset], count - release_list_offset); - return r; -} - -static int wince_open(struct libusb_device_handle *handle) -{ - // Nothing to do to open devices as a handle to it has - // been retrieved by wince_get_device_list - return LIBUSB_SUCCESS; -} - -static void wince_close(struct libusb_device_handle *handle) -{ - // Nothing to do as wince_open does nothing. -} - -static int wince_get_device_descriptor( - struct libusb_device *device, - unsigned char *buffer, int *host_endian) -{ - struct wince_device_priv *priv = _device_priv(device); - - *host_endian = 1; - memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH); - return LIBUSB_SUCCESS; -} - -static int wince_get_active_config_descriptor( - struct libusb_device *device, - unsigned char *buffer, size_t len, int *host_endian) -{ - struct wince_device_priv *priv = _device_priv(device); - DWORD actualSize = len; - - *host_endian = 0; - if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) - return translate_driver_error(GetLastError()); - - return actualSize; -} - -static int wince_get_config_descriptor( - struct libusb_device *device, - uint8_t config_index, - unsigned char *buffer, size_t len, int *host_endian) -{ - struct wince_device_priv *priv = _device_priv(device); - DWORD actualSize = len; - - *host_endian = 0; - if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize)) - return translate_driver_error(GetLastError()); - - return actualSize; -} - -static int wince_get_configuration( - struct libusb_device_handle *handle, - int *config) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - UCHAR cv = 0; - - if (!UkwGetConfig(priv->dev, &cv)) - return translate_driver_error(GetLastError()); - - (*config) = cv; - return LIBUSB_SUCCESS; -} - -static int wince_set_configuration( - struct libusb_device_handle *handle, - int config) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - // Setting configuration 0 places the device in Address state. - // This should correspond to the "unconfigured state" required by - // libusb when the specified configuration is -1. - UCHAR cv = (config < 0) ? 0 : config; - if (!UkwSetConfig(priv->dev, cv)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_claim_interface( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwClaimInterface(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_release_interface( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) - return translate_driver_error(GetLastError()); - - if (!UkwReleaseInterface(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_set_interface_altsetting( - struct libusb_device_handle *handle, - int interface_number, int altsetting) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_clear_halt( - struct libusb_device_handle *handle, - unsigned char endpoint) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwClearHaltHost(priv->dev, endpoint)) - return translate_driver_error(GetLastError()); - - if (!UkwClearHaltDevice(priv->dev, endpoint)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_reset_device( - struct libusb_device_handle *handle) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwResetDevice(priv->dev)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_kernel_driver_active( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - BOOL result = FALSE; - - if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) - return translate_driver_error(GetLastError()); - - return result ? 1 : 0; -} - -static int wince_detach_kernel_driver( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwDetachKernelDriver(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_attach_kernel_driver( - struct libusb_device_handle *handle, - int interface_number) -{ - struct wince_device_priv *priv = _device_priv(handle->dev); - - if (!UkwAttachKernelDriver(priv->dev, interface_number)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static void wince_destroy_device(struct libusb_device *dev) -{ - struct wince_device_priv *priv = _device_priv(dev); - - UkwReleaseDeviceList(driver_handle, &priv->dev, 1); -} - -static void wince_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); - - // No need to cancel transfer as it is either complete or abandoned - wfd.itransfer = NULL; - CloseHandle(wfd.handle); - usbi_free_fd(&transfer_priv->pollable_fd); -} - -static int wince_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) - return translate_driver_error(GetLastError()); - - return LIBUSB_SUCCESS; -} - -static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - BOOL direction_in, ret; - struct winfd wfd; - DWORD flags; - HANDLE eventHandle; - PUKW_CONTROL_HEADER setup = NULL; - const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; - - transfer_priv->pollable_fd = INVALID_WINFD; - if (control_transfer) { - setup = (PUKW_CONTROL_HEADER) transfer->buffer; - direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; - } else { - direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - } - flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; - flags |= UKW_TF_SHORT_TRANSFER_OK; - - eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); - if (eventHandle == NULL) { - usbi_err(ctx, "Failed to create event for async transfer"); - return LIBUSB_ERROR_NO_MEM; - } - - wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer); - if (wfd.fd < 0) { - CloseHandle(eventHandle); - return LIBUSB_ERROR_NO_MEM; - } - - transfer_priv->pollable_fd = wfd; - if (control_transfer) { - // Split out control setup header and data buffer - DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); - PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)]; - - ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped); - } else { - ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, - transfer->length, &transfer->actual_length, wfd.overlapped); - } - - if (!ret) { - int libusbErr = translate_driver_error(GetLastError()); - usbi_err(ctx, "UkwIssue%sTransfer failed: error %u", - control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError()); - wince_clear_transfer_priv(itransfer); - return libusbErr; - } - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT); - - return LIBUSB_SUCCESS; -} - -static int wince_submit_iso_transfer(struct usbi_transfer *itransfer) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int wince_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - return wince_submit_control_or_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return wince_submit_iso_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static void wince_transfer_callback( - struct usbi_transfer *itransfer, - uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); - struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int status; - - usbi_dbg("handling I/O completion with errcode %u", io_result); - - if (io_result == ERROR_NOT_SUPPORTED && - transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) { - /* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper - * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the - * endpoint isn't actually stalled. - * - * One example of this is that some devices will occasionally fail to reply to an IN - * token. The WinCE USB layer carries on with the transaction until it is completed - * (or cancelled) but then completes it with USB_ERROR_STALL. - * - * This code therefore needs to confirm that there really is a stall error, by both - * checking the pipe status and requesting the endpoint status from the device. - */ - BOOL halted = FALSE; - usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall"); - if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) { - /* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS - * control request to the device. This is done synchronously, which is a bit - * naughty, but this is a special corner case. - */ - WORD wStatus = 0; - DWORD written = 0; - UKW_CONTROL_HEADER ctrlHeader; - ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD | - LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT; - ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS; - ctrlHeader.wValue = 0; - ctrlHeader.wIndex = transfer->endpoint; - ctrlHeader.wLength = sizeof(wStatus); - if (UkwIssueControlTransfer(priv->dev, - UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT, - &ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) { - if (written == sizeof(wStatus) && - (wStatus & STATUS_HALT_FLAG) == 0) { - if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) { - usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success"); - io_result = ERROR_SUCCESS; - } else { - usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error"); - io_result = ERROR_IO_DEVICE; - } - } - } - } - } - - switch(io_result) { - case ERROR_SUCCESS: - itransfer->transferred += io_size; - status = LIBUSB_TRANSFER_COMPLETED; - break; - case ERROR_CANCELLED: - usbi_dbg("detected transfer cancel"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - case ERROR_NOT_SUPPORTED: - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - - wince_clear_transfer_priv(itransfer); - if (status == LIBUSB_TRANSFER_CANCELLED) - usbi_handle_transfer_cancellation(itransfer); - else - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); -} - -static void wince_handle_callback( - struct usbi_transfer *itransfer, - uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - wince_transfer_callback (itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } -} - -static int wince_handle_events( - struct libusb_context *ctx, - struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - struct wince_transfer_priv* transfer_priv = NULL; - POLL_NFDS_TYPE i = 0; - BOOL found = FALSE; - struct usbi_transfer *transfer; - DWORD io_size, io_result; - int r = LIBUSB_SUCCESS; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) - continue; - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - usbi_mutex_lock(&ctx->flying_transfers_lock); - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - transfer_priv = usbi_transfer_get_os_priv(transfer); - if (transfer_priv->pollable_fd.fd == fds[i].fd) { - found = TRUE; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) { - io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal; - io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; - usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - wince_handle_callback(transfer, io_result, io_size); - } else if (found) { - usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); - r = LIBUSB_ERROR_OTHER; - break; - } else { - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - r = LIBUSB_ERROR_NOT_FOUND; - break; - } - } - usbi_mutex_unlock(&ctx->open_devs_lock); - - return r; -} - -/* - * Monotonic and real time functions - */ -static int wince_clock_gettime(int clk_id, struct timespec *tp) -{ - LARGE_INTEGER hires_counter; - ULARGE_INTEGER rtime; - FILETIME filetime; - SYSTEMTIME st; - - switch(clk_id) { - case USBI_CLOCK_MONOTONIC: - if (hires_frequency != 0 && QueryPerformanceCounter(&hires_counter)) { - tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); - tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); - return LIBUSB_SUCCESS; - } - // Fall through and return real-time if monotonic read failed or was not detected @ init - case USBI_CLOCK_REALTIME: - // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 - // Note however that our resolution is bounded by the Windows system time - // functions and is at best of the order of 1 ms (or, usually, worse) - GetSystemTime(&st); - SystemTimeToFileTime(&st, &filetime); - rtime.LowPart = filetime.dwLowDateTime; - rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= EPOCH_TIME; - tp->tv_sec = (long)(rtime.QuadPart / 10000000); - tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100); - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -const struct usbi_os_backend wince_backend = { - "Windows CE", - 0, - wince_init, - wince_exit, - - wince_get_device_list, - NULL, /* hotplug_poll */ - wince_open, - wince_close, - - wince_get_device_descriptor, - wince_get_active_config_descriptor, - wince_get_config_descriptor, - NULL, /* get_config_descriptor_by_value() */ - - wince_get_configuration, - wince_set_configuration, - wince_claim_interface, - wince_release_interface, - - wince_set_interface_altsetting, - wince_clear_halt, - wince_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc() */ - NULL, /* dev_mem_free() */ - - wince_kernel_driver_active, - wince_detach_kernel_driver, - wince_attach_kernel_driver, - - wince_destroy_device, - - wince_submit_transfer, - wince_cancel_transfer, - wince_clear_transfer_priv, - - wince_handle_events, - NULL, /* handle_transfer_completion() */ - - wince_clock_gettime, - sizeof(struct wince_device_priv), - 0, - sizeof(struct wince_transfer_priv), -}; diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/wince_usb.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/wince_usb.h deleted file mode 100644 index edcb9fcc400..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/wince_usb.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Windows CE backend for libusb 1.0 - * Copyright © 2011-2013 RealVNC Ltd. - * Portions taken from Windows backend, which is - * Copyright © 2009-2010 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#pragma once - -#include "windows_common.h" - -#include -#include "poll_windows.h" - -#define MAX_DEVICE_COUNT 256 - -// This is a modified dump of the types in the ceusbkwrapper.h library header -// with functions transformed into extern pointers. -// -// This backend dynamically loads ceusbkwrapper.dll and doesn't include -// ceusbkwrapper.h directly to simplify the build process. The kernel -// side wrapper driver is built using the platform image build tools, -// which makes it difficult to reference directly from the libusb build -// system. -struct UKW_DEVICE_PRIV; -typedef struct UKW_DEVICE_PRIV *UKW_DEVICE; -typedef UKW_DEVICE *PUKW_DEVICE, *LPUKW_DEVICE; - -typedef struct { - UINT8 bLength; - UINT8 bDescriptorType; - UINT16 bcdUSB; - UINT8 bDeviceClass; - UINT8 bDeviceSubClass; - UINT8 bDeviceProtocol; - UINT8 bMaxPacketSize0; - UINT16 idVendor; - UINT16 idProduct; - UINT16 bcdDevice; - UINT8 iManufacturer; - UINT8 iProduct; - UINT8 iSerialNumber; - UINT8 bNumConfigurations; -} UKW_DEVICE_DESCRIPTOR, *PUKW_DEVICE_DESCRIPTOR, *LPUKW_DEVICE_DESCRIPTOR; - -typedef struct { - UINT8 bmRequestType; - UINT8 bRequest; - UINT16 wValue; - UINT16 wIndex; - UINT16 wLength; -} UKW_CONTROL_HEADER, *PUKW_CONTROL_HEADER, *LPUKW_CONTROL_HEADER; - -// Collection of flags which can be used when issuing transfer requests -/* Indicates that the transfer direction is 'in' */ -#define UKW_TF_IN_TRANSFER 0x00000001 -/* Indicates that the transfer direction is 'out' */ -#define UKW_TF_OUT_TRANSFER 0x00000000 -/* Specifies that the transfer should complete as soon as possible, - * even if no OVERLAPPED structure has been provided. */ -#define UKW_TF_NO_WAIT 0x00000100 -/* Indicates that transfers shorter than the buffer are ok */ -#define UKW_TF_SHORT_TRANSFER_OK 0x00000200 -#define UKW_TF_SEND_TO_DEVICE 0x00010000 -#define UKW_TF_SEND_TO_INTERFACE 0x00020000 -#define UKW_TF_SEND_TO_ENDPOINT 0x00040000 -/* Don't block when waiting for memory allocations */ -#define UKW_TF_DONT_BLOCK_FOR_MEM 0x00080000 - -/* Value to use when dealing with configuration values, such as UkwGetConfigDescriptor, - * to specify the currently active configuration for the device. */ -#define UKW_ACTIVE_CONFIGURATION -1 - -DLL_DECLARE_HANDLE(ceusbkwrapper); -DLL_DECLARE_FUNC(WINAPI, HANDLE, UkwOpenDriver, ()); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceList, (HANDLE, LPUKW_DEVICE, DWORD, LPDWORD)); -DLL_DECLARE_FUNC(WINAPI, void, UkwReleaseDeviceList, (HANDLE, LPUKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceAddress, (UKW_DEVICE, unsigned char*, unsigned char*, unsigned long*)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetDeviceDescriptor, (UKW_DEVICE, LPUKW_DEVICE_DESCRIPTOR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfigDescriptor, (UKW_DEVICE, DWORD, LPVOID, DWORD, LPDWORD)); -DLL_DECLARE_FUNC(WINAPI, void, UkwCloseDriver, (HANDLE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwCancelTransfer, (UKW_DEVICE, LPOVERLAPPED, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueControlTransfer, (UKW_DEVICE, DWORD, LPUKW_CONTROL_HEADER, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClaimInterface, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwReleaseInterface, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetInterfaceAlternateSetting, (UKW_DEVICE, DWORD, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltHost, (UKW_DEVICE, UCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwClearHaltDevice, (UKW_DEVICE, UCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwGetConfig, (UKW_DEVICE, PUCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwSetConfig, (UKW_DEVICE, UCHAR)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwResetDevice, (UKW_DEVICE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwKernelDriverActive, (UKW_DEVICE, DWORD, PBOOL)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwAttachKernelDriver, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwDetachKernelDriver, (UKW_DEVICE, DWORD)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIssueBulkTransfer, (UKW_DEVICE, DWORD, UCHAR, LPVOID, DWORD, LPDWORD, LPOVERLAPPED)); -DLL_DECLARE_FUNC(WINAPI, BOOL, UkwIsPipeHalted, (UKW_DEVICE, UCHAR, LPBOOL)); - -// Used to determine if an endpoint status really is halted on a failed transfer. -#define STATUS_HALT_FLAG 0x1 - -struct wince_device_priv { - UKW_DEVICE dev; - UKW_DEVICE_DESCRIPTOR desc; -}; - -struct wince_transfer_priv { - struct winfd pollable_fd; - uint8_t interface_number; -}; - diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_common.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_common.h deleted file mode 100644 index 55344ca264e..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_common.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Windows backend common header for libusb 1.0 - * - * This file brings together header code common between - * the desktop Windows and Windows CE backends. - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -// Windows API default is uppercase - ugh! -#if !defined(bool) -#define bool BOOL -#endif -#if !defined(true) -#define true TRUE -#endif -#if !defined(false) -#define false FALSE -#endif - -#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime - -#if defined(__CYGWIN__ ) -#define _stricmp strcasecmp -#define _strdup strdup -// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread -#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f) -#endif - -#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0) - -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif - -#define ERR_BUFFER_SIZE 256 - -/* - * API macros - leveraged from libusb-win32 1.x - */ -#ifndef _WIN32_WCE -#define DLL_STRINGIFY(s) #s -#define DLL_LOAD_LIBRARY(name) LoadLibraryA(DLL_STRINGIFY(name)) -#else -#define DLL_STRINGIFY(s) L#s -#define DLL_LOAD_LIBRARY(name) LoadLibrary(DLL_STRINGIFY(name)) -#endif - -/* - * Macros for handling DLL themselves - */ -#define DLL_DECLARE_HANDLE(name) \ - static HMODULE __dll_##name##_handle = NULL - -#define DLL_GET_HANDLE(name) \ - do { \ - __dll_##name##_handle = DLL_LOAD_LIBRARY(name); \ - if (!__dll_##name##_handle) \ - return LIBUSB_ERROR_OTHER; \ - } while (0) - -#define DLL_FREE_HANDLE(name) \ - do { \ - if (__dll_##name##_handle) { \ - FreeLibrary(__dll_##name##_handle); \ - __dll_##name##_handle = NULL; \ - } \ - } while(0) - - -/* - * Macros for handling functions within a DLL - */ -#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \ - typedef ret (api * __dll_##name##_func_t)args; \ - static __dll_##name##_func_t prefixname = NULL - -#define DLL_DECLARE_FUNC(api, ret, name, args) \ - DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args) -#define DLL_DECLARE_FUNC_PREFIXED(api, ret, prefix, name, args) \ - DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefix##name, name, args) - -#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \ - do { \ - HMODULE h = __dll_##dll##_handle; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ - DLL_STRINGIFY(name)); \ - if (prefixname) \ - break; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \ - if (prefixname) \ - break; \ - prefixname = (__dll_##name##_func_t)GetProcAddress(h, \ - DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \ - if (prefixname) \ - break; \ - if (ret_on_failure) \ - return LIBUSB_ERROR_NOT_FOUND; \ - } while(0) - -#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \ - DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure) -#define DLL_LOAD_FUNC_PREFIXED(dll, prefix, name, ret_on_failure) \ - DLL_LOAD_FUNC_PREFIXNAME(dll, prefix##name, name, ret_on_failure) diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_nt_common.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_nt_common.c deleted file mode 100644 index d935394a65b..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_nt_common.c +++ /dev/null @@ -1,591 +0,0 @@ -/* - * windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software - * Hash table functions adapted from glibc, by Ulrich Drepper et al. - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include - -#include "libusbi.h" -#include "windows_common.h" -#include "windows_nt_common.h" - -// Global variables for clock_gettime mechanism -static uint64_t hires_ticks_to_ps; -static uint64_t hires_frequency; - -#define TIMER_REQUEST_RETRY_MS 100 -#define WM_TIMER_REQUEST (WM_USER + 1) -#define WM_TIMER_EXIT (WM_USER + 2) - -// used for monotonic clock_gettime() -struct timer_request { - struct timespec *tp; - HANDLE event; -}; - -// Timer thread -static HANDLE timer_thread = NULL; -static DWORD timer_thread_id = 0; - -/* User32 dependencies */ -DLL_DECLARE_HANDLE(User32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM)); - -static unsigned __stdcall windows_clock_gettime_threaded(void *param); - -/* -* Converts a windows error to human readable string -* uses retval as errorcode, or, if 0, use GetLastError() -*/ -#if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD error_code) -{ - static char err_string[ERR_BUFFER_SIZE]; - - DWORD size; - int len; - - if (error_code == 0) - error_code = GetLastError(); - - len = sprintf(err_string, "[%u] ", (unsigned int)error_code); - - // Translate codes returned by SetupAPI. The ones we are dealing with are either - // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes. - // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx - switch (error_code & 0xE0000000) { - case 0: - error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified - break; - case 0xE0000000: - error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF); - break; - default: - break; - } - - size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - &err_string[len], ERR_BUFFER_SIZE - len, NULL); - if (size == 0) { - DWORD format_error = GetLastError(); - if (format_error) - snprintf(err_string, ERR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", - (unsigned int)error_code, (unsigned int)format_error); - else - snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code); - } else { - // Remove CRLF from end of message, if present - size_t pos = len + size - 2; - if (err_string[pos] == '\r') - err_string[pos] = '\0'; - } - - return err_string; -} -#endif - -/* Hash table functions - modified From glibc 2.3.2: - [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 - [Knuth] The Art of Computer Programming, part 3 (6.4) */ - -#define HTAB_SIZE 1021UL // *MUST* be a prime number!! - -typedef struct htab_entry { - unsigned long used; - char *str; -} htab_entry; - -static htab_entry *htab_table = NULL; -static usbi_mutex_t htab_mutex = NULL; -static unsigned long htab_filled; - -/* Before using the hash table we must allocate memory for it. - We allocate one element more as the found prime number says. - This is done for more effective indexing as explained in the - comment for the hash function. */ -static bool htab_create(struct libusb_context *ctx) -{ - if (htab_table != NULL) { - usbi_err(ctx, "hash table already allocated"); - return true; - } - - // Create a mutex - usbi_mutex_init(&htab_mutex); - - usbi_dbg("using %lu entries hash table", HTAB_SIZE); - htab_filled = 0; - - // allocate memory and zero out. - htab_table = calloc(HTAB_SIZE + 1, sizeof(htab_entry)); - if (htab_table == NULL) { - usbi_err(ctx, "could not allocate space for hash table"); - return false; - } - - return true; -} - -/* After using the hash table it has to be destroyed. */ -static void htab_destroy(void) -{ - unsigned long i; - - if (htab_table == NULL) - return; - - for (i = 0; i < HTAB_SIZE; i++) - free(htab_table[i].str); - - safe_free(htab_table); - - usbi_mutex_destroy(&htab_mutex); -} - -/* This is the search function. It uses double hashing with open addressing. - We use a trick to speed up the lookup. The table is created with one - more element available. This enables us to use the index zero special. - This index will never be used because we store the first hash index in - the field used where zero means not used. Every other value means used. - The used field can be used as a first fast comparison for equality of - the stored and the parameter value. This helps to prevent unnecessary - expensive calls of strcmp. */ -unsigned long htab_hash(const char *str) -{ - unsigned long hval, hval2; - unsigned long idx; - unsigned long r = 5381; - int c; - const char *sz = str; - - if (str == NULL) - return 0; - - // Compute main hash value (algorithm suggested by Nokia) - while ((c = *sz++) != 0) - r = ((r << 5) + r) + c; - if (r == 0) - ++r; - - // compute table hash: simply take the modulus - hval = r % HTAB_SIZE; - if (hval == 0) - ++hval; - - // Try the first index - idx = hval; - - // Mutually exclusive access (R/W lock would be better) - usbi_mutex_lock(&htab_mutex); - - if (htab_table[idx].used) { - if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) - goto out_unlock; // existing hash - - usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str); - - // Second hash function, as suggested in [Knuth] - hval2 = 1 + hval % (HTAB_SIZE - 2); - - do { - // Because size is prime this guarantees to step through all available indexes - if (idx <= hval2) - idx = HTAB_SIZE + idx - hval2; - else - idx -= hval2; - - // If we visited all entries leave the loop unsuccessfully - if (idx == hval) - break; - - // If entry is found use it. - if ((htab_table[idx].used == hval) && (strcmp(str, htab_table[idx].str) == 0)) - goto out_unlock; - } while (htab_table[idx].used); - } - - // Not found => New entry - - // If the table is full return an error - if (htab_filled >= HTAB_SIZE) { - usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE); - idx = 0; - goto out_unlock; - } - - htab_table[idx].str = _strdup(str); - if (htab_table[idx].str == NULL) { - usbi_err(NULL, "could not duplicate string for hash table"); - idx = 0; - goto out_unlock; - } - - htab_table[idx].used = hval; - ++htab_filled; - -out_unlock: - usbi_mutex_unlock(&htab_mutex); - - return idx; -} - -static int windows_init_dlls(void) -{ - DLL_GET_HANDLE(User32); - DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); - DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); - DLL_LOAD_FUNC_PREFIXED(User32, p, PostThreadMessageA, TRUE); - - return LIBUSB_SUCCESS; -} - -static void windows_exit_dlls(void) -{ - DLL_FREE_HANDLE(User32); -} - -static bool windows_init_clock(struct libusb_context *ctx) -{ - DWORD_PTR affinity, dummy; - HANDLE event = NULL; - LARGE_INTEGER li_frequency; - int i; - - if (QueryPerformanceFrequency(&li_frequency)) { - // Load DLL imports - if (windows_init_dlls() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - return false; - } - - // The hires frequency can go as high as 4 GHz, so we'll use a conversion - // to picoseconds to compute the tv_nsecs part in clock_gettime - hires_frequency = li_frequency.QuadPart; - hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; - usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); - - // Because QueryPerformanceCounter might report different values when - // running on different cores, we create a separate thread for the timer - // calls, which we glue to the first available core always to prevent timing discrepancies. - if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) { - usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0)); - return false; - } - - // The process affinity mask is a bitmask where each set bit represents a core on - // which this process is allowed to run, so we find the first set bit - for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++); - affinity = (DWORD_PTR)(1 << i); - - usbi_dbg("timer thread will run on core #%d", i); - - event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (event == NULL) { - usbi_err(ctx, "could not create event: %s", windows_error_str(0)); - return false; - } - - timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event, - 0, (unsigned int *)&timer_thread_id); - if (timer_thread == NULL) { - usbi_err(ctx, "unable to create timer thread - aborting"); - CloseHandle(event); - return false; - } - - if (!SetThreadAffinityMask(timer_thread, affinity)) - usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise"); - - // Wait for timer thread to init before continuing. - if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failed to wait for timer thread to become ready - aborting"); - CloseHandle(event); - return false; - } - - CloseHandle(event); - } else { - usbi_dbg("no hires timer available on this platform"); - hires_frequency = 0; - hires_ticks_to_ps = UINT64_C(0); - } - - return true; -} - -void windows_destroy_clock(void) -{ - if (timer_thread) { - // actually the signal to quit the thread. - if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) - || (WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) { - usbi_dbg("could not wait for timer thread to quit"); - TerminateThread(timer_thread, 1); - // shouldn't happen, but we're destroying - // all objects it might have held anyway. - } - CloseHandle(timer_thread); - timer_thread = NULL; - timer_thread_id = 0; - } -} - -/* -* Monotonic and real time functions -*/ -static unsigned __stdcall windows_clock_gettime_threaded(void *param) -{ - struct timer_request *request; - LARGE_INTEGER hires_counter; - MSG msg; - - // The following call will create this thread's message queue - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx - pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); - - // Signal windows_init_clock() that we're ready to service requests - if (!SetEvent((HANDLE)param)) - usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0)); - param = NULL; - - // Main loop - wait for requests - while (1) { - if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) { - usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0)); - return 1; - } - - switch (msg.message) { - case WM_TIMER_REQUEST: - // Requests to this thread are for hires always - // Microsoft says that this function always succeeds on XP and later - // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx - request = (struct timer_request *)msg.lParam; - QueryPerformanceCounter(&hires_counter); - request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency); - request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps); - if (!SetEvent(request->event)) - usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0)); - break; - case WM_TIMER_EXIT: - usbi_dbg("timer thread quitting"); - return 0; - } - } -} - -int windows_clock_gettime(int clk_id, struct timespec *tp) -{ - struct timer_request request; -#if !defined(_MSC_VER) || (_MSC_VER < 1900) - FILETIME filetime; - ULARGE_INTEGER rtime; -#endif - DWORD r; - - switch (clk_id) { - case USBI_CLOCK_MONOTONIC: - if (timer_thread) { - request.tp = tp; - request.event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (request.event == NULL) - return LIBUSB_ERROR_NO_MEM; - - if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) { - usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0)); - CloseHandle(request.event); - return LIBUSB_ERROR_OTHER; - } - - do { - r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS); - if (r == WAIT_TIMEOUT) - usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); - else if (r == WAIT_FAILED) - usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0)); - } while (r == WAIT_TIMEOUT); - CloseHandle(request.event); - - if (r == WAIT_OBJECT_0) - return LIBUSB_SUCCESS; - else - return LIBUSB_ERROR_OTHER; - } - // Fall through and return real-time if monotonic was not detected @ timer init - case USBI_CLOCK_REALTIME: -#if defined(_MSC_VER) && (_MSC_VER >= 1900) - timespec_get(tp, TIME_UTC); -#else - // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx - // with a predef epoch time to have an epoch that starts at 1970.01.01 00:00 - // Note however that our resolution is bounded by the Windows system time - // functions and is at best of the order of 1 ms (or, usually, worse) - GetSystemTimeAsFileTime(&filetime); - rtime.LowPart = filetime.dwLowDateTime; - rtime.HighPart = filetime.dwHighDateTime; - rtime.QuadPart -= EPOCH_TIME; - tp->tv_sec = (long)(rtime.QuadPart / 10000000); - tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100); -#endif - return LIBUSB_SUCCESS; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) -{ - int status, istatus; - - usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size); - - switch (io_result) { - case NO_ERROR: - status = windows_copy_transfer_data(itransfer, io_size); - break; - case ERROR_GEN_FAILURE: - usbi_dbg("detected endpoint stall"); - status = LIBUSB_TRANSFER_STALL; - break; - case ERROR_SEM_TIMEOUT: - usbi_dbg("detected semaphore timeout"); - status = LIBUSB_TRANSFER_TIMED_OUT; - break; - case ERROR_OPERATION_ABORTED: - istatus = windows_copy_transfer_data(itransfer, io_size); - if (istatus != LIBUSB_TRANSFER_COMPLETED) - usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); - - usbi_dbg("detected operation aborted"); - status = LIBUSB_TRANSFER_CANCELLED; - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); - status = LIBUSB_TRANSFER_ERROR; - break; - } - windows_clear_transfer_priv(itransfer); // Cancel polling - if (status == LIBUSB_TRANSFER_CANCELLED) - usbi_handle_transfer_cancellation(itransfer); - else - usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); -} - -void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - windows_transfer_callback(itransfer, io_result, io_size); - break; - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); - break; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - } -} - -int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) -{ - POLL_NFDS_TYPE i; - bool found = false; - struct usbi_transfer *transfer; - struct winfd *pollable_fd = NULL; - DWORD io_size, io_result; - int r = LIBUSB_SUCCESS; - - usbi_mutex_lock(&ctx->open_devs_lock); - for (i = 0; i < nfds && num_ready > 0; i++) { - - usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); - - if (!fds[i].revents) - continue; - - num_ready--; - - // Because a Windows OVERLAPPED is used for poll emulation, - // a pollable fd is created and stored with each transfer - usbi_mutex_lock(&ctx->flying_transfers_lock); - found = false; - list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { - pollable_fd = windows_get_fd(transfer); - if (pollable_fd->fd == fds[i].fd) { - found = true; - break; - } - } - usbi_mutex_unlock(&ctx->flying_transfers_lock); - - if (found) { - windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size); - - usbi_remove_pollfd(ctx, pollable_fd->fd); - // let handle_callback free the event using the transfer wfd - // If you don't use the transfer wfd, you run a risk of trying to free a - // newly allocated wfd that took the place of the one from the transfer. - windows_handle_callback(transfer, io_result, io_size); - } else { - usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); - r = LIBUSB_ERROR_NOT_FOUND; - break; - } - } - usbi_mutex_unlock(&ctx->open_devs_lock); - - return r; -} - -int windows_common_init(struct libusb_context *ctx) -{ - if (!windows_init_clock(ctx)) - goto error_roll_back; - - if (!htab_create(ctx)) - goto error_roll_back; - - return LIBUSB_SUCCESS; - -error_roll_back: - windows_common_exit(); - return LIBUSB_ERROR_NO_MEM; -} - -void windows_common_exit(void) -{ - htab_destroy(); - windows_destroy_clock(); - windows_exit_dlls(); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_nt_common.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_nt_common.h deleted file mode 100644 index 52ea8708b04..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_nt_common.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Windows backend common header for libusb 1.0 - * - * This file brings together header code common between - * the desktop Windows backends. - * Copyright © 2012-2013 RealVNC Ltd. - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -// Missing from MinGW -#if !defined(FACILITY_SETUPAPI) -#define FACILITY_SETUPAPI 15 -#endif - -typedef struct USB_CONFIGURATION_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - USHORT wTotalLength; - UCHAR bNumInterfaces; - UCHAR bConfigurationValue; - UCHAR iConfiguration; - UCHAR bmAttributes; - UCHAR MaxPower; -} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; - -typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; - -int windows_common_init(struct libusb_context *ctx); -void windows_common_exit(void); - -unsigned long htab_hash(const char *str); -int windows_clock_gettime(int clk_id, struct timespec *tp); - -void windows_clear_transfer_priv(struct usbi_transfer *itransfer); -int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size); -struct winfd *windows_get_fd(struct usbi_transfer *transfer); -void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size); - -void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size); -int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); - -#if defined(ENABLE_LOGGING) -const char *windows_error_str(DWORD error_code); -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_usbdk.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_usbdk.c deleted file mode 100644 index 7cc5793872a..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_usbdk.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * windows UsbDk backend for libusb 1.0 - * Copyright © 2014 Red Hat, Inc. - - * Authors: - * Dmitry Fleytman - * Pavel Gurvich - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#if defined(USE_USBDK) - -#include -#include -#include - -#include "libusbi.h" -#include "windows_common.h" -#include "windows_nt_common.h" - -#define ULONG64 uint64_t -#define PVOID64 uint64_t - -typedef CONST WCHAR *PCWCHAR; -#define wcsncpy_s wcsncpy - -#include "windows_usbdk.h" - -#if !defined(STATUS_SUCCESS) -typedef LONG NTSTATUS; -#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) -#endif - -#if !defined(STATUS_CANCELLED) -#define STATUS_CANCELLED ((NTSTATUS)0xC0000120L) -#endif - -#if !defined(STATUS_REQUEST_CANCELED) -#define STATUS_REQUEST_CANCELED ((NTSTATUS)0xC0000703L) -#endif - -#if !defined(USBD_SUCCESS) -typedef int32_t USBD_STATUS; -#define USBD_SUCCESS(Status) ((USBD_STATUS) (Status) >= 0) -#define USBD_PENDING(Status) ((ULONG) (Status) >> 30 == 1) -#define USBD_ERROR(Status) ((USBD_STATUS) (Status) < 0) -#define USBD_STATUS_STALL_PID ((USBD_STATUS) 0xc0000004) -#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS) 0xc0000030) -#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS) 0xc0000a00) -#define USBD_STATUS_TIMEOUT ((USBD_STATUS) 0xc0006000) -#define USBD_STATUS_CANCELED ((USBD_STATUS) 0xc0010000) -#endif - -static int concurrent_usage = -1; - -struct usbdk_device_priv { - USB_DK_DEVICE_INFO info; - PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors; - HANDLE redirector_handle; - uint8_t active_configuration; -}; - -struct usbdk_transfer_priv { - USB_DK_TRANSFER_REQUEST request; - struct winfd pollable_fd; - PULONG64 IsochronousPacketsArray; - PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray; -}; - -static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device *dev) -{ - return (struct usbdk_device_priv *)dev->os_priv; -} - -static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer) -{ - return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer); -} - -static struct { - HMODULE module; - - USBDK_GET_DEVICES_LIST GetDevicesList; - USBDK_RELEASE_DEVICES_LIST ReleaseDevicesList; - USBDK_START_REDIRECT StartRedirect; - USBDK_STOP_REDIRECT StopRedirect; - USBDK_GET_CONFIGURATION_DESCRIPTOR GetConfigurationDescriptor; - USBDK_RELEASE_CONFIGURATION_DESCRIPTOR ReleaseConfigurationDescriptor; - USBDK_READ_PIPE ReadPipe; - USBDK_WRITE_PIPE WritePipe; - USBDK_ABORT_PIPE AbortPipe; - USBDK_RESET_PIPE ResetPipe; - USBDK_SET_ALTSETTING SetAltsetting; - USBDK_RESET_DEVICE ResetDevice; - USBDK_GET_REDIRECTOR_SYSTEM_HANDLE GetRedirectorSystemHandle; -} usbdk_helper; - -static FARPROC get_usbdk_proc_addr(struct libusb_context *ctx, LPCSTR api_name) -{ - FARPROC api_ptr = GetProcAddress(usbdk_helper.module, api_name); - - if (api_ptr == NULL) - usbi_err(ctx, "UsbDkHelper API %s not found, error %d", api_name, GetLastError()); - - return api_ptr; -} - -static void unload_usbdk_helper_dll(void) -{ - if (usbdk_helper.module != NULL) { - FreeLibrary(usbdk_helper.module); - usbdk_helper.module = NULL; - } -} - -static int load_usbdk_helper_dll(struct libusb_context *ctx) -{ - usbdk_helper.module = LoadLibraryA("UsbDkHelper"); - if (usbdk_helper.module == NULL) { - usbi_err(ctx, "Failed to load UsbDkHelper.dll, error %d", GetLastError()); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbdk_helper.GetDevicesList = (USBDK_GET_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_GetDevicesList"); - if (usbdk_helper.GetDevicesList == NULL) - goto error_unload; - - usbdk_helper.ReleaseDevicesList = (USBDK_RELEASE_DEVICES_LIST)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseDevicesList"); - if (usbdk_helper.ReleaseDevicesList == NULL) - goto error_unload; - - usbdk_helper.StartRedirect = (USBDK_START_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StartRedirect"); - if (usbdk_helper.StartRedirect == NULL) - goto error_unload; - - usbdk_helper.StopRedirect = (USBDK_STOP_REDIRECT)get_usbdk_proc_addr(ctx, "UsbDk_StopRedirect"); - if (usbdk_helper.StopRedirect == NULL) - goto error_unload; - - usbdk_helper.GetConfigurationDescriptor = (USBDK_GET_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_GetConfigurationDescriptor"); - if (usbdk_helper.GetConfigurationDescriptor == NULL) - goto error_unload; - - usbdk_helper.ReleaseConfigurationDescriptor = (USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)get_usbdk_proc_addr(ctx, "UsbDk_ReleaseConfigurationDescriptor"); - if (usbdk_helper.ReleaseConfigurationDescriptor == NULL) - goto error_unload; - - usbdk_helper.ReadPipe = (USBDK_READ_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ReadPipe"); - if (usbdk_helper.ReadPipe == NULL) - goto error_unload; - - usbdk_helper.WritePipe = (USBDK_WRITE_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_WritePipe"); - if (usbdk_helper.WritePipe == NULL) - goto error_unload; - - usbdk_helper.AbortPipe = (USBDK_ABORT_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_AbortPipe"); - if (usbdk_helper.AbortPipe == NULL) - goto error_unload; - - usbdk_helper.ResetPipe = (USBDK_RESET_PIPE)get_usbdk_proc_addr(ctx, "UsbDk_ResetPipe"); - if (usbdk_helper.ResetPipe == NULL) - goto error_unload; - - usbdk_helper.SetAltsetting = (USBDK_SET_ALTSETTING)get_usbdk_proc_addr(ctx, "UsbDk_SetAltsetting"); - if (usbdk_helper.SetAltsetting == NULL) - goto error_unload; - - usbdk_helper.ResetDevice = (USBDK_RESET_DEVICE)get_usbdk_proc_addr(ctx, "UsbDk_ResetDevice"); - if (usbdk_helper.ResetDevice == NULL) - goto error_unload; - - usbdk_helper.GetRedirectorSystemHandle = (USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)get_usbdk_proc_addr(ctx, "UsbDk_GetRedirectorSystemHandle"); - if (usbdk_helper.GetRedirectorSystemHandle == NULL) - goto error_unload; - - return LIBUSB_SUCCESS; - -error_unload: - FreeLibrary(usbdk_helper.module); - usbdk_helper.module = NULL; - return LIBUSB_ERROR_NOT_FOUND; -} - -static int usbdk_init(struct libusb_context *ctx) -{ - int r; - - if (++concurrent_usage == 0) { // First init? - r = load_usbdk_helper_dll(ctx); - if (r) - goto init_exit; - - init_polling(); - - r = windows_common_init(ctx); - if (r) - goto init_exit; - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - exit_polling(); - windows_common_exit(); - unload_usbdk_helper_dll(); - } - - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. - - return r; -} - -static int usbdk_get_session_id_for_device(struct libusb_context *ctx, - PUSB_DK_DEVICE_ID id, unsigned long *session_id) -{ - char dev_identity[ARRAYSIZE(id->DeviceID) + ARRAYSIZE(id->InstanceID)]; - - if (sprintf(dev_identity, "%S%S", id->DeviceID, id->InstanceID) == -1) { - usbi_warn(ctx, "cannot form device identity", id->DeviceID); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - *session_id = htab_hash(dev_identity); - - return LIBUSB_SUCCESS; -} - -static void usbdk_release_config_descriptors(struct usbdk_device_priv *p, uint8_t count) -{ - uint8_t i; - - for (i = 0; i < count; i++) - usbdk_helper.ReleaseConfigurationDescriptor(p->config_descriptors[i]); - - free(p->config_descriptors); - p->config_descriptors = NULL; -} - -static int usbdk_cache_config_descriptors(struct libusb_context *ctx, - struct usbdk_device_priv *p, PUSB_DK_DEVICE_INFO info) -{ - uint8_t i; - USB_DK_CONFIG_DESCRIPTOR_REQUEST Request; - Request.ID = info->ID; - - p->config_descriptors = calloc(info->DeviceDescriptor.bNumConfigurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR)); - if (p->config_descriptors == NULL) { - usbi_err(ctx, "failed to allocate configuration descriptors holder"); - return LIBUSB_ERROR_NO_MEM; - } - - for (i = 0; i < info->DeviceDescriptor.bNumConfigurations; i++) { - ULONG Length; - - Request.Index = i; - if (!usbdk_helper.GetConfigurationDescriptor(&Request, &p->config_descriptors[i], &Length)) { - usbi_err(ctx, "failed to retrieve configuration descriptors"); - usbdk_release_config_descriptors(p, i); - return LIBUSB_ERROR_OTHER; - } - } - - return LIBUSB_SUCCESS; -} - -static inline int usbdk_device_priv_init(struct libusb_context *ctx, struct libusb_device *dev, PUSB_DK_DEVICE_INFO info) -{ - struct usbdk_device_priv *p = _usbdk_device_priv(dev); - - p->info = *info; - p->active_configuration = 0; - - return usbdk_cache_config_descriptors(ctx, p, info); -} - -static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info) -{ - dev->bus_number = (uint8_t)info->FilterID; - dev->port_number = (uint8_t)info->Port; - dev->parent_dev = NULL; - - //Addresses in libusb are 1-based - dev->device_address = (uint8_t)(info->Port + 1); - - dev->num_configurations = info->DeviceDescriptor.bNumConfigurations; - dev->device_descriptor = info->DeviceDescriptor; - - switch (info->Speed) { - case LowSpeed: - dev->speed = LIBUSB_SPEED_LOW; - break; - case FullSpeed: - dev->speed = LIBUSB_SPEED_FULL; - break; - case HighSpeed: - dev->speed = LIBUSB_SPEED_HIGH; - break; - case SuperSpeed: - dev->speed = LIBUSB_SPEED_SUPER; - break; - case NoSpeed: - default: - dev->speed = LIBUSB_SPEED_UNKNOWN; - break; - } -} - -static int usbdk_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) -{ - int r = LIBUSB_SUCCESS; - ULONG i; - struct discovered_devs *discdevs = NULL; - ULONG dev_number; - PUSB_DK_DEVICE_INFO devices; - - if(!usbdk_helper.GetDevicesList(&devices, &dev_number)) - return LIBUSB_ERROR_OTHER; - - for (i = 0; i < dev_number; i++) { - unsigned long session_id; - struct libusb_device *dev = NULL; - - if (usbdk_get_session_id_for_device(ctx, &devices[i].ID, &session_id)) - continue; - - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) { - usbi_err(ctx, "failed to allocate a new device structure"); - continue; - } - - usbdk_device_init(dev, &devices[i]); - if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) { - libusb_unref_device(dev); - continue; - } - } - - discdevs = discovered_devs_append(*_discdevs, dev); - libusb_unref_device(dev); - if (!discdevs) { - usbi_err(ctx, "cannot append new device to list"); - r = LIBUSB_ERROR_NO_MEM; - goto func_exit; - } - - *_discdevs = discdevs; - } - -func_exit: - usbdk_helper.ReleaseDevicesList(devices); - return r; -} - -static void usbdk_exit(void) -{ - if (--concurrent_usage < 0) { - windows_common_exit(); - exit_polling(); - unload_usbdk_helper_dll(); - } -} - -static int usbdk_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - - memcpy(buffer, &priv->info.DeviceDescriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; - - return LIBUSB_SUCCESS; -} - -static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - size_t size; - - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_INVALID_PARAM; - - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index]; - - size = min(config_header->wTotalLength, len); - memcpy(buffer, config_header, size); - *host_endian = 0; - - return (int)size; -} - -static inline int usbdk_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) -{ - return usbdk_get_config_descriptor(dev, _usbdk_device_priv(dev)->active_configuration, - buffer, len, host_endian); -} - -static int usbdk_open(struct libusb_device_handle *dev_handle) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID); - if (priv->redirector_handle == INVALID_HANDLE_VALUE) { - usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed"); - return LIBUSB_ERROR_OTHER; - } - - return LIBUSB_SUCCESS; -} - -static void usbdk_close(struct libusb_device_handle *dev_handle) -{ - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.StopRedirect(priv->redirector_handle)) { - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - usbi_err(ctx, "Redirector shutdown failed"); - } -} - -static int usbdk_get_configuration(struct libusb_device_handle *dev_handle, int *config) -{ - *config = _usbdk_device_priv(dev_handle->dev)->active_configuration; - - return LIBUSB_SUCCESS; -} - -static int usbdk_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - UNUSED(dev_handle); - UNUSED(config); - return LIBUSB_SUCCESS; -} - -static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_SUCCESS; -} - -static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) { - usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_SUCCESS; -} - -static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) { - usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_reset_device(struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev); - - if (!usbdk_helper.ResetDevice(priv->redirector_handle)) { - usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int usbdk_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int usbdk_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - UNUSED(dev_handle); - UNUSED(iface); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static void usbdk_destroy_device(struct libusb_device *dev) -{ - struct usbdk_device_priv* p = _usbdk_device_priv(dev); - - if (p->config_descriptors != NULL) - usbdk_release_config_descriptors(p, p->info.DeviceDescriptor.bNumConfigurations); -} - -void windows_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - usbi_free_fd(&transfer_priv->pollable_fd); - - if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - safe_free(transfer_priv->IsochronousPacketsArray); - safe_free(transfer_priv->IsochronousResultsArray); - } -} - -static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - ULONG Length; - TransferResult transResult; - HANDLE sysHandle; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.TransferType = ControlTransferType; - transfer_priv->pollable_fd = INVALID_WINFD; - Length = (ULONG)transfer->length; - - if (IS_XFERIN(transfer)) - transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - else - transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - - switch (transResult) { - case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)Length; - break; - case TransferSuccessAsync: - break; - case TransferFailure: - usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - - return LIBUSB_SUCCESS; -} - -static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - TransferResult transferRes; - HANDLE sysHandle; - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.EndpointAddress = transfer->endpoint; - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_BULK: - transfer_priv->request.TransferType = BulkTransferType; - break; - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - transfer_priv->request.TransferType = IntertuptTransferType; - break; - default: - usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); - return LIBUSB_ERROR_INVALID_PARAM; - } - - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - - switch (transferRes) { - case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - break; - case TransferSuccessAsync: - break; - case TransferFailure: - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); - - return LIBUSB_SUCCESS; -} - -static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct winfd wfd; - TransferResult transferRes; - int i; - HANDLE sysHandle; - - transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; - transfer_priv->request.BufferLength = transfer->length; - transfer_priv->request.EndpointAddress = transfer->endpoint; - transfer_priv->request.TransferType = IsochronousTransferType; - transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; - transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); - transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; - if (!transfer_priv->IsochronousPacketsArray) { - usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); - transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; - if (!transfer_priv->IsochronousResultsArray) { - usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); - free(transfer_priv->IsochronousPacketsArray); - return LIBUSB_ERROR_IO; - } - - for (i = 0; i < transfer->num_iso_packets; i++) - transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; - - transfer_priv->pollable_fd = INVALID_WINFD; - - sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); - - wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) { - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); - return LIBUSB_ERROR_NO_MEM; - } - - if (IS_XFERIN(transfer)) - transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - else - transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); - - switch (transferRes) { - case TransferSuccess: - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - break; - case TransferSuccessAsync: - break; - case TransferFailure: - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - free(transfer_priv->IsochronousPacketsArray); - free(transfer_priv->IsochronousResultsArray); - return LIBUSB_ERROR_IO; - } - - transfer_priv->pollable_fd = wfd; - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); - - return LIBUSB_SUCCESS; -} - -static int usbdk_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return usbdk_do_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk - else - return usbdk_do_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_do_iso_transfer(itransfer); - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int usbdk_abort_transfers(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); - - if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - // Control transfers cancelled by IoCancelXXX() API - // No special treatment needed - return LIBUSB_SUCCESS; - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return usbdk_abort_transfers(itransfer); - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) -{ - itransfer->transferred += io_size; - return LIBUSB_TRANSFER_COMPLETED; -} - -struct winfd *windows_get_fd(struct usbi_transfer *transfer) -{ - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); - return &transfer_priv->pollable_fd; -} - -static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus) -{ - if (USBD_SUCCESS(UsbdStatus)) - return NO_ERROR; - - switch (UsbdStatus) { - case USBD_STATUS_STALL_PID: - case USBD_STATUS_ENDPOINT_HALTED: - case USBD_STATUS_BAD_START_FRAME: - return ERROR_GEN_FAILURE; - case USBD_STATUS_TIMEOUT: - return ERROR_SEM_TIMEOUT; - case USBD_STATUS_CANCELED: - return ERROR_OPERATION_ABORTED; - default: - return ERROR_FUNCTION_FAILED; - } -} - -void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) -{ - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first - || GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped - struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); - struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); - - if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { - int i; - for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { - struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; - - switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { - case STATUS_SUCCESS: - case STATUS_CANCELLED: - case STATUS_REQUEST_CANCELED: - lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS - break; - default: - lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; - break; - } - - lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength; - } - } - - *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; - *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); - } - else { - *io_result = GetLastError(); - } -} - -static int usbdk_clock_gettime(int clk_id, struct timespec *tp) -{ - return windows_clock_gettime(clk_id, tp); -} - -const struct usbi_os_backend usbdk_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, - usbdk_init, - usbdk_exit, - - usbdk_get_device_list, - NULL, - usbdk_open, - usbdk_close, - - usbdk_get_device_descriptor, - usbdk_get_active_config_descriptor, - usbdk_get_config_descriptor, - NULL, - - usbdk_get_configuration, - usbdk_set_configuration, - usbdk_claim_interface, - usbdk_release_interface, - - usbdk_set_interface_altsetting, - usbdk_clear_halt, - usbdk_reset_device, - - NULL, - NULL, - - NULL, // dev_mem_alloc() - NULL, // dev_mem_free() - - usbdk_kernel_driver_active, - usbdk_detach_kernel_driver, - usbdk_attach_kernel_driver, - - usbdk_destroy_device, - - usbdk_submit_transfer, - usbdk_cancel_transfer, - windows_clear_transfer_priv, - - windows_handle_events, - NULL, - - usbdk_clock_gettime, -#if defined(USBI_TIMERFD_AVAILABLE) - NULL, -#endif - sizeof(struct usbdk_device_priv), - 0, - sizeof(struct usbdk_transfer_priv), -}; - -#endif /* USE_USBDK */ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_usbdk.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_usbdk.h deleted file mode 100644 index 04a9787f2d6..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_usbdk.h +++ /dev/null @@ -1,146 +0,0 @@ -/* -* windows UsbDk backend for libusb 1.0 -* Copyright © 2014 Red Hat, Inc. - -* Authors: -* Dmitry Fleytman -* Pavel Gurvich -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#pragma once - -typedef struct tag_USB_DK_DEVICE_ID { - WCHAR DeviceID[MAX_DEVICE_ID_LEN]; - WCHAR InstanceID[MAX_DEVICE_ID_LEN]; -} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID; - -static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID) -{ - wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN); - wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN); -} - -typedef struct tag_USB_DK_DEVICE_INFO { - USB_DK_DEVICE_ID ID; - ULONG64 FilterID; - ULONG64 Port; - ULONG64 Speed; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; -} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO; - -typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST { - USB_DK_DEVICE_ID ID; - ULONG64 Index; -} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST; - -typedef struct tag_USB_DK_ISO_TRANSFER_RESULT { - ULONG64 ActualLength; - ULONG64 TransferResult; -} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT; - -typedef struct tag_USB_DK_GEN_TRANSFER_RESULT { - ULONG64 BytesTransferred; - ULONG64 UsbdStatus; // USBD_STATUS code -} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT; - -typedef struct tag_USB_DK_TRANSFER_RESULT { - USB_DK_GEN_TRANSFER_RESULT GenResult; - PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT -} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT; - -typedef struct tag_USB_DK_TRANSFER_REQUEST { - ULONG64 EndpointAddress; - PVOID64 Buffer; - ULONG64 BufferLength; - ULONG64 TransferType; - ULONG64 IsochronousPacketsArraySize; - PVOID64 IsochronousPacketsArray; - - USB_DK_TRANSFER_RESULT Result; -} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST; - -typedef enum { - TransferFailure = 0, - TransferSuccess, - TransferSuccessAsync -} TransferResult; - -typedef enum { - NoSpeed = 0, - LowSpeed, - FullSpeed, - HighSpeed, - SuperSpeed -} USB_DK_DEVICE_SPEED; - -typedef enum { - ControlTransferType, - BulkTransferType, - IntertuptTransferType, - IsochronousTransferType -} USB_DK_TRANSFER_TYPE; - -typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)( - PUSB_DK_DEVICE_INFO *DeviceInfo, - PULONG DeviceNumber -); -typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)( - PUSB_DK_DEVICE_INFO DeviceInfo -); -typedef HANDLE (__cdecl *USBDK_START_REDIRECT)( - PUSB_DK_DEVICE_ID DeviceId -); -typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)( - HANDLE DeviceHandle -); -typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)( - PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request, - PUSB_CONFIGURATION_DESCRIPTOR *Descriptor, - PULONG Length -); -typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)( - PUSB_CONFIGURATION_DESCRIPTOR Descriptor -); -typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)( - HANDLE DeviceHandle, - PUSB_DK_TRANSFER_REQUEST Request, - LPOVERLAPPED lpOverlapped -); -typedef TransferResult (__cdecl *USBDK_READ_PIPE)( - HANDLE DeviceHandle, - PUSB_DK_TRANSFER_REQUEST Request, - LPOVERLAPPED lpOverlapped -); -typedef BOOL (__cdecl *USBDK_ABORT_PIPE)( - HANDLE DeviceHandle, - ULONG64 PipeAddress -); -typedef BOOL (__cdecl *USBDK_RESET_PIPE)( - HANDLE DeviceHandle, - ULONG64 PipeAddress -); -typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)( - HANDLE DeviceHandle, - ULONG64 InterfaceIdx, - ULONG64 AltSettingIdx -); -typedef BOOL (__cdecl *USBDK_RESET_DEVICE)( - HANDLE DeviceHandle -); -typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)( - HANDLE DeviceHandle -); diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_winusb.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_winusb.c deleted file mode 100644 index 0dce0ea6cb6..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_winusb.c +++ /dev/null @@ -1,4290 +0,0 @@ -/* - * windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * HID Reports IOCTLs inspired from HIDAPI by Alan Ott, Signal 11 Software - * Hash table functions adapted from glibc, by Ulrich Drepper et al. - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#if !defined(USE_USBDK) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libusbi.h" -#include "poll_windows.h" -#include "windows_winusb.h" - -#define HANDLE_VALID(h) (((h) != 0) && ((h) != INVALID_HANDLE_VALUE)) - -// The 2 macros below are used in conjunction with safe loops. -#define LOOP_CHECK(fcall) \ - { \ - r = fcall; \ - if (r != LIBUSB_SUCCESS) \ - continue; \ - } -#define LOOP_BREAK(err) \ - { \ - r = err; \ - continue; \ - } - -// WinUSB-like API prototypes -static int winusbx_init(int sub_api, struct libusb_context *ctx); -static int winusbx_exit(int sub_api); -static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle); -static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle); -static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer); -static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -// HID API prototypes -static int hid_init(int sub_api, struct libusb_context *ctx); -static int hid_exit(int sub_api); -static int hid_open(int sub_api, struct libusb_device_handle *dev_handle); -static void hid_close(int sub_api, struct libusb_device_handle *dev_handle); -static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -// Composite API prototypes -static int composite_init(int sub_api, struct libusb_context *ctx); -static int composite_exit(int sub_api); -static int composite_open(int sub_api, struct libusb_device_handle *dev_handle); -static void composite_close(int sub_api, struct libusb_device_handle *dev_handle); -static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); -static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface); -static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer); -static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); -static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer); -static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer); -static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle); -static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); - - -// Global variables -int windows_version = WINDOWS_UNDEFINED; -static char windows_version_str[128] = "Undefined"; -// Concurrency -static int concurrent_usage = -1; -static usbi_mutex_t autoclaim_lock; -// API globals -#define CHECK_WINUSBX_AVAILABLE(sub_api) \ - do { \ - if (sub_api == SUB_API_NOTSET) \ - sub_api = priv->sub_api; \ - if (!WinUSBX[sub_api].initialized) \ - return LIBUSB_ERROR_ACCESS; \ - } while(0) - -static HMODULE WinUSBX_handle = NULL; -static struct winusb_interface WinUSBX[SUB_API_MAX]; -static const char *sub_api_name[SUB_API_MAX] = WINUSBX_DRV_NAMES; - -static bool api_hid_available = false; -#define CHECK_HID_AVAILABLE \ - do { \ - if (!api_hid_available) \ - return LIBUSB_ERROR_ACCESS; \ - } while (0) - -static inline BOOLEAN guid_eq(const GUID *guid1, const GUID *guid2) -{ - if ((guid1 != NULL) && (guid2 != NULL)) - return (memcmp(guid1, guid2, sizeof(GUID)) == 0); - - return false; -} - -#if defined(ENABLE_LOGGING) -static char *guid_to_string(const GUID *guid) -{ - static char guid_string[MAX_GUID_STRING_LENGTH]; - - if (guid == NULL) - return NULL; - - sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - (unsigned int)guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); - - return guid_string; -} -#endif - -/* - * Sanitize Microsoft's paths: convert to uppercase, add prefix and fix backslashes. - * Return an allocated sanitized string or NULL on error. - */ -static char *sanitize_path(const char *path) -{ - const char root_prefix[] = { '\\', '\\', '.', '\\' }; - size_t j, size; - char *ret_path; - size_t add_root = 0; - - if (path == NULL) - return NULL; - - size = strlen(path) + 1; - - // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes. - if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) - || ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) { - add_root = sizeof(root_prefix); - size += add_root; - } - - ret_path = malloc(size); - if (ret_path == NULL) - return NULL; - - strcpy(&ret_path[add_root], path); - - // Ensure consistency with root prefix - memcpy(ret_path, root_prefix, sizeof(root_prefix)); - - // Same goes for '\' and '#' after the root prefix. Ensure '#' is used - for (j = sizeof(root_prefix); j < size; j++) { - ret_path[j] = (char)toupper((int)ret_path[j]); // Fix case too - if (ret_path[j] == '\\') - ret_path[j] = '#'; - } - - return ret_path; -} - -/* - * Cfgmgr32, OLE32 and SetupAPI DLL functions - */ -static int init_dlls(void) -{ - DLL_GET_HANDLE(Cfgmgr32); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Sibling, TRUE); - DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Device_IDA, TRUE); - - // Prefixed to avoid conflict with header files - DLL_GET_HANDLE(AdvAPI32); - DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE); - DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE); - - DLL_GET_HANDLE(Kernel32); - DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); - - DLL_GET_HANDLE(OLE32); - DLL_LOAD_FUNC_PREFIXED(OLE32, p, CLSIDFromString, TRUE); - - DLL_GET_HANDLE(SetupAPI); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE); - DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE); - - return LIBUSB_SUCCESS; -} - -static void exit_dlls(void) -{ - DLL_FREE_HANDLE(Cfgmgr32); - DLL_FREE_HANDLE(AdvAPI32); - DLL_FREE_HANDLE(Kernel32); - DLL_FREE_HANDLE(OLE32); - DLL_FREE_HANDLE(SetupAPI); -} - -/* - * enumerate interfaces for the whole USB class - * - * Parameters: - * dev_info: a pointer to a dev_info list - * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * usb_class: the generic USB class for which to retrieve interface details - * index: zero based index of the interface in the device info list - * - * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA - * structure returned and call this function repeatedly using the same guid (with an - * incremented index starting at zero) until all interfaces have been returned. - */ -static bool get_devinfo_data(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const char *usb_class, unsigned _index) -{ - if (_index <= 0) { - *dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); - if (*dev_info == INVALID_HANDLE_VALUE) - return false; - } - - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return false; - } - return true; -} - -/* - * enumerate interfaces for a specific GUID - * - * Parameters: - * dev_info: a pointer to a dev_info list - * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed) - * guid: the GUID for which to retrieve interface details - * index: zero based index of the interface in the device info list - * - * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA - * structure returned and call this function repeatedly using the same guid (with an - * incremented index starting at zero) until all interfaces have been returned. - */ -static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index) -{ - SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; - DWORD size; - - if (_index <= 0) - *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - - if (dev_info_data != NULL) { - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - } - - dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain interface data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - - // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { - // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", - _index, windows_error_str(0)); - goto err_exit; - } - } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); - goto err_exit; - } - - dev_interface_details = calloc(1, size); - if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for index %u.", _index); - goto err_exit; - } - - dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, - dev_interface_details, size, &size, NULL)) { - usbi_err(ctx, "could not access interface data (actual) for index %u: %s", - _index, windows_error_str(0)); - } - - return dev_interface_details; - -err_exit: - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; -} - -/* For libusb0 filter */ -static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct libusb_context *ctx, - HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, const GUID *guid, unsigned _index, char *filter_path) -{ - SP_DEVICE_INTERFACE_DATA dev_interface_data; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details; - DWORD size; - - if (_index <= 0) - *dev_info = pSetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); - - if (dev_info_data != NULL) { - dev_info_data->cbSize = sizeof(SP_DEVINFO_DATA); - if (!pSetupDiEnumDeviceInfo(*dev_info, _index, dev_info_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain device info data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - } - - dev_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - if (!pSetupDiEnumDeviceInterfaces(*dev_info, NULL, guid, _index, &dev_interface_data)) { - if (GetLastError() != ERROR_NO_MORE_ITEMS) - usbi_err(ctx, "Could not obtain interface data for index %u: %s", - _index, windows_error_str(0)); - - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; - } - - // Read interface data (dummy + actual) to access the device path - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, NULL, 0, &size, NULL)) { - // The dummy call should fail with ERROR_INSUFFICIENT_BUFFER - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - usbi_err(ctx, "could not access interface data (dummy) for index %u: %s", - _index, windows_error_str(0)); - goto err_exit; - } - } else { - usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong."); - goto err_exit; - } - - dev_interface_details = calloc(1, size); - if (dev_interface_details == NULL) { - usbi_err(ctx, "could not allocate interface data for index %u.", _index); - goto err_exit; - } - - dev_interface_details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if (!pSetupDiGetDeviceInterfaceDetailA(*dev_info, &dev_interface_data, dev_interface_details, size, &size, NULL)) - usbi_err(ctx, "could not access interface data (actual) for index %u: %s", - _index, windows_error_str(0)); - - // [trobinso] lookup the libusb0 symbolic index. - if (dev_interface_details) { - HKEY hkey_device_interface = pSetupDiOpenDeviceInterfaceRegKey(*dev_info, &dev_interface_data, 0, KEY_READ); - if (hkey_device_interface != INVALID_HANDLE_VALUE) { - DWORD libusb0_symboliclink_index = 0; - DWORD value_length = sizeof(DWORD); - DWORD value_type = 0; - LONG status; - - status = pRegQueryValueExW(hkey_device_interface, L"LUsb0", NULL, &value_type, - (LPBYTE)&libusb0_symboliclink_index, &value_length); - if (status == ERROR_SUCCESS) { - if (libusb0_symboliclink_index < 256) { - // libusb0.sys is connected to this device instance. - // If the the device interface guid is {F9F3FF14-AE21-48A0-8A25-8011A7A931D9} then it's a filter. - sprintf(filter_path, "\\\\.\\libusb0-%04u", (unsigned int)libusb0_symboliclink_index); - usbi_dbg("assigned libusb0 symbolic link %s", filter_path); - } else { - // libusb0.sys was connected to this device instance at one time; but not anymore. - } - } - pRegCloseKey(hkey_device_interface); - } - } - - return dev_interface_details; - -err_exit: - pSetupDiDestroyDeviceInfoList(*dev_info); - *dev_info = INVALID_HANDLE_VALUE; - return NULL; -} - -/* - * Returns the session ID of a device's nth level ancestor - * If there's no device at the nth level, return 0 - */ -static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level) -{ - DWORD parent_devinst; - unsigned long session_id; - char *sanitized_path; - char path[MAX_PATH_LENGTH]; - unsigned i; - - if (level < 1) - return 0; - - for (i = 0; i < level; i++) { - if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) - return 0; - devinst = parent_devinst; - } - - if (CM_Get_Device_IDA(devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS) - return 0; - - // TODO: (post hotplug): try without sanitizing - sanitized_path = sanitize_path(path); - if (sanitized_path == NULL) - return 0; - - session_id = htab_hash(sanitized_path); - free(sanitized_path); - return session_id; -} - -/* - * Determine which interface the given endpoint address belongs to - */ -static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep) -{ - const struct libusb_interface *intf; - const struct libusb_interface_descriptor *intf_desc; - int i, j, k; - - for (i = 0; i < conf_desc->bNumInterfaces; i++) { - intf = &conf_desc->interface[i]; - for (j = 0; j < intf->num_altsetting; j++) { - intf_desc = &intf->altsetting[j]; - for (k = 0; k < intf_desc->bNumEndpoints; k++) { - if (intf_desc->endpoint[k].bEndpointAddress == ep) { - usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber, i); - return intf_desc->bInterfaceNumber; - } - } - } - } - - usbi_dbg("endpoint %02X not found on any interface", ep); - return LIBUSB_ERROR_NOT_FOUND; -} - -/* - * Populate the endpoints addresses of the device_priv interface helper structs - */ -static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - int i, r; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct libusb_config_descriptor *conf_desc; - const struct libusb_interface_descriptor *if_desc; - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc); - if (r != LIBUSB_SUCCESS) { - usbi_warn(ctx, "could not read config descriptor: error %d", r); - return r; - } - - if_desc = &conf_desc->interface[iface].altsetting[altsetting]; - safe_free(priv->usb_interface[iface].endpoint); - - if (if_desc->bNumEndpoints == 0) { - usbi_dbg("no endpoints found for interface %d", iface); - libusb_free_config_descriptor(conf_desc); - return LIBUSB_SUCCESS; - } - - priv->usb_interface[iface].endpoint = malloc(if_desc->bNumEndpoints); - if (priv->usb_interface[iface].endpoint == NULL) { - libusb_free_config_descriptor(conf_desc); - return LIBUSB_ERROR_NO_MEM; - } - - priv->usb_interface[iface].nb_endpoints = if_desc->bNumEndpoints; - for (i = 0; i < if_desc->bNumEndpoints; i++) { - priv->usb_interface[iface].endpoint[i] = if_desc->endpoint[i].bEndpointAddress; - usbi_dbg("(re)assigned endpoint %02X to interface %d", priv->usb_interface[iface].endpoint[i], iface); - } - libusb_free_config_descriptor(conf_desc); - - // Extra init may be required to configure endpoints - return priv->apib->configure_endpoints(SUB_API_NOTSET, dev_handle, iface); -} - -// Lookup for a match in the list of API driver names -// return -1 if not found, driver match number otherwise -static int get_sub_api(char *driver, int api) -{ - int i; - const char sep_str[2] = {LIST_SEPARATOR, 0}; - char *tok, *tmp_str; - size_t len = strlen(driver); - - if (len == 0) - return SUB_API_NOTSET; - - tmp_str = _strdup(driver); - if (tmp_str == NULL) - return SUB_API_NOTSET; - - tok = strtok(tmp_str, sep_str); - while (tok != NULL) { - for (i = 0; i < usb_api_backend[api].nb_driver_names; i++) { - if (_stricmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) { - free(tmp_str); - return i; - } - } - tok = strtok(NULL, sep_str); - } - - free(tmp_str); - return SUB_API_NOTSET; -} - -/* - * auto-claiming and auto-release helper functions - */ -static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type) -{ - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv( - transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface = *interface_number; - int r = LIBUSB_SUCCESS; - - switch(api_type) { - case USB_API_WINUSBX: - case USB_API_HID: - break; - default: - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_mutex_lock(&autoclaim_lock); - if (current_interface < 0) { // No serviceable interface was found - for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { - // Must claim an interface of the same API type - if ((priv->usb_interface[current_interface].apib->id == api_type) - && (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) { - usbi_dbg("auto-claimed interface %d for control request", current_interface); - if (handle_priv->autoclaim_count[current_interface] != 0) - usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero"); - handle_priv->autoclaim_count[current_interface]++; - break; - } - } - if (current_interface == USB_MAXINTERFACES) { - usbi_err(ctx, "could not auto-claim any interface"); - r = LIBUSB_ERROR_NOT_FOUND; - } - } else { - // If we have a valid interface that was autoclaimed, we must increment - // its autoclaim count so that we can prevent an early release. - if (handle_priv->autoclaim_count[current_interface] != 0) - handle_priv->autoclaim_count[current_interface]++; - } - usbi_mutex_unlock(&autoclaim_lock); - - *interface_number = current_interface; - return r; -} - -static void auto_release(struct usbi_transfer *itransfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - libusb_device_handle *dev_handle = transfer->dev_handle; - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - int r; - - usbi_mutex_lock(&autoclaim_lock); - if (handle_priv->autoclaim_count[transfer_priv->interface_number] > 0) { - handle_priv->autoclaim_count[transfer_priv->interface_number]--; - if (handle_priv->autoclaim_count[transfer_priv->interface_number] == 0) { - r = libusb_release_interface(dev_handle, transfer_priv->interface_number); - if (r == LIBUSB_SUCCESS) - usbi_dbg("auto-released interface %d", transfer_priv->interface_number); - else - usbi_dbg("failed to auto-release interface %d (%s)", - transfer_priv->interface_number, libusb_error_name((enum libusb_error)r)); - } - } - usbi_mutex_unlock(&autoclaim_lock); -} - -/* Windows version dtection */ -static BOOL is_x64(void) -{ - BOOL ret = FALSE; - - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - if (pIsWow64Process != NULL) - pIsWow64Process(GetCurrentProcess(), &ret); - } else { - ret = TRUE; - } - - return ret; -} - -static void get_windows_version(void) -{ - OSVERSIONINFOEXA vi, vi2; - const char *arch, *w = NULL; - unsigned major, minor; - ULONGLONG major_equal, minor_equal; - BOOL ws; - - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { - memset(&vi, 0, sizeof(vi)); - vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) - return; - } - - if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { - if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { - // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version - // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx - - major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); - for (major = vi.dwMajorVersion; major <= 9; major++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMajorVersion = major; - if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) - continue; - - if (vi.dwMajorVersion < major) { - vi.dwMajorVersion = major; - vi.dwMinorVersion = 0; - } - - minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); - for (minor = vi.dwMinorVersion; minor <= 9; minor++) { - memset(&vi2, 0, sizeof(vi2)); - vi2.dwOSVersionInfoSize = sizeof(vi2); - vi2.dwMinorVersion = minor; - if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) - continue; - - vi.dwMinorVersion = minor; - break; - } - - break; - } - } - - if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { - ws = (vi.wProductType <= VER_NT_WORKSTATION); - windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; - switch (windows_version) { - case 0x50: w = "2000"; break; - case 0x51: w = "XP"; break; - case 0x52: w = "2003"; break; - case 0x60: w = (ws ? "Vista" : "2008"); break; - case 0x61: w = (ws ? "7" : "2008_R2"); break; - case 0x62: w = (ws ? "8" : "2012"); break; - case 0x63: w = (ws ? "8.1" : "2012_R2"); break; - case 0x64: w = (ws ? "10" : "2015"); break; - default: - if (windows_version < 0x50) - windows_version = WINDOWS_UNSUPPORTED; - else - w = "11 or later"; - break; - } - } - } - - arch = is_x64() ? "64-bit" : "32-bit"; - - if (w == NULL) - snprintf(windows_version_str, sizeof(windows_version_str), "%s %u.%u %s", - (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), - (unsigned int)vi.dwMajorVersion, (unsigned int)vi.dwMinorVersion, arch); - else if (vi.wServicePackMinor) - snprintf(windows_version_str, sizeof(windows_version_str), "%s SP%u.%u %s", - w, vi.wServicePackMajor, vi.wServicePackMinor, arch); - else if (vi.wServicePackMajor) - snprintf(windows_version_str, sizeof(windows_version_str), "%s SP%u %s", - w, vi.wServicePackMajor, arch); - else - snprintf(windows_version_str, sizeof(windows_version_str), "%s %s", - w, arch); -} - -/* - * init: libusb backend init function - * - * This function enumerates the HCDs (Host Controller Drivers) and populates our private HCD list - * In our implementation, we equate Windows' "HCD" to libusb's "bus". Note that bus is zero indexed. - * HCDs are not expected to change after init (might not hold true for hot pluggable USB PCI card?) - */ -static int windows_init(struct libusb_context *ctx) -{ - int i, r = LIBUSB_ERROR_OTHER; - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) { - usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_MEM; - } - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore's release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); - CloseHandle(semaphore); - return LIBUSB_ERROR_NO_MEM; - } - - // NB: concurrent usage supposes that init calls are equally balanced with - // exit calls. If init is called more than exit, we will not exit properly - if (++concurrent_usage == 0) { // First init? - get_windows_version(); - usbi_dbg("Windows %s", windows_version_str); - - if (windows_version == WINDOWS_UNSUPPORTED) { - usbi_err(ctx, "This version of Windows is NOT supported"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - goto init_exit; - } - - // We need a lock for proper auto-release - usbi_mutex_init(&autoclaim_lock); - - // Initialize pollable file descriptors - init_polling(); - - // Load DLL imports - if (init_dlls() != LIBUSB_SUCCESS) { - usbi_err(ctx, "could not resolve DLL functions"); - goto init_exit; - } - - // Initialize the low level APIs (we don't care about errors at this stage) - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].init(SUB_API_NOTSET, ctx); - - r = windows_common_init(ctx); - if (r) - goto init_exit; - } - // At this stage, either we went through full init successfully, or didn't need to - r = LIBUSB_SUCCESS; - -init_exit: // Holds semaphore here. - if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUB_API_NOTSET); - exit_dlls(); - exit_polling(); - windows_common_exit(); - usbi_mutex_destroy(&autoclaim_lock); - } - - if (r != LIBUSB_SUCCESS) - --concurrent_usage; // Not expected to call libusb_exit if we failed. - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); - return r; -} - -/* - * HCD (root) hubs need to have their device descriptor manually populated - * - * Note that, like Microsoft does in the device manager, we populate the - * Vendor and Device ID for HCD hubs with the ones from the PCI HCD device. - */ -static int force_hcd_device_descriptor(struct libusb_device *dev) -{ - struct windows_device_priv *parent_priv, *priv = _device_priv(dev); - struct libusb_context *ctx = DEVICE_CTX(dev); - int vid, pid; - - dev->num_configurations = 1; - priv->dev_descriptor.bLength = sizeof(USB_DEVICE_DESCRIPTOR); - priv->dev_descriptor.bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; - priv->dev_descriptor.bNumConfigurations = 1; - priv->active_config = 1; - - if (dev->parent_dev == NULL) { - usbi_err(ctx, "program assertion failed - HCD hub has no parent"); - return LIBUSB_ERROR_NO_DEVICE; - } - - parent_priv = _device_priv(dev->parent_dev); - if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) { - priv->dev_descriptor.idVendor = (uint16_t)vid; - priv->dev_descriptor.idProduct = (uint16_t)pid; - } else { - usbi_warn(ctx, "could not infer VID/PID of HCD hub from '%s'", parent_priv->path); - priv->dev_descriptor.idVendor = 0x1d6b; // Linux Foundation root hub - priv->dev_descriptor.idProduct = 1; - } - - return LIBUSB_SUCCESS; -} - -/* - * fetch and cache all the config descriptors through I/O - */ -static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle, char *device_id) -{ - DWORD size, ret_size; - struct libusb_context *ctx = DEVICE_CTX(dev); - struct windows_device_priv *priv = _device_priv(dev); - int r; - uint8_t i; - - USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request - PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request - PUSB_CONFIGURATION_DESCRIPTOR cd_data = NULL; - - if (dev->num_configurations == 0) - return LIBUSB_ERROR_INVALID_PARAM; - - priv->config_descriptor = calloc(dev->num_configurations, sizeof(unsigned char *)); - if (priv->config_descriptor == NULL) - return LIBUSB_ERROR_NO_MEM; - - for (i = 0; i < dev->num_configurations; i++) - priv->config_descriptor[i] = NULL; - - for (i = 0, r = LIBUSB_SUCCESS; ; i++) { - // safe loop: release all dynamic resources - safe_free(cd_buf_actual); - - // safe loop: end of loop condition - if ((i >= dev->num_configurations) || (r != LIBUSB_SUCCESS)) - break; - - size = sizeof(USB_CONFIGURATION_DESCRIPTOR_SHORT); - memset(&cd_buf_short, 0, size); - - cd_buf_short.req.ConnectionIndex = (ULONG)priv->port; - cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; - cd_buf_short.req.SetupPacket.wIndex = 0; - cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Dummy call to get the required data size. Initial failures are reported as info rather - // than error as they can occur for non-penalizing situations, such as with some hubs. - // coverity[tainted_data_argument] - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size, - &cd_buf_short, size, &ret_size, NULL)) { - usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - if ((ret_size != size) || (cd_buf_short.data.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))) { - usbi_info(ctx, "unexpected configuration descriptor size (dummy) for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - size = sizeof(USB_DESCRIPTOR_REQUEST) + cd_buf_short.data.wTotalLength; - cd_buf_actual = calloc(1, size); - if (cd_buf_actual == NULL) { - usbi_err(ctx, "could not allocate configuration descriptor buffer for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - - // Actual call - cd_buf_actual->ConnectionIndex = (ULONG)priv->port; - cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; - cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i; - cd_buf_actual->SetupPacket.wIndex = 0; - cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST)); - - if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size, - cd_buf_actual, size, &ret_size, NULL)) { - usbi_err(ctx, "could not access configuration descriptor (actual) for '%s': %s", device_id, windows_error_str(0)); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST)); - - if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.data.wTotalLength)) { - usbi_err(ctx, "unexpected configuration descriptor size (actual) for '%s'.", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - if (cd_data->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) { - usbi_err(ctx, "not a configuration descriptor for '%s'", device_id); - LOOP_BREAK(LIBUSB_ERROR_IO); - } - - usbi_dbg("cached config descriptor %d (bConfigurationValue=%u, %u bytes)", - i, cd_data->bConfigurationValue, cd_data->wTotalLength); - - // Cache the descriptor - priv->config_descriptor[i] = malloc(cd_data->wTotalLength); - if (priv->config_descriptor[i] == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength); - } - return LIBUSB_SUCCESS; -} - -/* - * Populate a libusb device structure - */ -static int init_device(struct libusb_device *dev, struct libusb_device *parent_dev, - uint8_t port_number, char *device_id, DWORD devinst) -{ - HANDLE handle; - DWORD size; - USB_NODE_CONNECTION_INFORMATION_EX conn_info; - USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; - struct windows_device_priv *priv, *parent_priv; - struct libusb_context *ctx; - struct libusb_device *tmp_dev; - unsigned long tmp_id; - unsigned i; - - if ((dev == NULL) || (parent_dev == NULL)) - return LIBUSB_ERROR_NOT_FOUND; - - ctx = DEVICE_CTX(dev); - priv = _device_priv(dev); - parent_priv = _device_priv(parent_dev); - if (parent_priv->apib->id != USB_API_HUB) { - usbi_warn(ctx, "parent for device '%s' is not a hub", device_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - // It is possible for the parent hub not to have been initialized yet - // If that's the case, lookup the ancestors to set the bus number - if (parent_dev->bus_number == 0) { - for (i = 2; ; i++) { - tmp_id = get_ancestor_session_id(devinst, i); - if (tmp_id == 0) - break; - - tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id); - if (tmp_dev == NULL) - continue; - - if (tmp_dev->bus_number != 0) { - usbi_dbg("got bus number from ancestor #%u", i); - parent_dev->bus_number = tmp_dev->bus_number; - libusb_unref_device(tmp_dev); - break; - } - - libusb_unref_device(tmp_dev); - } - } - - if (parent_dev->bus_number == 0) { - usbi_err(ctx, "program assertion failed: unable to find ancestor bus number for '%s'", device_id); - return LIBUSB_ERROR_NOT_FOUND; - } - - dev->bus_number = parent_dev->bus_number; - priv->port = port_number; - dev->port_number = port_number; - priv->depth = parent_priv->depth + 1; - dev->parent_dev = parent_dev; - - // If the device address is already set, we can stop here - if (dev->device_address != 0) - return LIBUSB_SUCCESS; - - memset(&conn_info, 0, sizeof(conn_info)); - if (priv->depth != 0) { // Not a HCD hub - handle = CreateFileA(parent_priv->path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - if (handle == INVALID_HANDLE_VALUE) { - usbi_warn(ctx, "could not open hub %s: %s", parent_priv->path, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - - size = sizeof(conn_info); - conn_info.ConnectionIndex = (ULONG)port_number; - // coverity[tainted_data_argument] - if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size, - &conn_info, size, &size, NULL)) { - usbi_warn(ctx, "could not get node connection information for device '%s': %s", - device_id, windows_error_str(0)); - CloseHandle(handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - if (conn_info.ConnectionStatus == NoDeviceConnected) { - usbi_err(ctx, "device '%s' is no longer connected!", device_id); - CloseHandle(handle); - return LIBUSB_ERROR_NO_DEVICE; - } - - memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR)); - dev->num_configurations = priv->dev_descriptor.bNumConfigurations; - priv->active_config = conn_info.CurrentConfigurationValue; - usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config); - - // If we can't read the config descriptors, just set the number of confs to zero - if (cache_config_descriptors(dev, handle, device_id) != LIBUSB_SUCCESS) { - dev->num_configurations = 0; - priv->dev_descriptor.bNumConfigurations = 0; - } - - // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8 - if (windows_version >= WINDOWS_8) { - memset(&conn_info_v2, 0, sizeof(conn_info_v2)); - size = sizeof(conn_info_v2); - conn_info_v2.ConnectionIndex = (ULONG)port_number; - conn_info_v2.Length = size; - conn_info_v2.SupportedUsbProtocols.Usb300 = 1; - if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, - &conn_info_v2, size, &conn_info_v2, size, &size, NULL)) { - usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s", - device_id, windows_error_str(0)); - } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { - conn_info.Speed = 3; - } - } - - CloseHandle(handle); - - if (conn_info.DeviceAddress > UINT8_MAX) - usbi_err(ctx, "program assertion failed: device address overflow"); - - dev->device_address = (uint8_t)conn_info.DeviceAddress + 1; - if (dev->device_address == 1) - usbi_err(ctx, "program assertion failed: device address collision with root hub"); - - switch (conn_info.Speed) { - case 0: dev->speed = LIBUSB_SPEED_LOW; break; - case 1: dev->speed = LIBUSB_SPEED_FULL; break; - case 2: dev->speed = LIBUSB_SPEED_HIGH; break; - case 3: dev->speed = LIBUSB_SPEED_SUPER; break; - default: - usbi_warn(ctx, "Got unknown device speed %u", conn_info.Speed); - break; - } - } else { - dev->device_address = 1; // root hubs are set to use device number 1 - force_hcd_device_descriptor(dev); - } - - usbi_sanitize_device(dev); - - usbi_dbg("(bus: %u, addr: %u, depth: %u, port: %u): '%s'", - dev->bus_number, dev->device_address, priv->depth, priv->port, device_id); - - return LIBUSB_SUCCESS; -} - -// Returns the api type, or 0 if not found/unsupported -static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info, - SP_DEVINFO_DATA *dev_info_data, int *api, int *sub_api) -{ - // Precedence for filter drivers vs driver is in the order of this array - struct driver_lookup lookup[3] = { - {"\0\0", SPDRP_SERVICE, "driver"}, - {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"}, - {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"} - }; - DWORD size, reg_type; - unsigned k, l; - int i, j; - - *api = USB_API_UNSUPPORTED; - *sub_api = SUB_API_NOTSET; - - // Check the service & filter names to know the API we should use - for (k = 0; k < 3; k++) { - if (pSetupDiGetDeviceRegistryPropertyA(*dev_info, dev_info_data, lookup[k].reg_prop, - ®_type, (BYTE *)lookup[k].list, MAX_KEY_LENGTH, &size)) { - // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ - if (lookup[k].reg_prop == SPDRP_SERVICE) - // our buffers are MAX_KEY_LENGTH + 1 so we can overflow if needed - lookup[k].list[strlen(lookup[k].list) + 1] = 0; - - // MULTI_SZ is a pain to work with. Turn it into something much more manageable - // NB: none of the driver names we check against contain LIST_SEPARATOR, - // (currently ';'), so even if an unsuported one does, it's not an issue - for (l = 0; (lookup[k].list[l] != 0) || (lookup[k].list[l + 1] != 0); l++) { - if (lookup[k].list[l] == 0) - lookup[k].list[l] = LIST_SEPARATOR; - } - usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list); - } else { - if (GetLastError() != ERROR_INVALID_DATA) - usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0)); - lookup[k].list[0] = 0; - } - } - - for (i = 1; i < USB_API_MAX; i++) { - for (k = 0; k < 3; k++) { - j = get_sub_api(lookup[k].list, i); - if (j >= 0) { - usbi_dbg("matched %s name against %s", lookup[k].designation, - (i != USB_API_WINUSBX) ? usb_api_backend[i].designation : sub_api_name[j]); - *api = i; - *sub_api = j; - return; - } - } - } -} - -static int set_composite_interface(struct libusb_context *ctx, struct libusb_device *dev, - char *dev_interface_path, char *device_id, int api, int sub_api) -{ - unsigned i; - struct windows_device_priv *priv = _device_priv(dev); - int interface_number; - - if (priv->apib->id != USB_API_COMPOSITE) { - usbi_err(ctx, "program assertion failed: '%s' is not composite", device_id); - return LIBUSB_ERROR_NO_DEVICE; - } - - // Because MI_## are not necessarily in sequential order (some composite - // devices will have only MI_00 & MI_03 for instance), we retrieve the actual - // interface number from the path's MI value - interface_number = 0; - for (i = 0; device_id[i] != 0; ) { - if ((device_id[i++] == 'M') && (device_id[i++] == 'I') - && (device_id[i++] == '_')) { - interface_number = (device_id[i++] - '0') * 10; - interface_number += device_id[i] - '0'; - break; - } - } - - if (device_id[i] == 0) - usbi_warn(ctx, "failure to read interface number for %s. Using default value %d", - device_id, interface_number); - - if (priv->usb_interface[interface_number].path != NULL) { - if (api == USB_API_HID) { - // HID devices can have multiple collections (COL##) for each MI_## interface - usbi_dbg("interface[%d] already set - ignoring HID collection: %s", - interface_number, device_id); - return LIBUSB_ERROR_ACCESS; - } - // In other cases, just use the latest data - safe_free(priv->usb_interface[interface_number].path); - } - - usbi_dbg("interface[%d] = %s", interface_number, dev_interface_path); - priv->usb_interface[interface_number].path = dev_interface_path; - priv->usb_interface[interface_number].apib = &usb_api_backend[api]; - priv->usb_interface[interface_number].sub_api = sub_api; - if ((api == USB_API_HID) && (priv->hid == NULL)) { - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) - return LIBUSB_ERROR_NO_MEM; - } - - return LIBUSB_SUCCESS; -} - -static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev, - char *dev_interface_path) -{ - int i; - struct windows_device_priv *priv = _device_priv(dev); - - if (priv->hid == NULL) { - usbi_err(ctx, "program assertion failed: parent is not HID"); - return LIBUSB_ERROR_NO_DEVICE; - } else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) { - usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device"); - return LIBUSB_ERROR_NO_DEVICE; - } - - for (i = 0; i < priv->hid->nb_interfaces; i++) { - if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) { - usbi_dbg("interface[%d] already set to %s", i, dev_interface_path); - return LIBUSB_ERROR_ACCESS; - } - } - - priv->usb_interface[priv->hid->nb_interfaces].path = dev_interface_path; - priv->usb_interface[priv->hid->nb_interfaces].apib = &usb_api_backend[USB_API_HID]; - usbi_dbg("interface[%u] = %s", priv->hid->nb_interfaces, dev_interface_path); - priv->hid->nb_interfaces++; - return LIBUSB_SUCCESS; -} - -/* - * get_device_list: libusb backend device enumeration function - */ -static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) -{ - struct discovered_devs *discdevs; - HDEVINFO dev_info = { 0 }; - const char *usb_class[] = {"USB", "NUSB3", "IUSB3", "IARUSB3"}; - SP_DEVINFO_DATA dev_info_data = { 0 }; - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; - GUID hid_guid; -#define MAX_ENUM_GUIDS 64 - const GUID *guid[MAX_ENUM_GUIDS]; -#define HCD_PASS 0 -#define HUB_PASS 1 -#define GEN_PASS 2 -#define DEV_PASS 3 -#define HID_PASS 4 - int r = LIBUSB_SUCCESS; - int api, sub_api; - size_t class_index = 0; - unsigned int nb_guids, pass, i, j, ancestor; - char path[MAX_PATH_LENGTH]; - char strbuf[MAX_PATH_LENGTH]; - struct libusb_device *dev, *parent_dev; - struct windows_device_priv *priv, *parent_priv; - char *dev_interface_path = NULL; - char *dev_id_path = NULL; - unsigned long session_id; - DWORD size, reg_type, port_nr, install_state; - HKEY key; - WCHAR guid_string_w[MAX_GUID_STRING_LENGTH]; - GUID *if_guid; - LONG s; - // Keep a list of newly allocated devs to unref - libusb_device **unref_list, **new_unref_list; - unsigned int unref_size = 64; - unsigned int unref_cur = 0; - - // PASS 1 : (re)enumerate HCDs (allows for HCD hotplug) - // PASS 2 : (re)enumerate HUBS - // PASS 3 : (re)enumerate generic USB devices (including driverless) - // and list additional USB device interface GUIDs to explore - // PASS 4 : (re)enumerate master USB devices that have a device interface - // PASS 5+: (re)enumerate device interfaced GUIDs (including HID) and - // set the device interfaces. - - // Init the GUID table - guid[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER; - guid[HUB_PASS] = &GUID_DEVINTERFACE_USB_HUB; - guid[GEN_PASS] = NULL; - guid[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE; - HidD_GetHidGuid(&hid_guid); - guid[HID_PASS] = &hid_guid; - nb_guids = HID_PASS + 1; - - unref_list = calloc(unref_size, sizeof(libusb_device *)); - if (unref_list == NULL) - return LIBUSB_ERROR_NO_MEM; - - for (pass = 0; ((pass < nb_guids) && (r == LIBUSB_SUCCESS)); pass++) { -//#define ENUM_DEBUG -#if defined(ENABLE_LOGGING) && defined(ENUM_DEBUG) - const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" }; - usbi_dbg("#### PROCESSING %ss %s", passname[(pass <= HID_PASS) ? pass : (HID_PASS + 1)], - (pass != GEN_PASS) ? guid_to_string(guid[pass]) : ""); -#endif - for (i = 0; ; i++) { - // safe loop: free up any (unprotected) dynamic resource - // NB: this is always executed before breaking the loop - safe_free(dev_interface_details); - safe_free(dev_interface_path); - safe_free(dev_id_path); - priv = parent_priv = NULL; - dev = parent_dev = NULL; - - // Safe loop: end of loop conditions - if (r != LIBUSB_SUCCESS) - break; - - if ((pass == HCD_PASS) && (i == UINT8_MAX)) { - usbi_warn(ctx, "program assertion failed - found more than %d buses, skipping the rest.", UINT8_MAX); - break; - } - - if (pass != GEN_PASS) { - // Except for GEN, all passes deal with device interfaces - dev_interface_details = get_interface_details(ctx, &dev_info, &dev_info_data, guid[pass], i); - if (dev_interface_details == NULL) - break; - - dev_interface_path = sanitize_path(dev_interface_details->DevicePath); - if (dev_interface_path == NULL) { - usbi_warn(ctx, "could not sanitize device interface path for '%s'", dev_interface_details->DevicePath); - continue; - } - } else { - // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are - // being listed under the "NUSB3" PnP Symbolic Name rather than "USB". - // The Intel USB 3.0 driver behaves similar, but uses "IUSB3" - // The Intel Alpine Ridge USB 3.1 driver uses "IARUSB3" - for (; class_index < ARRAYSIZE(usb_class); class_index++) { - if (get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i)) - break; - i = 0; - } - if (class_index >= ARRAYSIZE(usb_class)) - break; - } - - // Read the Device ID path. This is what we'll use as UID - // Note that if the device is plugged in a different port or hub, the Device ID changes - if (CM_Get_Device_IDA(dev_info_data.DevInst, path, sizeof(path), 0) != CR_SUCCESS) { - usbi_warn(ctx, "could not read the device id path for devinst %X, skipping", - (unsigned int)dev_info_data.DevInst); - continue; - } - - dev_id_path = sanitize_path(path); - if (dev_id_path == NULL) { - usbi_warn(ctx, "could not sanitize device id path for devinst %X, skipping", - (unsigned int)dev_info_data.DevInst); - continue; - } -#ifdef ENUM_DEBUG - usbi_dbg("PRO: %s", dev_id_path); -#endif - - // The SPDRP_ADDRESS for USB devices is the device port number on the hub - port_nr = 0; - if ((pass >= HUB_PASS) && (pass <= GEN_PASS)) { - if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ADDRESS, - ®_type, (BYTE *)&port_nr, 4, &size)) || (size != 4)) { - usbi_warn(ctx, "could not retrieve port number for device '%s', skipping: %s", - dev_id_path, windows_error_str(0)); - continue; - } - } - - // Set API to use or get additional data from generic pass - api = USB_API_UNSUPPORTED; - sub_api = SUB_API_NOTSET; - switch (pass) { - case HCD_PASS: - break; - case GEN_PASS: - // We use the GEN pass to detect driverless devices... - size = sizeof(strbuf); - if (!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER, - ®_type, (BYTE *)strbuf, size, &size)) { - usbi_info(ctx, "The following device has no driver: '%s'", dev_id_path); - usbi_info(ctx, "libusb will not be able to access it."); - } - // ...and to add the additional device interface GUIDs - key = pSetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); - if (key != INVALID_HANDLE_VALUE) { - size = sizeof(guid_string_w); - s = pRegQueryValueExW(key, L"DeviceInterfaceGUIDs", NULL, ®_type, - (BYTE *)guid_string_w, &size); - pRegCloseKey(key); - if (s == ERROR_SUCCESS) { - if (nb_guids >= MAX_ENUM_GUIDS) { - // If this assert is ever reported, grow a GUID table dynamically - usbi_err(ctx, "program assertion failed: too many GUIDs"); - LOOP_BREAK(LIBUSB_ERROR_OVERFLOW); - } - if_guid = calloc(1, sizeof(GUID)); - if (if_guid == NULL) { - usbi_err(ctx, "could not calloc for if_guid: not enough memory"); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } - pCLSIDFromString(guid_string_w, if_guid); - guid[nb_guids++] = if_guid; - usbi_dbg("extra GUID: %s", guid_to_string(if_guid)); - } - } - break; - case HID_PASS: - api = USB_API_HID; - break; - default: - // Get the API type (after checking that the driver installation is OK) - if ((!pSetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_INSTALL_STATE, - ®_type, (BYTE *)&install_state, 4, &size)) || (size != 4)) { - usbi_warn(ctx, "could not detect installation state of driver for '%s': %s", - dev_id_path, windows_error_str(0)); - } else if (install_state != 0) { - usbi_warn(ctx, "driver for device '%s' is reporting an issue (code: %u) - skipping", - dev_id_path, (unsigned int)install_state); - continue; - } - get_api_type(ctx, &dev_info, &dev_info_data, &api, &sub_api); - break; - } - - // Find parent device (for the passes that need it) - switch (pass) { - case HCD_PASS: - case DEV_PASS: - case HUB_PASS: - break; - default: - // Go through the ancestors until we see a face we recognize - parent_dev = NULL; - for (ancestor = 1; parent_dev == NULL; ancestor++) { - session_id = get_ancestor_session_id(dev_info_data.DevInst, ancestor); - if (session_id == 0) - break; - - parent_dev = usbi_get_device_by_session_id(ctx, session_id); - } - - if (parent_dev == NULL) { - usbi_dbg("unlisted ancestor for '%s' (non USB HID, newly connected, etc.) - ignoring", dev_id_path); - continue; - } - - parent_priv = _device_priv(parent_dev); - // virtual USB devices are also listed during GEN - don't process these yet - if ((pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB)) { - libusb_unref_device(parent_dev); - continue; - } - - break; - } - - // Create new or match existing device, using the (hashed) device_id as session id - if (pass <= DEV_PASS) { // For subsequent passes, we'll lookup the parent - // These are the passes that create "new" devices - session_id = htab_hash(dev_id_path); - dev = usbi_get_device_by_session_id(ctx, session_id); - if (dev == NULL) { - if (pass == DEV_PASS) { - // This can occur if the OS only reports a newly plugged device after we started enum - usbi_warn(ctx, "'%s' was only detected in late pass (newly connected device?)" - " - ignoring", dev_id_path); - continue; - } - - usbi_dbg("allocating new device for session [%lX]", session_id); - dev = usbi_alloc_device(ctx, session_id); - if (dev == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - priv = windows_device_priv_init(dev); - } else { - usbi_dbg("found existing device for session [%lX] (%u.%u)", - session_id, dev->bus_number, dev->device_address); - - priv = _device_priv(dev); - if ((parent_dev != NULL) && (dev->parent_dev != NULL)) { - if (dev->parent_dev != parent_dev) { - // It is possible for the actual parent device to not have existed at the - // time of enumeration, so the currently assigned parent may in fact be a - // grandparent. If the devices differ, we assume the "new" parent device - // is in fact closer to the device. - usbi_dbg("updating parent device [session %lX -> %lX]", - dev->parent_dev->session_data, parent_dev->session_data); - libusb_unref_device(dev->parent_dev); - dev->parent_dev = parent_dev; - } else { - // We hold a reference to parent_dev instance, but this device already - // has a parent_dev reference (only one per child) - libusb_unref_device(parent_dev); - } - } - } - - // Keep track of devices that need unref - unref_list[unref_cur++] = dev; - if (unref_cur >= unref_size) { - unref_size += 64; - new_unref_list = usbi_reallocf(unref_list, unref_size * sizeof(libusb_device *)); - if (new_unref_list == NULL) { - usbi_err(ctx, "could not realloc list for unref - aborting."); - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - } else { - unref_list = new_unref_list; - } - } - } - - // Setup device - switch (pass) { - case HCD_PASS: - // If the hcd has already been setup, don't do it again - if (priv->path != NULL) - break; - dev->bus_number = (uint8_t)(i + 1); // bus 0 is reserved for disconnected - dev->device_address = 0; - dev->num_configurations = 0; - priv->apib = &usb_api_backend[USB_API_HUB]; - priv->sub_api = SUB_API_NOTSET; - priv->depth = UINT8_MAX; // Overflow to 0 for HCD Hubs - priv->path = dev_interface_path; - dev_interface_path = NULL; - break; - case HUB_PASS: - case DEV_PASS: - // If the device has already been setup, don't do it again - if (priv->path != NULL) - break; - // Take care of API initialization - priv->path = dev_interface_path; - dev_interface_path = NULL; - priv->apib = &usb_api_backend[api]; - priv->sub_api = sub_api; - switch(api) { - case USB_API_COMPOSITE: - case USB_API_HUB: - break; - case USB_API_HID: - priv->hid = calloc(1, sizeof(struct hid_device_priv)); - if (priv->hid == NULL) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - priv->hid->nb_interfaces = 0; - break; - default: - // For other devices, the first interface is the same as the device - priv->usb_interface[0].path = _strdup(priv->path); - if (priv->usb_interface[0].path == NULL) - usbi_warn(ctx, "could not duplicate interface path '%s'", priv->path); - // The following is needed if we want API calls to work for both simple - // and composite devices. - for (j = 0; j < USB_MAXINTERFACES; j++) - priv->usb_interface[j].apib = &usb_api_backend[api]; - - break; - } - break; - case GEN_PASS: - r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_id_path, dev_info_data.DevInst); - if (r == LIBUSB_SUCCESS) { - // Append device to the list of discovered devices - discdevs = discovered_devs_append(*_discdevs, dev); - if (!discdevs) - LOOP_BREAK(LIBUSB_ERROR_NO_MEM); - - *_discdevs = discdevs; - } else if (r == LIBUSB_ERROR_NO_DEVICE) { - // This can occur if the device was disconnected but Windows hasn't - // refreshed its enumeration yet - in that case, we ignore the device - r = LIBUSB_SUCCESS; - } - break; - default: // HID_PASS and later - if (parent_priv->apib->id == USB_API_HID || parent_priv->apib->id == USB_API_COMPOSITE) { - if (parent_priv->apib->id == USB_API_HID) { - usbi_dbg("setting HID interface for [%lX]:", parent_dev->session_data); - r = set_hid_interface(ctx, parent_dev, dev_interface_path); - } else { - usbi_dbg("setting composite interface for [%lX]:", parent_dev->session_data); - r = set_composite_interface(ctx, parent_dev, dev_interface_path, dev_id_path, api, sub_api); - } - switch (r) { - case LIBUSB_SUCCESS: - dev_interface_path = NULL; - break; - case LIBUSB_ERROR_ACCESS: - // interface has already been set => make sure dev_interface_path is freed then - r = LIBUSB_SUCCESS; - break; - default: - LOOP_BREAK(r); - break; - } - } - libusb_unref_device(parent_dev); - break; - } - } - } - - // Free any additional GUIDs - for (pass = HID_PASS + 1; pass < nb_guids; pass++) - free((void *)guid[pass]); - - // Unref newly allocated devs - for (i = 0; i < unref_cur; i++) - libusb_unref_device(unref_list[i]); - free(unref_list); - - return r; -} - -/* - * exit: libusb backend deinitialization function - */ -static void windows_exit(void) -{ - int i; - HANDLE semaphore; - char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' - - sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); - semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); - if (semaphore == NULL) - return; - - // A successful wait brings our semaphore count to 0 (unsignaled) - // => any concurent wait stalls until the semaphore release - if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { - CloseHandle(semaphore); - return; - } - - // Only works if exits and inits are balanced exactly - if (--concurrent_usage < 0) { // Last exit - for (i = 0; i < USB_API_MAX; i++) - usb_api_backend[i].exit(SUB_API_NOTSET); - exit_dlls(); - exit_polling(); - windows_common_exit(); - usbi_mutex_destroy(&autoclaim_lock); - } - - ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 - CloseHandle(semaphore); -} - -static int windows_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - - memcpy(buffer, &priv->dev_descriptor, DEVICE_DESC_LENGTH); - *host_endian = 0; - - return LIBUSB_SUCCESS; -} - -static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - size_t size; - - // config index is zero based - if (config_index >= dev->num_configurations) - return LIBUSB_ERROR_INVALID_PARAM; - - if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL)) - return LIBUSB_ERROR_NOT_FOUND; - - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index]; - - size = MIN(config_header->wTotalLength, len); - memcpy(buffer, priv->config_descriptor[config_index], size); - *host_endian = 0; - - return (int)size; -} - -static int windows_get_config_descriptor_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, - unsigned char **buffer, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - PUSB_CONFIGURATION_DESCRIPTOR config_header; - uint8_t index; - - *buffer = NULL; - *host_endian = 0; - - if (priv->config_descriptor == NULL) - return LIBUSB_ERROR_NOT_FOUND; - - for (index = 0; index < dev->num_configurations; index++) { - config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[index]; - if (config_header->bConfigurationValue == bConfigurationValue) { - *buffer = priv->config_descriptor[index]; - return (int)config_header->wTotalLength; - } - } - - return LIBUSB_ERROR_NOT_FOUND; -} - -/* - * return the cached copy of the active config descriptor - */ -static int windows_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) -{ - struct windows_device_priv *priv = _device_priv(dev); - unsigned char *config_desc; - int r; - - if (priv->active_config == 0) - return LIBUSB_ERROR_NOT_FOUND; - - r = windows_get_config_descriptor_by_value(dev, priv->active_config, &config_desc, host_endian); - if (r < 0) - return r; - - len = MIN((size_t)r, len); - memcpy(buffer, config_desc, len); - return (int)len; -} - -static int windows_open(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - if (priv->apib == NULL) { - usbi_err(ctx, "program assertion failed - device is not initialized"); - return LIBUSB_ERROR_NO_DEVICE; - } - - return priv->apib->open(SUB_API_NOTSET, dev_handle); -} - -static void windows_close(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - priv->apib->close(SUB_API_NOTSET, dev_handle); -} - -static int windows_get_configuration(struct libusb_device_handle *dev_handle, int *config) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - if (priv->active_config == 0) { - *config = 0; - return LIBUSB_ERROR_NOT_FOUND; - } - - *config = priv->active_config; - return LIBUSB_SUCCESS; -} - -/* - * from http://msdn.microsoft.com/en-us/library/ms793522.aspx: "The port driver - * does not currently expose a service that allows higher-level drivers to set - * the configuration." - */ -static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int r = LIBUSB_SUCCESS; - - if (config >= USB_MAXCONFIG) - return LIBUSB_ERROR_INVALID_PARAM; - - r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT | - LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, - LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config, - 0, NULL, 0, 1000); - - if (r == LIBUSB_SUCCESS) - priv->active_config = (uint8_t)config; - - return r; -} - -static int windows_claim_interface(struct libusb_device_handle *dev_handle, int iface) -{ - int r = LIBUSB_SUCCESS; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints = 0; - - r = priv->apib->claim_interface(SUB_API_NOTSET, dev_handle, iface); - - if (r == LIBUSB_SUCCESS) - r = windows_assign_endpoints(dev_handle, iface, 0); - - return r; -} - -static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - int r = LIBUSB_SUCCESS; - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - safe_free(priv->usb_interface[iface].endpoint); - priv->usb_interface[iface].nb_endpoints = 0; - - r = priv->apib->set_interface_altsetting(SUB_API_NOTSET, dev_handle, iface, altsetting); - - if (r == LIBUSB_SUCCESS) - r = windows_assign_endpoints(dev_handle, iface, altsetting); - - return r; -} - -static int windows_release_interface(struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->apib->release_interface(SUB_API_NOTSET, dev_handle, iface); -} - -static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - return priv->apib->clear_halt(SUB_API_NOTSET, dev_handle, endpoint); -} - -static int windows_reset_device(struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - return priv->apib->reset_device(SUB_API_NOTSET, dev_handle); -} - -// The 3 functions below are unlikely to ever get supported on Windows -static int windows_kernel_driver_active(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int windows_attach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int windows_detach_kernel_driver(struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static void windows_destroy_device(struct libusb_device *dev) -{ - windows_device_priv_release(dev); -} - -void windows_clear_transfer_priv(struct usbi_transfer *itransfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - - usbi_free_fd(&transfer_priv->pollable_fd); - safe_free(transfer_priv->hid_buffer); - // When auto claim is in use, attempt to release the auto-claimed interface - auto_release(itransfer); -} - -static int submit_bulk_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_bulk_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, - (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - - return LIBUSB_SUCCESS; -} - -static int submit_iso_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_iso_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, - (short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT)); - - return LIBUSB_SUCCESS; -} - -static int submit_control_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int r; - - r = priv->apib->submit_control_transfer(SUB_API_NOTSET, itransfer); - if (r != LIBUSB_SUCCESS) - return r; - - usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); - - return LIBUSB_SUCCESS; -} - -static int windows_submit_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return submit_control_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) - return LIBUSB_ERROR_NOT_SUPPORTED; - return submit_bulk_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return submit_iso_transfer(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -static int windows_abort_control(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->apib->abort_control(SUB_API_NOTSET, itransfer); -} - -static int windows_abort_transfers(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer); -} - -static int windows_cancel_transfer(struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - - switch (transfer->type) { - case LIBUSB_TRANSFER_TYPE_CONTROL: - return windows_abort_control(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK: - case LIBUSB_TRANSFER_TYPE_INTERRUPT: - case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: - return windows_abort_transfers(itransfer); - case LIBUSB_TRANSFER_TYPE_BULK_STREAM: - return LIBUSB_ERROR_NOT_SUPPORTED; - default: - usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); - return LIBUSB_ERROR_INVALID_PARAM; - } -} - -int windows_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size); -} - -struct winfd *windows_get_fd(struct usbi_transfer *transfer) -{ - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(transfer); - return &transfer_priv->pollable_fd; -} - -void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) -{ - if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) { - *io_result = NO_ERROR; - *io_size = (DWORD)pollable_fd->overlapped->InternalHigh; - } else if (GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { - // Regular async overlapped - *io_result = NO_ERROR; - } else { - *io_result = GetLastError(); - } -} - -// NB: MSVC6 does not support named initializers. -const struct usbi_os_backend windows_backend = { - "Windows", - USBI_CAP_HAS_HID_ACCESS, - windows_init, - windows_exit, - - windows_get_device_list, - NULL, /* hotplug_poll */ - windows_open, - windows_close, - - windows_get_device_descriptor, - windows_get_active_config_descriptor, - windows_get_config_descriptor, - windows_get_config_descriptor_by_value, - - windows_get_configuration, - windows_set_configuration, - windows_claim_interface, - windows_release_interface, - - windows_set_interface_altsetting, - windows_clear_halt, - windows_reset_device, - - NULL, /* alloc_streams */ - NULL, /* free_streams */ - - NULL, /* dev_mem_alloc */ - NULL, /* dev_mem_free */ - - windows_kernel_driver_active, - windows_detach_kernel_driver, - windows_attach_kernel_driver, - - windows_destroy_device, - - windows_submit_transfer, - windows_cancel_transfer, - windows_clear_transfer_priv, - - windows_handle_events, - NULL, - - windows_clock_gettime, -#if defined(USBI_TIMERFD_AVAILABLE) - NULL, -#endif - sizeof(struct windows_device_priv), - sizeof(struct windows_device_handle_priv), - sizeof(struct windows_transfer_priv), -}; - - -/* - * USB API backends - */ -static int unsupported_init(int sub_api, struct libusb_context *ctx) -{ - return LIBUSB_SUCCESS; -} - -static int unsupported_exit(int sub_api) -{ - return LIBUSB_SUCCESS; -} - -static int unsupported_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - PRINT_UNSUPPORTED_API(open); -} - -static void unsupported_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - usbi_dbg("unsupported API call for 'close'"); -} - -static int unsupported_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(configure_endpoints); -} - -static int unsupported_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(claim_interface); -} - -static int unsupported_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - PRINT_UNSUPPORTED_API(set_interface_altsetting); -} - -static int unsupported_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - PRINT_UNSUPPORTED_API(release_interface); -} - -static int unsupported_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - PRINT_UNSUPPORTED_API(clear_halt); -} - -static int unsupported_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - PRINT_UNSUPPORTED_API(reset_device); -} - -static int unsupported_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_bulk_transfer); -} - -static int unsupported_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_iso_transfer); -} - -static int unsupported_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(submit_control_transfer); -} - -static int unsupported_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(abort_control); -} - -static int unsupported_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - PRINT_UNSUPPORTED_API(abort_transfers); -} - -static int unsupported_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - PRINT_UNSUPPORTED_API(copy_transfer_data); -} - -static int common_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - return LIBUSB_SUCCESS; -} - -// These names must be uppercase -static const char *hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30", "VHHUB", "AUSB3HUB"}; -static const char *composite_driver_names[] = {"USBCCGP"}; -static const char *winusbx_driver_names[] = WINUSBX_DRV_NAMES; -static const char *hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"}; -const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = { - { - USB_API_UNSUPPORTED, - "Unsupported API", - NULL, - 0, - unsupported_init, - unsupported_exit, - unsupported_open, - unsupported_close, - unsupported_configure_endpoints, - unsupported_claim_interface, - unsupported_set_interface_altsetting, - unsupported_release_interface, - unsupported_clear_halt, - unsupported_reset_device, - unsupported_submit_bulk_transfer, - unsupported_submit_iso_transfer, - unsupported_submit_control_transfer, - unsupported_abort_control, - unsupported_abort_transfers, - unsupported_copy_transfer_data, - }, - { - USB_API_HUB, - "HUB API", - hub_driver_names, - ARRAYSIZE(hub_driver_names), - unsupported_init, - unsupported_exit, - unsupported_open, - unsupported_close, - unsupported_configure_endpoints, - unsupported_claim_interface, - unsupported_set_interface_altsetting, - unsupported_release_interface, - unsupported_clear_halt, - unsupported_reset_device, - unsupported_submit_bulk_transfer, - unsupported_submit_iso_transfer, - unsupported_submit_control_transfer, - unsupported_abort_control, - unsupported_abort_transfers, - unsupported_copy_transfer_data, - }, - { - USB_API_COMPOSITE, - "Composite API", - composite_driver_names, - ARRAYSIZE(composite_driver_names), - composite_init, - composite_exit, - composite_open, - composite_close, - common_configure_endpoints, - composite_claim_interface, - composite_set_interface_altsetting, - composite_release_interface, - composite_clear_halt, - composite_reset_device, - composite_submit_bulk_transfer, - composite_submit_iso_transfer, - composite_submit_control_transfer, - composite_abort_control, - composite_abort_transfers, - composite_copy_transfer_data, - }, - { - USB_API_WINUSBX, - "WinUSB-like APIs", - winusbx_driver_names, - ARRAYSIZE(winusbx_driver_names), - winusbx_init, - winusbx_exit, - winusbx_open, - winusbx_close, - winusbx_configure_endpoints, - winusbx_claim_interface, - winusbx_set_interface_altsetting, - winusbx_release_interface, - winusbx_clear_halt, - winusbx_reset_device, - winusbx_submit_bulk_transfer, - unsupported_submit_iso_transfer, - winusbx_submit_control_transfer, - winusbx_abort_control, - winusbx_abort_transfers, - winusbx_copy_transfer_data, - }, - { - USB_API_HID, - "HID API", - hid_driver_names, - ARRAYSIZE(hid_driver_names), - hid_init, - hid_exit, - hid_open, - hid_close, - common_configure_endpoints, - hid_claim_interface, - hid_set_interface_altsetting, - hid_release_interface, - hid_clear_halt, - hid_reset_device, - hid_submit_bulk_transfer, - unsupported_submit_iso_transfer, - hid_submit_control_transfer, - hid_abort_transfers, - hid_abort_transfers, - hid_copy_transfer_data, - }, -}; - - -/* - * WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions - */ -#define WinUSBX_Set(fn) \ - do { \ - if (native_winusb) \ - WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \ - else \ - pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \ - } while (0) - -static int winusbx_init(int sub_api, struct libusb_context *ctx) -{ - HMODULE h; - bool native_winusb; - int i; - KLIB_VERSION LibK_Version; - LibK_GetProcAddress_t pLibK_GetProcAddress = NULL; - LibK_GetVersion_t pLibK_GetVersion; - - h = LoadLibraryA("libusbK"); - - if (h == NULL) { - usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB"); - h = LoadLibraryA("WinUSB"); - - if (h == NULL) { - usbi_warn(ctx, "WinUSB DLL is not available either, " - "you will not be able to access devices outside of enumeration"); - return LIBUSB_ERROR_NOT_FOUND; - } - } else { - usbi_dbg("using libusbK DLL for universal access"); - pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion"); - if (pLibK_GetVersion != NULL) { - pLibK_GetVersion(&LibK_Version); - usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor, - LibK_Version.Micro, LibK_Version.Nano); - } - pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress"); - if (pLibK_GetProcAddress == NULL) { - usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL"); - FreeLibrary(h); - return LIBUSB_ERROR_NOT_FOUND; - } - } - - native_winusb = (pLibK_GetProcAddress == NULL); - for (i = SUB_API_LIBUSBK; i < SUB_API_MAX; i++) { - WinUSBX_Set(AbortPipe); - WinUSBX_Set(ControlTransfer); - WinUSBX_Set(FlushPipe); - WinUSBX_Set(Free); - WinUSBX_Set(GetAssociatedInterface); - WinUSBX_Set(GetCurrentAlternateSetting); - WinUSBX_Set(GetDescriptor); - WinUSBX_Set(GetOverlappedResult); - WinUSBX_Set(GetPipePolicy); - WinUSBX_Set(GetPowerPolicy); - WinUSBX_Set(Initialize); - WinUSBX_Set(QueryDeviceInformation); - WinUSBX_Set(QueryInterfaceSettings); - WinUSBX_Set(QueryPipe); - WinUSBX_Set(ReadPipe); - WinUSBX_Set(ResetPipe); - WinUSBX_Set(SetCurrentAlternateSetting); - WinUSBX_Set(SetPipePolicy); - WinUSBX_Set(SetPowerPolicy); - WinUSBX_Set(WritePipe); - if (!native_winusb) - WinUSBX_Set(ResetDevice); - - if (WinUSBX[i].Initialize != NULL) { - WinUSBX[i].initialized = true; - usbi_dbg("initalized sub API %s", sub_api_name[i]); - } else { - usbi_warn(ctx, "Failed to initalize sub API %s", sub_api_name[i]); - WinUSBX[i].initialized = false; - } - } - - WinUSBX_handle = h; - return LIBUSB_SUCCESS; -} - -static int winusbx_exit(int sub_api) -{ - if (WinUSBX_handle != NULL) { - FreeLibrary(WinUSBX_handle); - WinUSBX_handle = NULL; - - /* Reset the WinUSBX API structures */ - memset(&WinUSBX, 0, sizeof(WinUSBX)); - } - - return LIBUSB_SUCCESS; -} - -// NB: open and close must ensure that they only handle interface of -// the right API type, as these functions can be called wholesale from -// composite_open(), with interfaces belonging to different APIs -static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - - HANDLE file_handle; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // WinUSB requires a separate handle for each interface - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) { - file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0)); - switch(GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ACCESS_DENIED: - return LIBUSB_ERROR_ACCESS; - default: - return LIBUSB_ERROR_IO; - } - } - handle_priv->interface_handle[i].dev_handle = file_handle; - } - } - - return LIBUSB_SUCCESS; -} - -static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE handle; - int i; - - if (sub_api == SUB_API_NOTSET) - sub_api = priv->sub_api; - - if (!WinUSBX[sub_api].initialized) - return; - - if (priv->apib->id == USB_API_COMPOSITE) { - // If this is a composite device, just free and close all WinUSB-like - // interfaces directly (each is independent and not associated with another) - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - - handle = handle_priv->interface_handle[i].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); - } - } - } else { - // If this is a WinUSB device, free all interfaces above interface 0, - // then free and close interface 0 last - for (i = 1; i < USB_MAXINTERFACES; i++) { - handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - } - handle = handle_priv->interface_handle[0].api_handle; - if (HANDLE_VALID(handle)) - WinUSBX[sub_api].Free(handle); - - handle = handle_priv->interface_handle[0].dev_handle; - if (HANDLE_VALID(handle)) - CloseHandle(handle); - } -} - -static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle = handle_priv->interface_handle[iface].api_handle; - UCHAR policy; - ULONG timeout = 0; - uint8_t endpoint_address; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // With handle and enpoints set (in parent), we can setup the default pipe properties - // see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx - for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) { - endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i]; - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout)) - usbi_dbg("failed to set PIPE_TRANSFER_TIMEOUT for control endpoint %02X", endpoint_address); - - if ((i == -1) || (sub_api == SUB_API_LIBUSB0)) - continue; // Other policies don't apply to control endpoint or libusb0 - - policy = false; - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - SHORT_PACKET_TERMINATE, sizeof(UCHAR), &policy)) - usbi_dbg("failed to disable SHORT_PACKET_TERMINATE for endpoint %02X", endpoint_address); - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - IGNORE_SHORT_PACKETS, sizeof(UCHAR), &policy)) - usbi_dbg("failed to disable IGNORE_SHORT_PACKETS for endpoint %02X", endpoint_address); - - policy = true; - /* ALLOW_PARTIAL_READS must be enabled due to likely libusbK bug. See: - https://sourceforge.net/mailarchive/message.php?msg_id=29736015 */ - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - ALLOW_PARTIAL_READS, sizeof(UCHAR), &policy)) - usbi_dbg("failed to enable ALLOW_PARTIAL_READS for endpoint %02X", endpoint_address); - - if (!WinUSBX[sub_api].SetPipePolicy(winusb_handle, endpoint_address, - AUTO_CLEAR_STALL, sizeof(UCHAR), &policy)) - usbi_dbg("failed to enable AUTO_CLEAR_STALL for endpoint %02X", endpoint_address); - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE); - SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL; - HDEVINFO dev_info = INVALID_HANDLE_VALUE; - SP_DEVINFO_DATA dev_info_data; - char *dev_path_no_guid = NULL; - char filter_path[] = "\\\\.\\libusb0-0000"; - bool found_filter = false; - HANDLE file_handle, winusb_handle; - DWORD err; - int i; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // If the device is composite, but using the default Windows composite parent driver (usbccgp) - // or if it's the first WinUSB-like interface, we get a handle through Initialize(). - if ((is_using_usbccgp) || (iface == 0)) { - // composite device (independent interfaces) or interface 0 - file_handle = handle_priv->interface_handle[iface].dev_handle; - if (!HANDLE_VALID(file_handle)) - return LIBUSB_ERROR_NOT_FOUND; - - if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - err = GetLastError(); - switch(err) { - case ERROR_BAD_COMMAND: - // The device was disconnected - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - default: - // it may be that we're using the libusb0 filter driver. - // TODO: can we move this whole business into the K/0 DLL? - for (i = 0; ; i++) { - safe_free(dev_interface_details); - safe_free(dev_path_no_guid); - - dev_interface_details = get_interface_details_filter(ctx, &dev_info, &dev_info_data, &GUID_DEVINTERFACE_LIBUSB0_FILTER, i, filter_path); - if ((found_filter) || (dev_interface_details == NULL)) - break; - - // ignore GUID part - dev_path_no_guid = sanitize_path(strtok(dev_interface_details->DevicePath, "{")); - if (dev_path_no_guid == NULL) - continue; - - if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) { - file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (file_handle != INVALID_HANDLE_VALUE) { - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - // Replace the existing file handle with the working one - CloseHandle(handle_priv->interface_handle[iface].dev_handle); - handle_priv->interface_handle[iface].dev_handle = file_handle; - found_filter = true; - } else { - usbi_err(ctx, "could not initialize filter driver for %s", filter_path); - CloseHandle(file_handle); - } - } else { - usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0)); - } - } - } - free(dev_interface_details); - if (!found_filter) { - usbi_err(ctx, "could not access interface %d: %s", iface, windows_error_str(err)); - return LIBUSB_ERROR_ACCESS; - } - } - } - handle_priv->interface_handle[iface].api_handle = winusb_handle; - } else { - // For all other interfaces, use GetAssociatedInterface() - winusb_handle = handle_priv->interface_handle[0].api_handle; - // It is a requirement for multiple interface devices on Windows that, to you - // must first claim the first interface before you claim the others - if (!HANDLE_VALID(winusb_handle)) { - file_handle = handle_priv->interface_handle[0].dev_handle; - if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) { - handle_priv->interface_handle[0].api_handle = winusb_handle; - usbi_warn(ctx, "auto-claimed interface 0 (required to claim %d with WinUSB)", iface); - } else { - usbi_warn(ctx, "failed to auto-claim interface 0 (required to claim %d with WinUSB): %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - if (!WinUSBX[sub_api].GetAssociatedInterface(winusb_handle, (UCHAR)(iface - 1), - &handle_priv->interface_handle[iface].api_handle)) { - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - switch(GetLastError()) { - case ERROR_NO_MORE_ITEMS: // invalid iface - return LIBUSB_ERROR_NOT_FOUND; - case ERROR_BAD_COMMAND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ALREADY_EXISTS: // already claimed - return LIBUSB_ERROR_BUSY; - default: - usbi_err(ctx, "could not claim interface %d: %s", iface, windows_error_str(0)); - return LIBUSB_ERROR_ACCESS; - } - } - } - usbi_dbg("claimed interface %d", iface); - handle_priv->active_interface = iface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - winusb_handle = handle_priv->interface_handle[iface].api_handle; - if (!HANDLE_VALID(winusb_handle)) - return LIBUSB_ERROR_NOT_FOUND; - - WinUSBX[sub_api].Free(winusb_handle); - handle_priv->interface_handle[iface].api_handle = INVALID_HANDLE_VALUE; - - return LIBUSB_SUCCESS; -} - -/* - * Return the first valid interface (of the same API type), for control transfers - */ -static int get_valid_interface(struct libusb_device_handle *dev_handle, int api_id) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int i; - - if ((api_id < USB_API_WINUSBX) || (api_id > USB_API_HID)) { - usbi_dbg("unsupported API ID"); - return -1; - } - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (HANDLE_VALID(handle_priv->interface_handle[i].dev_handle) - && HANDLE_VALID(handle_priv->interface_handle[i].api_handle) - && (priv->usb_interface[i].apib->id == api_id)) - return i; - } - - return -1; -} - -/* - * Lookup interface by endpoint address. -1 if not found - */ -static int interface_by_endpoint(struct windows_device_priv *priv, - struct windows_device_handle_priv *handle_priv, uint8_t endpoint_address) -{ - int i, j; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (!HANDLE_VALID(handle_priv->interface_handle[i].api_handle)) - continue; - if (priv->usb_interface[i].endpoint == NULL) - continue; - for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { - if (priv->usb_interface[i].endpoint[j] == endpoint_address) - return i; - } - } - - return -1; -} - -static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - ULONG size; - HANDLE winusb_handle; - int current_interface; - struct winfd wfd; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - transfer_priv->pollable_fd = INVALID_WINFD; - size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - // Windows places upper limits on the control transfer size - // See: https://msdn.microsoft.com/en-us/library/windows/hardware/ff538112.aspx - if (size > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - current_interface = get_valid_interface(transfer->dev_handle, USB_API_WINUSBX); - if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_WINUSBX) != LIBUSB_SUCCESS) - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("will use interface %d", current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - wfd = usbi_create_fd(winusb_handle, RW_READ, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - // Sending of set configuration control requests from WinUSB creates issues - if (((setup->request_type & (0x03 << 5)) == LIBUSB_REQUEST_TYPE_STANDARD) - && (setup->request == LIBUSB_REQUEST_SET_CONFIGURATION)) { - if (setup->value != priv->active_config) { - usbi_warn(ctx, "cannot set configuration other than the default one"); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_INVALID_PARAM; - } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = 0; - } else { - if (!WinUSBX[sub_api].ControlTransfer(wfd.handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, wfd.overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - } else { - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)size; - } - } - - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - if (altsetting > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - winusb_handle = handle_priv->interface_handle[iface].api_handle; - if (!HANDLE_VALID(winusb_handle)) { - usbi_err(ctx, "interface must be claimed first"); - return LIBUSB_ERROR_NOT_FOUND; - } - - if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) { - usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_IO; - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; - bool ret; - int current_interface; - struct winfd wfd; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - transfer_priv->pollable_fd = INVALID_WINFD; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - wfd = usbi_create_fd(winusb_handle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - if (IS_XFERIN(transfer)) { - usbi_dbg("reading %d bytes", transfer->length); - ret = WinUSBX[sub_api].ReadPipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); - } else { - usbi_dbg("writing %d bytes", transfer->length); - ret = WinUSBX[sub_api].WritePipe(wfd.handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, wfd.overlapped); - } - - if (!ret) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - return LIBUSB_ERROR_IO; - } - } else { - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = (DWORD)transfer->length; - } - - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return LIBUSB_SUCCESS; -} - -static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE winusb_handle; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) { - usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -/* - * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed - * through testing as well): - * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel - * the control transfer using CancelIo" - */ -static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - // Cancelling of the I/O is done in the parent - return LIBUSB_SUCCESS; -} - -static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - HANDLE winusb_handle; - int current_interface; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - current_interface = transfer_priv->interface_number; - if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) { - usbi_err(ctx, "program assertion failed: invalid interface_number"); - return LIBUSB_ERROR_NOT_FOUND; - } - usbi_dbg("will use interface %d", current_interface); - - winusb_handle = handle_priv->interface_handle[current_interface].api_handle; - - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -/* - * from the "How to Use WinUSB to Communicate with a USB Device" Microsoft white paper - * (http://www.microsoft.com/whdc/connect/usb/winusb_howto.mspx): - * "WinUSB does not support host-initiated reset port and cycle port operations" and - * IOCTL_INTERNAL_USB_CYCLE_PORT is only available in kernel mode and the - * IOCTL_USB_HUB_CYCLE_PORT ioctl was removed from Vista => the best we can do is - * cycle the pipes (and even then, the control pipe can not be reset using WinUSB) - */ -// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?) -static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct winfd wfd; - HANDLE winusb_handle; - int i, j; - - CHECK_WINUSBX_AVAILABLE(sub_api); - - // Reset any available pipe (except control) - for (i = 0; i < USB_MAXINTERFACES; i++) { - winusb_handle = handle_priv->interface_handle[i].api_handle; - for (wfd = handle_to_winfd(winusb_handle); wfd.fd > 0; ) { - // Cancel any pollable I/O - usbi_remove_pollfd(ctx, wfd.fd); - usbi_free_fd(&wfd); - wfd = handle_to_winfd(winusb_handle); - } - - if (HANDLE_VALID(winusb_handle)) { - for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) { - usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]); - if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) - usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - - // FlushPipe seems to fail on OUT pipes - if (IS_EPIN(priv->usb_interface[i].endpoint[j]) - && (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))) - usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - - if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j])) - usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s", - priv->usb_interface[i].endpoint[j], windows_error_str(0)); - } - } - } - - // libusbK & libusb0 have the ability to issue an actual device reset - if (WinUSBX[sub_api].ResetDevice != NULL) { - winusb_handle = handle_priv->interface_handle[0].api_handle; - if (HANDLE_VALID(winusb_handle)) - WinUSBX[sub_api].ResetDevice(winusb_handle); - } - - return LIBUSB_SUCCESS; -} - -static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - itransfer->transferred += io_size; - return LIBUSB_TRANSFER_COMPLETED; -} - -/* - * Internal HID Support functions (from libusb-win32) - * Note that functions that complete data transfer synchronously must return - * LIBUSB_COMPLETED instead of LIBUSB_SUCCESS - */ -static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size); -static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size); - -static int _hid_wcslen(WCHAR *str) -{ - int i = 0; - - while (str[i] && (str[i] != 0x409)) - i++; - - return i; -} - -static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - struct libusb_device_descriptor d; - - d.bLength = LIBUSB_DT_DEVICE_SIZE; - d.bDescriptorType = LIBUSB_DT_DEVICE; - d.bcdUSB = 0x0200; /* 2.00 */ - d.bDeviceClass = 0; - d.bDeviceSubClass = 0; - d.bDeviceProtocol = 0; - d.bMaxPacketSize0 = 64; /* fix this! */ - d.idVendor = (uint16_t)dev->vid; - d.idProduct = (uint16_t)dev->pid; - d.bcdDevice = 0x0100; - d.iManufacturer = dev->string_index[0]; - d.iProduct = dev->string_index[1]; - d.iSerialNumber = dev->string_index[2]; - d.bNumConfigurations = 1; - - if (*size > LIBUSB_DT_DEVICE_SIZE) - *size = LIBUSB_DT_DEVICE_SIZE; - memcpy(data, &d, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - char num_endpoints = 0; - size_t config_total_len = 0; - char tmp[HID_MAX_CONFIG_DESC_SIZE]; - struct libusb_config_descriptor *cd; - struct libusb_interface_descriptor *id; - struct libusb_hid_descriptor *hd; - struct libusb_endpoint_descriptor *ed; - size_t tmp_size; - - if (dev->input_report_size) - num_endpoints++; - if (dev->output_report_size) - num_endpoints++; - - config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE - + LIBUSB_DT_HID_SIZE + num_endpoints * LIBUSB_DT_ENDPOINT_SIZE; - - cd = (struct libusb_config_descriptor *)tmp; - id = (struct libusb_interface_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE); - hd = (struct libusb_hid_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE - + LIBUSB_DT_INTERFACE_SIZE); - ed = (struct libusb_endpoint_descriptor *)(tmp + LIBUSB_DT_CONFIG_SIZE - + LIBUSB_DT_INTERFACE_SIZE - + LIBUSB_DT_HID_SIZE); - - cd->bLength = LIBUSB_DT_CONFIG_SIZE; - cd->bDescriptorType = LIBUSB_DT_CONFIG; - cd->wTotalLength = (uint16_t)config_total_len; - cd->bNumInterfaces = 1; - cd->bConfigurationValue = 1; - cd->iConfiguration = 0; - cd->bmAttributes = 1 << 7; /* bus powered */ - cd->MaxPower = 50; - - id->bLength = LIBUSB_DT_INTERFACE_SIZE; - id->bDescriptorType = LIBUSB_DT_INTERFACE; - id->bInterfaceNumber = 0; - id->bAlternateSetting = 0; - id->bNumEndpoints = num_endpoints; - id->bInterfaceClass = 3; - id->bInterfaceSubClass = 0; - id->bInterfaceProtocol = 0; - id->iInterface = 0; - - tmp_size = LIBUSB_DT_HID_SIZE; - _hid_get_hid_descriptor(dev, hd, &tmp_size); - - if (dev->input_report_size) { - ed->bLength = LIBUSB_DT_ENDPOINT_SIZE; - ed->bDescriptorType = LIBUSB_DT_ENDPOINT; - ed->bEndpointAddress = HID_IN_EP; - ed->bmAttributes = 3; - ed->wMaxPacketSize = dev->input_report_size - 1; - ed->bInterval = 10; - ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE); - } - - if (dev->output_report_size) { - ed->bLength = LIBUSB_DT_ENDPOINT_SIZE; - ed->bDescriptorType = LIBUSB_DT_ENDPOINT; - ed->bEndpointAddress = HID_OUT_EP; - ed->bmAttributes = 3; - ed->wMaxPacketSize = dev->output_report_size - 1; - ed->bInterval = 10; - } - - if (*size > config_total_len) - *size = config_total_len; - memcpy(data, tmp, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index, - void *data, size_t *size) -{ - void *tmp = NULL; - size_t tmp_size = 0; - int i; - - /* language ID, EN-US */ - char string_langid[] = {0x09, 0x04}; - - if ((*size < 2) || (*size > 255)) - return LIBUSB_ERROR_OVERFLOW; - - if (_index == 0) { - tmp = string_langid; - tmp_size = sizeof(string_langid) + 2; - } else { - for (i = 0; i < 3; i++) { - if (_index == (dev->string_index[i])) { - tmp = dev->string[i]; - tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR); - break; - } - } - - if (i == 3) // not found - return LIBUSB_ERROR_INVALID_PARAM; - } - - if (!tmp_size) - return LIBUSB_ERROR_INVALID_PARAM; - - if (tmp_size < *size) - *size = tmp_size; - - // 2 byte header - ((uint8_t *)data)[0] = (uint8_t)*size; - ((uint8_t *)data)[1] = LIBUSB_DT_STRING; - memcpy((uint8_t *)data + 2, tmp, *size - 2); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - struct libusb_hid_descriptor d; - uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE]; - size_t report_len = MAX_HID_DESCRIPTOR_SIZE; - - _hid_get_report_descriptor(dev, tmp, &report_len); - - d.bLength = LIBUSB_DT_HID_SIZE; - d.bDescriptorType = LIBUSB_DT_HID; - d.bcdHID = 0x0110; /* 1.10 */ - d.bCountryCode = 0; - d.bNumDescriptors = 1; - d.bClassDescriptorType = LIBUSB_DT_REPORT; - d.wClassDescriptorLength = (uint16_t)report_len; - - if (*size > LIBUSB_DT_HID_SIZE) - *size = LIBUSB_DT_HID_SIZE; - memcpy(data, &d, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size) -{ - uint8_t d[MAX_HID_DESCRIPTOR_SIZE]; - size_t i = 0; - - /* usage page (0xFFA0 == vendor defined) */ - d[i++] = 0x06; d[i++] = 0xA0; d[i++] = 0xFF; - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x01; - /* start collection (application) */ - d[i++] = 0xA1; d[i++] = 0x01; - /* input report */ - if (dev->input_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x01; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1; - /* input (data, variable, absolute) */ - d[i++] = 0x81; d[i++] = 0x00; - } - /* output report */ - if (dev->output_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x02; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1; - /* output (data, variable, absolute) */ - d[i++] = 0x91; d[i++] = 0x00; - } - /* feature report */ - if (dev->feature_report_size) { - /* usage (vendor defined) */ - d[i++] = 0x09; d[i++] = 0x03; - /* logical minimum (0) */ - d[i++] = 0x15; d[i++] = 0x00; - /* logical maximum (255) */ - d[i++] = 0x25; d[i++] = 0xFF; - /* report size (8 bits) */ - d[i++] = 0x75; d[i++] = 0x08; - /* report count */ - d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1; - /* feature (data, variable, absolute) */ - d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01; - } - - /* end collection */ - d[i++] = 0xC0; - - if (*size > i) - *size = i; - memcpy(data, d, *size); - - return LIBUSB_COMPLETED; -} - -static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient, - int type, int _index, void *data, size_t *size) -{ - switch(type) { - case LIBUSB_DT_DEVICE: - usbi_dbg("LIBUSB_DT_DEVICE"); - return _hid_get_device_descriptor(dev, data, size); - case LIBUSB_DT_CONFIG: - usbi_dbg("LIBUSB_DT_CONFIG"); - if (!_index) - return _hid_get_config_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_STRING: - usbi_dbg("LIBUSB_DT_STRING"); - return _hid_get_string_descriptor(dev, _index, data, size); - case LIBUSB_DT_HID: - usbi_dbg("LIBUSB_DT_HID"); - if (!_index) - return _hid_get_hid_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_REPORT: - usbi_dbg("LIBUSB_DT_REPORT"); - if (!_index) - return _hid_get_report_descriptor(dev, data, size); - return LIBUSB_ERROR_INVALID_PARAM; - case LIBUSB_DT_PHYSICAL: - usbi_dbg("LIBUSB_DT_PHYSICAL"); - if (HidD_GetPhysicalDescriptor(hid_handle, data, (ULONG)*size)) - return LIBUSB_COMPLETED; - return LIBUSB_ERROR_OTHER; - } - - usbi_dbg("unsupported"); - return LIBUSB_ERROR_NOT_SUPPORTED; -} - -static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data, - struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) -{ - uint8_t *buf; - DWORD ioctl_code, read_size, expected_size = (DWORD)*size; - int r = LIBUSB_SUCCESS; - - if (tp->hid_buffer != NULL) - usbi_dbg("program assertion failed: hid_buffer is not NULL"); - - if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { - usbi_dbg("invalid size (%u)", *size); - return LIBUSB_ERROR_INVALID_PARAM; - } - - switch (report_type) { - case HID_REPORT_TYPE_INPUT: - ioctl_code = IOCTL_HID_GET_INPUT_REPORT; - break; - case HID_REPORT_TYPE_FEATURE: - ioctl_code = IOCTL_HID_GET_FEATURE; - break; - default: - usbi_dbg("unknown HID report type %d", report_type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - // Add a trailing byte to detect overflows - buf = calloc(1, expected_size + 1); - if (buf == NULL) - return LIBUSB_ERROR_NO_MEM; - - buf[0] = (uint8_t)id; // Must be set always - usbi_dbg("report ID: 0x%02X", buf[0]); - - tp->hid_expected_size = expected_size; - read_size = expected_size; - - // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0) - if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1, - buf, expected_size + 1, &read_size, overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0)); - free(buf); - return LIBUSB_ERROR_IO; - } - // Asynchronous wait - tp->hid_buffer = buf; - tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer - return LIBUSB_SUCCESS; - } - - // Transfer completed synchronously => copy and discard extra buffer - if (read_size == 0) { - usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read"); - *size = 0; - } else { - if (buf[0] != id) - usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id); - - if ((size_t)read_size > expected_size) { - r = LIBUSB_ERROR_OVERFLOW; - usbi_dbg("OVERFLOW!"); - } else { - r = LIBUSB_COMPLETED; - } - - *size = MIN((size_t)read_size, *size); - if (id == 0) - memcpy(data, buf + 1, *size); // Discard report ID - else - memcpy(data, buf, *size); - } - - free(buf); - return r; -} - -static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data, - struct windows_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type) -{ - uint8_t *buf = NULL; - DWORD ioctl_code, write_size = (DWORD)*size; - - if (tp->hid_buffer != NULL) - usbi_dbg("program assertion failed: hid_buffer is not NULL"); - - if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) { - usbi_dbg("invalid size (%u)", *size); - return LIBUSB_ERROR_INVALID_PARAM; - } - - switch (report_type) { - case HID_REPORT_TYPE_OUTPUT: - ioctl_code = IOCTL_HID_SET_OUTPUT_REPORT; - break; - case HID_REPORT_TYPE_FEATURE: - ioctl_code = IOCTL_HID_SET_FEATURE; - break; - default: - usbi_dbg("unknown HID report type %d", report_type); - return LIBUSB_ERROR_INVALID_PARAM; - } - - usbi_dbg("report ID: 0x%02X", id); - // When report IDs are not used (i.e. when id == 0), we must add - // a null report ID. Otherwise, we just use original data buffer - if (id == 0) - write_size++; - - buf = malloc(write_size); - if (buf == NULL) - return LIBUSB_ERROR_NO_MEM; - - if (id == 0) { - buf[0] = 0; - memcpy(buf + 1, data, *size); - } else { - // This seems like a waste, but if we don't duplicate the - // data, we'll get issues when freeing hid_buffer - memcpy(buf, data, *size); - if (buf[0] != id) - usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id); - } - - // NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0) - if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size, - buf, write_size, &write_size, overlapped)) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0)); - free(buf); - return LIBUSB_ERROR_IO; - } - tp->hid_buffer = buf; - tp->hid_dest = NULL; - return LIBUSB_SUCCESS; - } - - // Transfer completed synchronously - *size = write_size; - if (write_size == 0) - usbi_dbg("program assertion failed - write completed synchronously, but no data was written"); - - free(buf); - return LIBUSB_COMPLETED; -} - -static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type, - int request, int value, int _index, void *data, struct windows_transfer_priv *tp, - size_t *size, OVERLAPPED *overlapped) -{ - int report_type = (value >> 8) & 0xFF; - int report_id = value & 0xFF; - - if ((LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_INTERFACE) - && (LIBUSB_REQ_RECIPIENT(request_type) != LIBUSB_RECIPIENT_DEVICE)) - return LIBUSB_ERROR_INVALID_PARAM; - - if (LIBUSB_REQ_OUT(request_type) && request == HID_REQ_SET_REPORT) - return _hid_set_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type); - - if (LIBUSB_REQ_IN(request_type) && request == HID_REQ_GET_REPORT) - return _hid_get_report(dev, hid_handle, report_id, data, tp, size, overlapped, report_type); - - return LIBUSB_ERROR_INVALID_PARAM; -} - - -/* - * HID API functions - */ -static int hid_init(int sub_api, struct libusb_context *ctx) -{ - DLL_GET_HANDLE(hid); - DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE); - DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE); - DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE); - DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE); - DLL_LOAD_FUNC(hid, HidD_SetFeature, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetFeature, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE); - DLL_LOAD_FUNC(hid, HidD_GetInputReport, FALSE); - DLL_LOAD_FUNC(hid, HidD_SetOutputReport, FALSE); - DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE); - DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE); - - api_hid_available = true; - return LIBUSB_SUCCESS; -} - -static int hid_exit(int sub_api) -{ - DLL_FREE_HANDLE(hid); - - return LIBUSB_SUCCESS; -} - -// NB: open and close must ensure that they only handle interface of -// the right API type, as these functions can be called wholesale from -// composite_open(), with interfaces belonging to different APIs -static int hid_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HIDD_ATTRIBUTES hid_attributes; - PHIDP_PREPARSED_DATA preparsed_data = NULL; - HIDP_CAPS capabilities; - HIDP_VALUE_CAPS *value_caps; - HANDLE hid_handle = INVALID_HANDLE_VALUE; - int i, j; - // report IDs handling - ULONG size[3]; - int nb_ids[2]; // zero and nonzero report IDs -#if defined(ENABLE_LOGGING) - const char *type[3] = {"input", "output", "feature"}; -#endif - - CHECK_HID_AVAILABLE; - - if (priv->hid == NULL) { - usbi_err(ctx, "program assertion failed - private HID structure is unitialized"); - return LIBUSB_ERROR_NOT_FOUND; - } - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].path != NULL) - && (priv->usb_interface[i].apib->id == USB_API_HID)) { - hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - /* - * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID? - * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system - * keyboards or mice. An application can obtain a handle to a system keyboard or mouse by not - * requesting READ or WRITE access with CreateFile. Applications can then use HidD_SetFeature and - * HidD_GetFeature (if the device supports Feature reports)." - */ - if (hid_handle == INVALID_HANDLE_VALUE) { - usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without"); - hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - if (hid_handle == INVALID_HANDLE_VALUE) { - usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0)); - switch(GetLastError()) { - case ERROR_FILE_NOT_FOUND: // The device was disconnected - return LIBUSB_ERROR_NO_DEVICE; - case ERROR_ACCESS_DENIED: - return LIBUSB_ERROR_ACCESS; - default: - return LIBUSB_ERROR_IO; - } - } - priv->usb_interface[i].restricted_functionality = true; - } - handle_priv->interface_handle[i].api_handle = hid_handle; - } - } - - hid_attributes.Size = sizeof(hid_attributes); - do { - if (!HidD_GetAttributes(hid_handle, &hid_attributes)) { - usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)"); - break; - } - - priv->hid->vid = hid_attributes.VendorID; - priv->hid->pid = hid_attributes.ProductID; - - // Set the maximum available input buffer size - for (i = 32; HidD_SetNumInputBuffers(hid_handle, i); i *= 2); - usbi_dbg("set maximum input buffer size to %d", i / 2); - - // Get the maximum input and output report size - if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) { - usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)"); - break; - } - if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) { - usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)"); - break; - } - - // Find out if interrupt will need report IDs - size[0] = capabilities.NumberInputValueCaps; - size[1] = capabilities.NumberOutputValueCaps; - size[2] = capabilities.NumberFeatureValueCaps; - for (j = HidP_Input; j <= HidP_Feature; j++) { - usbi_dbg("%u HID %s report value(s) found", (unsigned int)size[j], type[j]); - priv->hid->uses_report_ids[j] = false; - if (size[j] > 0) { - value_caps = calloc(size[j], sizeof(HIDP_VALUE_CAPS)); - if ((value_caps != NULL) - && (HidP_GetValueCaps((HIDP_REPORT_TYPE)j, value_caps, &size[j], preparsed_data) == HIDP_STATUS_SUCCESS) - && (size[j] >= 1)) { - nb_ids[0] = 0; - nb_ids[1] = 0; - for (i = 0; i < (int)size[j]; i++) { - usbi_dbg(" Report ID: 0x%02X", value_caps[i].ReportID); - if (value_caps[i].ReportID != 0) - nb_ids[1]++; - else - nb_ids[0]++; - } - if (nb_ids[1] != 0) { - if (nb_ids[0] != 0) - usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s", - type[j]); - priv->hid->uses_report_ids[j] = true; - } - } else { - usbi_warn(ctx, " could not process %s report IDs", type[j]); - } - free(value_caps); - } - } - - // Set the report sizes - priv->hid->input_report_size = capabilities.InputReportByteLength; - priv->hid->output_report_size = capabilities.OutputReportByteLength; - priv->hid->feature_report_size = capabilities.FeatureReportByteLength; - - // Fetch string descriptors - priv->hid->string_index[0] = priv->dev_descriptor.iManufacturer; - if (priv->hid->string_index[0] != 0) - HidD_GetManufacturerString(hid_handle, priv->hid->string[0], sizeof(priv->hid->string[0])); - else - priv->hid->string[0][0] = 0; - - priv->hid->string_index[1] = priv->dev_descriptor.iProduct; - if (priv->hid->string_index[1] != 0) - HidD_GetProductString(hid_handle, priv->hid->string[1], sizeof(priv->hid->string[1])); - else - priv->hid->string[1][0] = 0; - - priv->hid->string_index[2] = priv->dev_descriptor.iSerialNumber; - if (priv->hid->string_index[2] != 0) - HidD_GetSerialNumberString(hid_handle, priv->hid->string[2], sizeof(priv->hid->string[2])); - else - priv->hid->string[2][0] = 0; - } while(0); - - if (preparsed_data) - HidD_FreePreparsedData(preparsed_data); - - return LIBUSB_SUCCESS; -} - -static void hid_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HANDLE file_handle; - int i; - - if (!api_hid_available) - return; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if (priv->usb_interface[i].apib->id == USB_API_HID) { - file_handle = handle_priv->interface_handle[i].api_handle; - if (HANDLE_VALID(file_handle)) - CloseHandle(file_handle); - } - } -} - -static int hid_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - // NB: Disconnection detection is not possible in this function - if (priv->usb_interface[iface].path == NULL) - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - - // We use dev_handle as a flag for interface claimed - if (handle_priv->interface_handle[iface].dev_handle == INTERFACE_CLAIMED) - return LIBUSB_ERROR_BUSY; // already claimed - - - handle_priv->interface_handle[iface].dev_handle = INTERFACE_CLAIMED; - - usbi_dbg("claimed interface %d", iface); - handle_priv->active_interface = iface; - - return LIBUSB_SUCCESS; -} - -static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - if (priv->usb_interface[iface].path == NULL) - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - - if (handle_priv->interface_handle[iface].dev_handle != INTERFACE_CLAIMED) - return LIBUSB_ERROR_NOT_FOUND; // invalid iface - - handle_priv->interface_handle[iface].dev_handle = INVALID_HANDLE_VALUE; - - return LIBUSB_SUCCESS; -} - -static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - - CHECK_HID_AVAILABLE; - - if (altsetting > 255) - return LIBUSB_ERROR_INVALID_PARAM; - - if (altsetting != 0) { - usbi_err(ctx, "set interface altsetting not supported for altsetting >0"); - return LIBUSB_ERROR_NOT_SUPPORTED; - } - - return LIBUSB_SUCCESS; -} - -static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - HANDLE hid_handle; - struct winfd wfd; - int current_interface, config; - size_t size; - int r = LIBUSB_ERROR_INVALID_PARAM; - - CHECK_HID_AVAILABLE; - - transfer_priv->pollable_fd = INVALID_WINFD; - safe_free(transfer_priv->hid_buffer); - transfer_priv->hid_dest = NULL; - size = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; - - if (size > MAX_CTRL_BUFFER_LENGTH) - return LIBUSB_ERROR_INVALID_PARAM; - - current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID); - if (current_interface < 0) { - if (auto_claim(transfer, ¤t_interface, USB_API_HID) != LIBUSB_SUCCESS) - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("will use interface %d", current_interface); - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - // Always use the handle returned from usbi_create_fd (wfd.handle) - wfd = usbi_create_fd(hid_handle, RW_READ, NULL, NULL); - if (wfd.fd < 0) - return LIBUSB_ERROR_NOT_FOUND; - - switch(LIBUSB_REQ_TYPE(setup->request_type)) { - case LIBUSB_REQUEST_TYPE_STANDARD: - switch(setup->request) { - case LIBUSB_REQUEST_GET_DESCRIPTOR: - r = _hid_get_descriptor(priv->hid, wfd.handle, LIBUSB_REQ_RECIPIENT(setup->request_type), - (setup->value >> 8) & 0xFF, setup->value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size); - break; - case LIBUSB_REQUEST_GET_CONFIGURATION: - r = windows_get_configuration(transfer->dev_handle, &config); - if (r == LIBUSB_SUCCESS) { - size = 1; - ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config; - r = LIBUSB_COMPLETED; - } - break; - case LIBUSB_REQUEST_SET_CONFIGURATION: - if (setup->value == priv->active_config) { - r = LIBUSB_COMPLETED; - } else { - usbi_warn(ctx, "cannot set configuration other than the default one"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - } - break; - case LIBUSB_REQUEST_GET_INTERFACE: - size = 1; - ((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = 0; - r = LIBUSB_COMPLETED; - break; - case LIBUSB_REQUEST_SET_INTERFACE: - r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->index, setup->value); - if (r == LIBUSB_SUCCESS) - r = LIBUSB_COMPLETED; - break; - default: - usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - break; - case LIBUSB_REQUEST_TYPE_CLASS: - r = _hid_class_request(priv->hid, wfd.handle, setup->request_type, setup->request, setup->value, - setup->index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv, - &size, wfd.overlapped); - break; - default: - usbi_warn(ctx, "unsupported HID control request"); - r = LIBUSB_ERROR_NOT_SUPPORTED; - break; - } - - if (r == LIBUSB_COMPLETED) { - // Force request to be completed synchronously. Transferred size has been set by previous call - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - // http://msdn.microsoft.com/en-us/library/ms684342%28VS.85%29.aspx - // set InternalHigh to the number of bytes transferred - wfd.overlapped->InternalHigh = (DWORD)size; - r = LIBUSB_SUCCESS; - } - - if (r == LIBUSB_SUCCESS) { - // Use priv_transfer to store data needed for async polling - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - } else { - usbi_free_fd(&wfd); - } - - return r; -} - -static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct winfd wfd; - HANDLE hid_handle; - bool direction_in, ret; - int current_interface, length; - DWORD size; - int r = LIBUSB_SUCCESS; - - CHECK_HID_AVAILABLE; - - transfer_priv->pollable_fd = INVALID_WINFD; - transfer_priv->hid_dest = NULL; - safe_free(transfer_priv->hid_buffer); - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface); - - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; - - wfd = usbi_create_fd(hid_handle, direction_in?RW_READ:RW_WRITE, NULL, NULL); - // Always use the handle returned from usbi_create_fd (wfd.handle) - if (wfd.fd < 0) - return LIBUSB_ERROR_NO_MEM; - - // If report IDs are not in use, an extra prefix byte must be added - if (((direction_in) && (!priv->hid->uses_report_ids[0])) - || ((!direction_in) && (!priv->hid->uses_report_ids[1]))) - length = transfer->length + 1; - else - length = transfer->length; - - // Add a trailing byte to detect overflows on input - transfer_priv->hid_buffer = calloc(1, length + 1); - if (transfer_priv->hid_buffer == NULL) - return LIBUSB_ERROR_NO_MEM; - - transfer_priv->hid_expected_size = length; - - if (direction_in) { - transfer_priv->hid_dest = transfer->buffer; - usbi_dbg("reading %d bytes (report ID: 0x00)", length); - ret = ReadFile(wfd.handle, transfer_priv->hid_buffer, length + 1, &size, wfd.overlapped); - } else { - if (!priv->hid->uses_report_ids[1]) - memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length); - else - // We could actually do without the calloc and memcpy in this case - memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length); - - usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]); - ret = WriteFile(wfd.handle, transfer_priv->hid_buffer, length, &size, wfd.overlapped); - } - - if (!ret) { - if (GetLastError() != ERROR_IO_PENDING) { - usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0)); - usbi_free_fd(&wfd); - safe_free(transfer_priv->hid_buffer); - return LIBUSB_ERROR_IO; - } - } else { - // Only write operations that completed synchronously need to free up - // hid_buffer. For reads, copy_transfer_data() handles that process. - if (!direction_in) - safe_free(transfer_priv->hid_buffer); - - if (size == 0) { - usbi_err(ctx, "program assertion failed - no data was transferred"); - size = 1; - } - if (size > (size_t)length) { - usbi_err(ctx, "OVERFLOW!"); - r = LIBUSB_ERROR_OVERFLOW; - } - wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; - wfd.overlapped->InternalHigh = size; - } - - transfer_priv->pollable_fd = wfd; - transfer_priv->interface_number = (uint8_t)current_interface; - - return r; -} - -static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - current_interface = transfer_priv->interface_number; - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - CancelIo(hid_handle); - - return LIBUSB_SUCCESS; -} - -static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - // Flushing the queues on all interfaces is the best we can achieve - for (current_interface = 0; current_interface < USB_MAXINTERFACES; current_interface++) { - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - if (HANDLE_VALID(hid_handle)) - HidD_FlushQueue(hid_handle); - } - - return LIBUSB_SUCCESS; -} - -static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - HANDLE hid_handle; - int current_interface; - - CHECK_HID_AVAILABLE; - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_dbg("matched endpoint %02X with interface %d", endpoint, current_interface); - hid_handle = handle_priv->interface_handle[current_interface].api_handle; - - // No endpoint selection with Microsoft's implementation, so we try to flush the - // whole interface. Should be OK for most case scenarios - if (!HidD_FlushQueue(hid_handle)) { - usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0)); - // Device was probably disconnected - return LIBUSB_ERROR_NO_DEVICE; - } - - return LIBUSB_SUCCESS; -} - -// This extra function is only needed for HID -static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - int r = LIBUSB_TRANSFER_COMPLETED; - uint32_t corrected_size = io_size; - - if (transfer_priv->hid_buffer != NULL) { - // If we have a valid hid_buffer, it means the transfer was async - if (transfer_priv->hid_dest != NULL) { // Data readout - if (corrected_size > 0) { - // First, check for overflow - if (corrected_size > transfer_priv->hid_expected_size) { - usbi_err(ctx, "OVERFLOW!"); - corrected_size = (uint32_t)transfer_priv->hid_expected_size; - r = LIBUSB_TRANSFER_OVERFLOW; - } - - if (transfer_priv->hid_buffer[0] == 0) { - // Discard the 1 byte report ID prefix - corrected_size--; - memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size); - } else { - memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size); - } - } - transfer_priv->hid_dest = NULL; - } - // For write, we just need to free the hid buffer - safe_free(transfer_priv->hid_buffer); - } - - itransfer->transferred += corrected_size; - return r; -} - - -/* - * Composite API functions - */ -static int composite_init(int sub_api, struct libusb_context *ctx) -{ - return LIBUSB_SUCCESS; -} - -static int composite_exit(int sub_api) -{ - return LIBUSB_SUCCESS; -} - -static int composite_open(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int r = LIBUSB_ERROR_NOT_FOUND; - uint8_t i; - // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX + 1] = { 0 }; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - switch (priv->usb_interface[i].apib->id) { - case USB_API_WINUSBX: - if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) - available[priv->usb_interface[i].sub_api] = true; - break; - case USB_API_HID: - available[SUB_API_MAX] = true; - break; - default: - break; - } - } - - for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers - if (available[i]) { - r = usb_api_backend[USB_API_WINUSBX].open(i, dev_handle); - if (r != LIBUSB_SUCCESS) - return r; - } - } - - if (available[SUB_API_MAX]) // HID driver - r = hid_open(SUB_API_NOTSET, dev_handle); - - return r; -} - -static void composite_close(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - uint8_t i; - // SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID - bool available[SUB_API_MAX + 1] = { 0 }; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - switch (priv->usb_interface[i].apib->id) { - case USB_API_WINUSBX: - if (priv->usb_interface[i].sub_api != SUB_API_NOTSET) - available[priv->usb_interface[i].sub_api] = true; - break; - case USB_API_HID: - available[SUB_API_MAX] = true; - break; - default: - break; - } - } - - for (i = 0; i < SUB_API_MAX; i++) { // WinUSB-like drivers - if (available[i]) - usb_api_backend[USB_API_WINUSBX].close(i, dev_handle); - } - - if (available[SUB_API_MAX]) // HID driver - hid_close(SUB_API_NOTSET, dev_handle); -} - -static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->usb_interface[iface].apib-> - claim_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); -} - -static int composite_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->usb_interface[iface].apib-> - set_interface_altsetting(priv->usb_interface[iface].sub_api, dev_handle, iface, altsetting); -} - -static int composite_release_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - - return priv->usb_interface[iface].apib-> - release_interface(priv->usb_interface[iface].sub_api, dev_handle, iface); -} - -static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - struct libusb_config_descriptor *conf_desc; - WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer; - int iface, pass, r; - - // Interface shouldn't matter for control, but it does in practice, with Windows' - // restrictions with regards to accessing HID keyboards and mice. Try to target - // a specific interface first, if possible. - switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) { - case LIBUSB_RECIPIENT_INTERFACE: - iface = setup->index & 0xFF; - break; - case LIBUSB_RECIPIENT_ENDPOINT: - r = libusb_get_active_config_descriptor(transfer->dev_handle->dev, &conf_desc); - if (r == LIBUSB_SUCCESS) { - iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF)); - libusb_free_config_descriptor(conf_desc); - break; - } - // Fall through if not able to determine interface - default: - iface = -1; - break; - } - - // Try and target a specific interface if the control setup indicates such - if ((iface >= 0) && (iface < USB_MAXINTERFACES)) { - usbi_dbg("attempting control transfer targeted to interface %d", iface); - if (priv->usb_interface[iface].path != NULL) { - r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - if (r == LIBUSB_SUCCESS) - return r; - } - } - - // Either not targeted to a specific interface or no luck in doing so. - // Try a 2 pass approach with all interfaces. - for (pass = 0; pass < 2; pass++) { - for (iface = 0; iface < USB_MAXINTERFACES; iface++) { - if (priv->usb_interface[iface].path != NULL) { - if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) { - usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface); - continue; - } - usbi_dbg("using interface %d", iface); - r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer); - // If not supported on this API, it may be supported on another, so don't give up yet!! - if (r == LIBUSB_ERROR_NOT_SUPPORTED) - continue; - return r; - } - } - } - - usbi_err(ctx, "no libusb supported interfaces to complete request"); - return LIBUSB_ERROR_NOT_FOUND; -} - -static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - return priv->usb_interface[current_interface].apib-> - submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) { - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer"); - return LIBUSB_ERROR_NOT_FOUND; - } - - return priv->usb_interface[current_interface].apib-> - submit_iso_transfer(priv->usb_interface[current_interface].sub_api, itransfer); -} - -static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint) -{ - struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev); - struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle); - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int current_interface; - - current_interface = interface_by_endpoint(priv, handle_priv, endpoint); - if (current_interface < 0) { - usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear"); - return LIBUSB_ERROR_NOT_FOUND; - } - - return priv->usb_interface[current_interface].apib-> - clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint); -} - -static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_control(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); -} - -static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->usb_interface[transfer_priv->interface_number].apib-> - abort_transfers(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer); -} - -static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle) -{ - struct windows_device_priv *priv = _device_priv(dev_handle->dev); - int r; - uint8_t i; - bool available[SUB_API_MAX]; - - for (i = 0; i < SUB_API_MAX; i++) - available[i] = false; - - for (i = 0; i < USB_MAXINTERFACES; i++) { - if ((priv->usb_interface[i].apib->id == USB_API_WINUSBX) - && (priv->usb_interface[i].sub_api != SUB_API_NOTSET)) - available[priv->usb_interface[i].sub_api] = true; - } - - for (i = 0; i < SUB_API_MAX; i++) { - if (available[i]) { - r = usb_api_backend[USB_API_WINUSBX].reset_device(i, dev_handle); - if (r != LIBUSB_SUCCESS) - return r; - } - } - - return LIBUSB_SUCCESS; -} - -static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size) -{ - struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); - struct windows_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); - struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev); - - return priv->usb_interface[transfer_priv->interface_number].apib-> - copy_transfer_data(priv->usb_interface[transfer_priv->interface_number].sub_api, itransfer, io_size); -} - -#endif /* !USE_USBDK */ diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_winusb.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_winusb.h deleted file mode 100644 index b7b9cd919a9..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/os/windows_winusb.h +++ /dev/null @@ -1,937 +0,0 @@ -/* - * Windows backend for libusb 1.0 - * Copyright © 2009-2012 Pete Batard - * With contributions from Michael Plante, Orin Eman et al. - * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer - * Major code testing contribution by Xiaofan Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "windows_common.h" -#include "windows_nt_common.h" - -#if defined(_MSC_VER) -// disable /W4 MSVC warnings that are benign -#pragma warning(disable:4100) // unreferenced formal parameter -#pragma warning(disable:4127) // conditional expression is constant -#pragma warning(disable:4201) // nameless struct/union -#pragma warning(disable:4214) // bit field types other than int -#pragma warning(disable:4996) // deprecated API calls -#pragma warning(disable:28159) // more deprecated API calls -#endif - -// Missing from MSVC6 setupapi.h -#if !defined(SPDRP_ADDRESS) -#define SPDRP_ADDRESS 28 -#endif -#if !defined(SPDRP_INSTALL_STATE) -#define SPDRP_INSTALL_STATE 34 -#endif - -#define MAX_CTRL_BUFFER_LENGTH 4096 -#define MAX_USB_DEVICES 256 -#define MAX_USB_STRING_LENGTH 128 -#define MAX_HID_REPORT_SIZE 1024 -#define MAX_HID_DESCRIPTOR_SIZE 256 -#define MAX_GUID_STRING_LENGTH 40 -#define MAX_PATH_LENGTH 128 -#define MAX_KEY_LENGTH 256 -#define LIST_SEPARATOR ';' - -// Handle code for HID interface that have been claimed ("dibs") -#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5) -// Additional return code for HID operations that completed synchronously -#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) - -// http://msdn.microsoft.com/en-us/library/ff545978.aspx -// http://msdn.microsoft.com/en-us/library/ff545972.aspx -// http://msdn.microsoft.com/en-us/library/ff545982.aspx -#if !defined(GUID_DEVINTERFACE_USB_HOST_CONTROLLER) -const GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = { 0x3ABF6F2D, 0x71C4, 0x462A, {0x8A, 0x92, 0x1E, 0x68, 0x61, 0xE6, 0xAF, 0x27} }; -#endif -#if !defined(GUID_DEVINTERFACE_USB_DEVICE) -const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} }; -#endif -#if !defined(GUID_DEVINTERFACE_USB_HUB) -const GUID GUID_DEVINTERFACE_USB_HUB = { 0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15, 0x00, 0xA0, 0xC9, 0x06, 0xBE, 0xD8} }; -#endif -#if !defined(GUID_DEVINTERFACE_LIBUSB0_FILTER) -const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9} }; -#endif - - -/* - * Multiple USB API backend support - */ -#define USB_API_UNSUPPORTED 0 -#define USB_API_HUB 1 -#define USB_API_COMPOSITE 2 -#define USB_API_WINUSBX 3 -#define USB_API_HID 4 -#define USB_API_MAX 5 -// The following is used to indicate if the HID or composite extra props have already been set. -#define USB_API_SET (1 << USB_API_MAX) - -// Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL) -// Must have the same values as the KUSB_DRVID enum from libusbk.h -#define SUB_API_NOTSET -1 -#define SUB_API_LIBUSBK 0 -#define SUB_API_LIBUSB0 1 -#define SUB_API_WINUSB 2 -#define SUB_API_MAX 3 - -#define WINUSBX_DRV_NAMES {"libusbK", "libusb0", "WinUSB"} - -struct windows_usb_api_backend { - const uint8_t id; - const char *designation; - const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp" - const uint8_t nb_driver_names; - int (*init)(int sub_api, struct libusb_context *ctx); - int (*exit)(int sub_api); - int (*open)(int sub_api, struct libusb_device_handle *dev_handle); - void (*close)(int sub_api, struct libusb_device_handle *dev_handle); - int (*configure_endpoints)(int sub_api, struct libusb_device_handle *dev_handle, int iface); - int (*claim_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface); - int (*set_interface_altsetting)(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting); - int (*release_interface)(int sub_api, struct libusb_device_handle *dev_handle, int iface); - int (*clear_halt)(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint); - int (*reset_device)(int sub_api, struct libusb_device_handle *dev_handle); - int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer); - int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer); - int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer); - int (*abort_control)(int sub_api, struct usbi_transfer *itransfer); - int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer); - int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size); -}; - -extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX]; - -#define PRINT_UNSUPPORTED_API(fname) \ - usbi_dbg("unsupported API call for '" \ - #fname "' (unrecognized device driver)"); \ - return LIBUSB_ERROR_NOT_SUPPORTED; - -/* - * private structures definition - * with inline pseudo constructors/destructors - */ - -// TODO (v2+): move hid desc to libusb.h? -struct libusb_hid_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bClassDescriptorType; - uint16_t wClassDescriptorLength; -}; - -#define LIBUSB_DT_HID_SIZE 9 -#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \ - + LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE) -#define HID_MAX_REPORT_SIZE 1024 -#define HID_IN_EP 0x81 -#define HID_OUT_EP 0x02 -#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F) -#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5)) -#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN) -#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type)) - -// The following are used for HID reports IOCTLs -#define HID_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS) -#define HID_BUFFER_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HID_IN_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS) -#define HID_OUT_CTL_CODE(id) \ - CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS) - -#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100) -#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104) -#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100) -#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101) - -enum libusb_hid_request_type { - HID_REQ_GET_REPORT = 0x01, - HID_REQ_GET_IDLE = 0x02, - HID_REQ_GET_PROTOCOL = 0x03, - HID_REQ_SET_REPORT = 0x09, - HID_REQ_SET_IDLE = 0x0A, - HID_REQ_SET_PROTOCOL = 0x0B -}; - -enum libusb_hid_report_type { - HID_REPORT_TYPE_INPUT = 0x01, - HID_REPORT_TYPE_OUTPUT = 0x02, - HID_REPORT_TYPE_FEATURE = 0x03 -}; - -struct hid_device_priv { - uint16_t vid; - uint16_t pid; - uint8_t config; - uint8_t nb_interfaces; - bool uses_report_ids[3]; // input, ouptput, feature - uint16_t input_report_size; - uint16_t output_report_size; - uint16_t feature_report_size; - WCHAR string[3][MAX_USB_STRING_LENGTH]; - uint8_t string_index[3]; // man, prod, ser -}; - -struct windows_device_priv { - uint8_t depth; // distance to HCD - uint8_t port; // port number on the hub - uint8_t active_config; - struct windows_usb_api_backend const *apib; - char *path; // device interface path - int sub_api; // for WinUSB-like APIs - struct { - char *path; // each interface needs a device interface path, - struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support), - int sub_api; - int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) - uint8_t *endpoint; - bool restricted_functionality; // indicates if the interface functionality is restricted - // by Windows (eg. HID keyboards or mice cannot do R/W) - } usb_interface[USB_MAXINTERFACES]; - struct hid_device_priv *hid; - USB_DEVICE_DESCRIPTOR dev_descriptor; - unsigned char **config_descriptor; // list of pointers to the cached config descriptors -}; - -static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) -{ - return (struct windows_device_priv *)dev->os_priv; -} - -static inline struct windows_device_priv *windows_device_priv_init(struct libusb_device *dev) -{ - struct windows_device_priv *p = _device_priv(dev); - int i; - - p->apib = &usb_api_backend[USB_API_UNSUPPORTED]; - p->sub_api = SUB_API_NOTSET; - for (i = 0; i < USB_MAXINTERFACES; i++) { - p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED]; - p->usb_interface[i].sub_api = SUB_API_NOTSET; - } - - return p; -} - -static inline void windows_device_priv_release(struct libusb_device *dev) -{ - struct windows_device_priv *p = _device_priv(dev); - int i; - - free(p->path); - if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { - for (i = 0; i < dev->num_configurations; i++) - free(p->config_descriptor[i]); - } - free(p->config_descriptor); - free(p->hid); - for (i = 0; i < USB_MAXINTERFACES; i++) { - free(p->usb_interface[i].path); - free(p->usb_interface[i].endpoint); - } -} - -struct interface_handle_t { - HANDLE dev_handle; // WinUSB needs an extra handle for the file - HANDLE api_handle; // used by the API to communicate with the device -}; - -struct windows_device_handle_priv { - int active_interface; - struct interface_handle_t interface_handle[USB_MAXINTERFACES]; - int autoclaim_count[USB_MAXINTERFACES]; // For auto-release -}; - -static inline struct windows_device_handle_priv *_device_handle_priv( - struct libusb_device_handle *handle) -{ - return (struct windows_device_handle_priv *)handle->os_priv; -} - -// used for async polling functions -struct windows_transfer_priv { - struct winfd pollable_fd; - uint8_t interface_number; - uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID - uint8_t *hid_dest; // transfer buffer destination, required for HID - size_t hid_expected_size; -}; - -// used to match a device driver (including filter drivers) against a supported API -struct driver_lookup { - char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names - const DWORD reg_prop; // SPDRP registry key to use to retrieve list - const char* designation; // internal designation (for debug output) -}; - -/* OLE32 dependency */ -DLL_DECLARE_HANDLE(OLE32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HRESULT, p, CLSIDFromString, (LPCOLESTR, LPCLSID)); - -/* Kernel32 dependencies */ -DLL_DECLARE_HANDLE(Kernel32); -/* This call is only available from XP SP2 */ -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); - -/* SetupAPI dependencies */ -DLL_DECLARE_HANDLE(SetupAPI); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (const GUID*, PCSTR, HWND, DWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, - const GUID*, DWORD, PSP_DEVICE_INTERFACE_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, - PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiDestroyDeviceInfoList, (HDEVINFO)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDevRegKey, (HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, - PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, HKEY, p, SetupDiOpenDeviceInterfaceRegKey, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, DWORD)); - -/* AdvAPI32 dependencies */ -DLL_DECLARE_HANDLE(AdvAPI32); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegQueryValueExW, (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD)); -DLL_DECLARE_FUNC_PREFIXED(WINAPI, LONG, p, RegCloseKey, (HKEY)); - -/* - * Windows DDK API definitions. Most of it copied from MinGW's includes - */ -typedef DWORD DEVNODE, DEVINST; -typedef DEVNODE *PDEVNODE, *PDEVINST; -typedef DWORD RETURN_TYPE; -typedef RETURN_TYPE CONFIGRET; - -#define CR_SUCCESS 0x00000000 -#define CR_NO_SUCH_DEVNODE 0x0000000D - -#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE -#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG -#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING -#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE -#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT - -#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS -#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE -#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE -#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION -#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE -#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE -#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME - -#define USB_GET_NODE_INFORMATION 258 -#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260 -#define USB_GET_NODE_CONNECTION_NAME 261 -#define USB_GET_HUB_CAPABILITIES 271 -#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX) -#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274 -#endif -#if !defined(USB_GET_HUB_CAPABILITIES_EX) -#define USB_GET_HUB_CAPABILITIES_EX 276 -#endif -#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2) -#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279 -#endif - -#ifndef METHOD_BUFFERED -#define METHOD_BUFFERED 0 -#endif -#ifndef FILE_ANY_ACCESS -#define FILE_ANY_ACCESS 0x00000000 -#endif -#ifndef FILE_DEVICE_UNKNOWN -#define FILE_DEVICE_UNKNOWN 0x00000022 -#endif -#ifndef FILE_DEVICE_USB -#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN -#endif - -#ifndef CTL_CODE -#define CTL_CODE(DeviceType, Function, Method, Access) \ - (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) -#endif - -typedef enum USB_CONNECTION_STATUS { - NoDeviceConnected, - DeviceConnected, - DeviceFailedEnumeration, - DeviceGeneralFailure, - DeviceCausedOvercurrent, - DeviceNotEnoughPower, - DeviceNotEnoughBandwidth, - DeviceHubNestedTooDeeply, - DeviceInLegacyHub -} USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS; - -typedef enum USB_HUB_NODE { - UsbHub, - UsbMIParent -} USB_HUB_NODE; - -/* Cfgmgr32.dll interface */ -DLL_DECLARE_HANDLE(Cfgmgr32); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); - -#define IOCTL_USB_GET_HUB_CAPABILITIES_EX \ - CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_HUB_CAPABILITIES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_ROOT_HUB_NAME \ - CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_INFORMATION \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_USB_GET_NODE_CONNECTION_NAME \ - CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS) - -// Most of the structures below need to be packed -#pragma pack(push, 1) - -typedef struct USB_INTERFACE_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bInterfaceNumber; - UCHAR bAlternateSetting; - UCHAR bNumEndpoints; - UCHAR bInterfaceClass; - UCHAR bInterfaceSubClass; - UCHAR bInterfaceProtocol; - UCHAR iInterface; -} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; - -typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT { - struct { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; - } req; - USB_CONFIGURATION_DESCRIPTOR data; -} USB_CONFIGURATION_DESCRIPTOR_SHORT; - -typedef struct USB_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bEndpointAddress; - UCHAR bmAttributes; - USHORT wMaxPacketSize; - UCHAR bInterval; -} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; - -typedef struct USB_DESCRIPTOR_REQUEST { - ULONG ConnectionIndex; - struct { - UCHAR bmRequest; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - } SetupPacket; -// UCHAR Data[0]; -} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST; - -typedef struct USB_HUB_DESCRIPTOR { - UCHAR bDescriptorLength; - UCHAR bDescriptorType; - UCHAR bNumberOfPorts; - USHORT wHubCharacteristics; - UCHAR bPowerOnToPowerGood; - UCHAR bHubControlCurrent; - UCHAR bRemoveAndPowerMask[64]; -} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR; - -typedef struct USB_ROOT_HUB_NAME { - ULONG ActualLength; - WCHAR RootHubName[1]; -} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME; - -typedef struct USB_ROOT_HUB_NAME_FIXED { - ULONG ActualLength; - WCHAR RootHubName[MAX_PATH_LENGTH]; -} USB_ROOT_HUB_NAME_FIXED; - -typedef struct USB_NODE_CONNECTION_NAME { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[1]; -} USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME; - -typedef struct USB_NODE_CONNECTION_NAME_FIXED { - ULONG ConnectionIndex; - ULONG ActualLength; - WCHAR NodeName[MAX_PATH_LENGTH]; -} USB_NODE_CONNECTION_NAME_FIXED; - -typedef struct USB_HUB_NAME_FIXED { - union { - USB_ROOT_HUB_NAME_FIXED root; - USB_NODE_CONNECTION_NAME_FIXED node; - } u; -} USB_HUB_NAME_FIXED; - -typedef struct USB_HUB_INFORMATION { - USB_HUB_DESCRIPTOR HubDescriptor; - BOOLEAN HubIsBusPowered; -} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION; - -typedef struct USB_MI_PARENT_INFORMATION { - ULONG NumberOfInterfaces; -} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION; - -typedef struct USB_NODE_INFORMATION { - USB_HUB_NODE NodeType; - union { - USB_HUB_INFORMATION HubInformation; - USB_MI_PARENT_INFORMATION MiParentInformation; - } u; -} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION; - -typedef struct USB_PIPE_INFO { - USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - ULONG ScheduleOffset; -} USB_PIPE_INFO, *PUSB_PIPE_INFO; - -typedef struct USB_NODE_CONNECTION_INFORMATION_EX { - ULONG ConnectionIndex; - USB_DEVICE_DESCRIPTOR DeviceDescriptor; - UCHAR CurrentConfigurationValue; - UCHAR Speed; - BOOLEAN DeviceIsHub; - USHORT DeviceAddress; - ULONG NumberOfOpenPipes; - USB_CONNECTION_STATUS ConnectionStatus; -// USB_PIPE_INFO PipeList[0]; -} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX; - -typedef union _USB_PROTOCOLS { - ULONG ul; - struct { - ULONG Usb110:1; - ULONG Usb200:1; - ULONG Usb300:1; - ULONG ReservedMBZ:29; - }; -} USB_PROTOCOLS, *PUSB_PROTOCOLS; - -typedef union _USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS { - ULONG ul; - struct { - ULONG DeviceIsOperatingAtSuperSpeedOrHigher:1; - ULONG DeviceIsSuperSpeedCapableOrHigher:1; - ULONG ReservedMBZ:30; - }; -} USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS; - -typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 { - ULONG ConnectionIndex; - ULONG Length; - USB_PROTOCOLS SupportedUsbProtocols; - USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags; -} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2; - -typedef struct USB_HUB_CAP_FLAGS { - ULONG HubIsHighSpeedCapable:1; - ULONG HubIsHighSpeed:1; - ULONG HubIsMultiTtCapable:1; - ULONG HubIsMultiTt:1; - ULONG HubIsRoot:1; - ULONG HubIsArmedWakeOnConnect:1; - ULONG ReservedMBZ:26; -} USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS; - -typedef struct USB_HUB_CAPABILITIES { - ULONG HubIs2xCapable:1; -} USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES; - -typedef struct USB_HUB_CAPABILITIES_EX { - USB_HUB_CAP_FLAGS CapabilityFlags; -} USB_HUB_CAPABILITIES_EX, *PUSB_HUB_CAPABILITIES_EX; - -#pragma pack(pop) - -/* winusb.dll interface */ - -#define SHORT_PACKET_TERMINATE 0x01 -#define AUTO_CLEAR_STALL 0x02 -#define PIPE_TRANSFER_TIMEOUT 0x03 -#define IGNORE_SHORT_PACKETS 0x04 -#define ALLOW_PARTIAL_READS 0x05 -#define AUTO_FLUSH 0x06 -#define RAW_IO 0x07 -#define MAXIMUM_TRANSFER_SIZE 0x08 -#define AUTO_SUSPEND 0x81 -#define SUSPEND_DELAY 0x83 -#define DEVICE_SPEED 0x01 -#define LowSpeed 0x01 -#define FullSpeed 0x02 -#define HighSpeed 0x03 - -typedef enum USBD_PIPE_TYPE { - UsbdPipeTypeControl, - UsbdPipeTypeIsochronous, - UsbdPipeTypeBulk, - UsbdPipeTypeInterrupt -} USBD_PIPE_TYPE; - -typedef struct { - USBD_PIPE_TYPE PipeType; - UCHAR PipeId; - USHORT MaximumPacketSize; - UCHAR Interval; -} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION; - -#pragma pack(1) -typedef struct { - UCHAR request_type; - UCHAR request; - USHORT value; - USHORT index; - USHORT length; -} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET; -#pragma pack() - -typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE; - -typedef BOOL (WINAPI *WinUsb_AbortPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID -); -typedef BOOL (WINAPI *WinUsb_ControlTransfer_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - WINUSB_SETUP_PACKET SetupPacket, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred, - LPOVERLAPPED Overlapped -); -typedef BOOL (WINAPI *WinUsb_FlushPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID -); -typedef BOOL (WINAPI *WinUsb_Free_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_GetAssociatedInterface_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AssociatedInterfaceIndex, - PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_GetCurrentAlternateSetting_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - PUCHAR AlternateSetting -); -typedef BOOL (WINAPI *WinUsb_GetDescriptor_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR DescriptorType, - UCHAR Index, - USHORT LanguageID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred -); -typedef BOOL (WINAPI *WinUsb_GetOverlappedResult_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpNumberOfBytesTransferred, - BOOL bWait -); -typedef BOOL (WINAPI *WinUsb_GetPipePolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - ULONG PolicyType, - PULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_GetPowerPolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG PolicyType, - PULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_Initialize_t)( - HANDLE DeviceHandle, - PWINUSB_INTERFACE_HANDLE InterfaceHandle -); -typedef BOOL (WINAPI *WinUsb_QueryDeviceInformation_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG InformationType, - PULONG BufferLength, - PVOID Buffer -); -typedef BOOL (WINAPI *WinUsb_QueryInterfaceSettings_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateSettingNumber, - PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor -); -typedef BOOL (WINAPI *WinUsb_QueryPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateInterfaceNumber, - UCHAR PipeIndex, - PWINUSB_PIPE_INFORMATION PipeInformation -); -typedef BOOL (WINAPI *WinUsb_ReadPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred, - LPOVERLAPPED Overlapped -); -typedef BOOL (WINAPI *WinUsb_ResetPipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID -); -typedef BOOL (WINAPI *WinUsb_SetCurrentAlternateSetting_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR AlternateSetting -); -typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - ULONG PolicyType, - ULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_SetPowerPolicy_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - ULONG PolicyType, - ULONG ValueLength, - PVOID Value -); -typedef BOOL (WINAPI *WinUsb_WritePipe_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle, - UCHAR PipeID, - PUCHAR Buffer, - ULONG BufferLength, - PULONG LengthTransferred, - LPOVERLAPPED Overlapped -); -typedef BOOL (WINAPI *WinUsb_ResetDevice_t)( - WINUSB_INTERFACE_HANDLE InterfaceHandle -); - -/* /!\ These must match the ones from the official libusbk.h */ -typedef enum _KUSB_FNID { - KUSB_FNID_Init, - KUSB_FNID_Free, - KUSB_FNID_ClaimInterface, - KUSB_FNID_ReleaseInterface, - KUSB_FNID_SetAltInterface, - KUSB_FNID_GetAltInterface, - KUSB_FNID_GetDescriptor, - KUSB_FNID_ControlTransfer, - KUSB_FNID_SetPowerPolicy, - KUSB_FNID_GetPowerPolicy, - KUSB_FNID_SetConfiguration, - KUSB_FNID_GetConfiguration, - KUSB_FNID_ResetDevice, - KUSB_FNID_Initialize, - KUSB_FNID_SelectInterface, - KUSB_FNID_GetAssociatedInterface, - KUSB_FNID_Clone, - KUSB_FNID_QueryInterfaceSettings, - KUSB_FNID_QueryDeviceInformation, - KUSB_FNID_SetCurrentAlternateSetting, - KUSB_FNID_GetCurrentAlternateSetting, - KUSB_FNID_QueryPipe, - KUSB_FNID_SetPipePolicy, - KUSB_FNID_GetPipePolicy, - KUSB_FNID_ReadPipe, - KUSB_FNID_WritePipe, - KUSB_FNID_ResetPipe, - KUSB_FNID_AbortPipe, - KUSB_FNID_FlushPipe, - KUSB_FNID_IsoReadPipe, - KUSB_FNID_IsoWritePipe, - KUSB_FNID_GetCurrentFrameNumber, - KUSB_FNID_GetOverlappedResult, - KUSB_FNID_GetProperty, - KUSB_FNID_COUNT, -} KUSB_FNID; - -typedef struct _KLIB_VERSION { - INT Major; - INT Minor; - INT Micro; - INT Nano; -} KLIB_VERSION; -typedef KLIB_VERSION* PKLIB_VERSION; - -typedef BOOL (WINAPI *LibK_GetProcAddress_t)( - PVOID *ProcAddress, - ULONG DriverID, - ULONG FunctionID -); - -typedef VOID (WINAPI *LibK_GetVersion_t)( - PKLIB_VERSION Version -); - -struct winusb_interface { - bool initialized; - WinUsb_AbortPipe_t AbortPipe; - WinUsb_ControlTransfer_t ControlTransfer; - WinUsb_FlushPipe_t FlushPipe; - WinUsb_Free_t Free; - WinUsb_GetAssociatedInterface_t GetAssociatedInterface; - WinUsb_GetCurrentAlternateSetting_t GetCurrentAlternateSetting; - WinUsb_GetDescriptor_t GetDescriptor; - WinUsb_GetOverlappedResult_t GetOverlappedResult; - WinUsb_GetPipePolicy_t GetPipePolicy; - WinUsb_GetPowerPolicy_t GetPowerPolicy; - WinUsb_Initialize_t Initialize; - WinUsb_QueryDeviceInformation_t QueryDeviceInformation; - WinUsb_QueryInterfaceSettings_t QueryInterfaceSettings; - WinUsb_QueryPipe_t QueryPipe; - WinUsb_ReadPipe_t ReadPipe; - WinUsb_ResetPipe_t ResetPipe; - WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting; - WinUsb_SetPipePolicy_t SetPipePolicy; - WinUsb_SetPowerPolicy_t SetPowerPolicy; - WinUsb_WritePipe_t WritePipe; - WinUsb_ResetDevice_t ResetDevice; -}; - -/* hid.dll interface */ - -#define HIDP_STATUS_SUCCESS 0x110000 -typedef void * PHIDP_PREPARSED_DATA; - -#pragma pack(1) -typedef struct { - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; -} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; -#pragma pack() - -typedef USHORT USAGE; -typedef struct { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT NumberLinkCollectionNodes; - USHORT NumberInputButtonCaps; - USHORT NumberInputValueCaps; - USHORT NumberInputDataIndices; - USHORT NumberOutputButtonCaps; - USHORT NumberOutputValueCaps; - USHORT NumberOutputDataIndices; - USHORT NumberFeatureButtonCaps; - USHORT NumberFeatureValueCaps; - USHORT NumberFeatureDataIndices; -} HIDP_CAPS, *PHIDP_CAPS; - -typedef enum _HIDP_REPORT_TYPE { - HidP_Input, - HidP_Output, - HidP_Feature -} HIDP_REPORT_TYPE; - -typedef struct _HIDP_VALUE_CAPS { - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - USHORT BitField; - USHORT LinkCollection; - USAGE LinkUsage; - USAGE LinkUsagePage; - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - BOOLEAN HasNull; - UCHAR Reserved; - USHORT BitSize; - USHORT ReportCount; - USHORT Reserved2[5]; - ULONG UnitsExp; - ULONG Units; - LONG LogicalMin, LogicalMax; - LONG PhysicalMin, PhysicalMax; - union { - struct { - USAGE UsageMin, UsageMax; - USHORT StringMin, StringMax; - USHORT DesignatorMin, DesignatorMax; - USHORT DataIndexMin, DataIndexMax; - } Range; - struct { - USAGE Usage, Reserved1; - USHORT StringIndex, Reserved2; - USHORT DesignatorIndex, Reserved3; - USHORT DataIndex, Reserved4; - } NotRange; - } u; -} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; - -DLL_DECLARE_HANDLE(hid); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetAttributes, (HANDLE, PHIDD_ATTRIBUTES)); -DLL_DECLARE_FUNC(WINAPI, VOID, HidD_GetHidGuid, (LPGUID)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPreparsedData, (HANDLE, PHIDP_PREPARSED_DATA *)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FreePreparsedData, (PHIDP_PREPARSED_DATA)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetManufacturerString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetProductString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetSerialNumberString, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, LONG, HidP_GetCaps, (PHIDP_PREPARSED_DATA, PHIDP_CAPS)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetNumInputBuffers, (HANDLE, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetFeature, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetFeature, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetPhysicalDescriptor, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_GetInputReport, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_SetOutputReport, (HANDLE, PVOID, ULONG)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidD_FlushQueue, (HANDLE)); -DLL_DECLARE_FUNC(WINAPI, BOOL, HidP_GetValueCaps, (HIDP_REPORT_TYPE, PHIDP_VALUE_CAPS, PULONG, PHIDP_PREPARSED_DATA)); \ No newline at end of file diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/strerror.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/strerror.c deleted file mode 100644 index d2be0e2a008..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/strerror.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * libusb strerror code - * Copyright © 2013 Hans de Goede - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#if defined(HAVE_STRINGS_H) -#include -#endif - -#include "libusbi.h" - -#if defined(_MSC_VER) -#define strncasecmp _strnicmp -#endif - -static size_t usbi_locale = 0; - -/** \ingroup libusb_misc - * How to add a new \ref libusb_strerror() translation: - *
    - *
  1. Download the latest \c strerror.c from:
    - * https://raw.github.com/libusb/libusb/master/libusb/sterror.c
  2. - *
  3. Open the file in an UTF-8 capable editor
  4. - *
  5. Add the 2 letter ISO 639-1 - * code for your locale at the end of \c usbi_locale_supported[]
    - * Eg. for Chinese, you would add "zh" so that: - * \code... usbi_locale_supported[] = { "en", "nl", "fr" };\endcode - * becomes: - * \code... usbi_locale_supported[] = { "en", "nl", "fr", "zh" };\endcode
  6. - *
  7. Copy the { / * English (en) * / ... } section and add it at the end of \c usbi_localized_errors
    - * Eg. for Chinese, the last section of \c usbi_localized_errors could look like: - * \code - * }, { / * Chinese (zh) * / - * "Success", - * ... - * "Other error", - * } - * };\endcode
  8. - *
  9. Translate each of the English messages from the section you copied into your language
  10. - *
  11. Save the file (in UTF-8 format) and send it to \c libusb-devel\@lists.sourceforge.net
  12. - *
- */ - -static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru" }; -static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = { - { /* English (en) */ - "Success", - "Input/Output Error", - "Invalid parameter", - "Access denied (insufficient permissions)", - "No such device (it may have been disconnected)", - "Entity not found", - "Resource busy", - "Operation timed out", - "Overflow", - "Pipe error", - "System call interrupted (perhaps due to signal)", - "Insufficient memory", - "Operation not supported or unimplemented on this platform", - "Other error", - }, { /* Dutch (nl) */ - "Gelukt", - "Invoer-/uitvoerfout", - "Ongeldig argument", - "Toegang geweigerd (onvoldoende toegangsrechten)", - "Apparaat bestaat niet (verbinding met apparaat verbroken?)", - "Niet gevonden", - "Apparaat of hulpbron is bezig", - "Bewerking verlopen", - "Waarde is te groot", - "Gebroken pijp", - "Onderbroken systeemaanroep", - "Onvoldoende geheugen beschikbaar", - "Bewerking wordt niet ondersteund", - "Andere fout", - }, { /* French (fr) */ - "Succès", - "Erreur d'entrée/sortie", - "Paramètre invalide", - "Accès refusé (permissions insuffisantes)", - "Périphérique introuvable (peut-être déconnecté)", - "Elément introuvable", - "Resource déjà occupée", - "Operation expirée", - "Débordement", - "Erreur de pipe", - "Appel système abandonné (peut-être à cause d’un signal)", - "Mémoire insuffisante", - "Opération non supportée or non implémentée sur cette plateforme", - "Autre erreur", - }, { /* Russian (ru) */ - "Успех", - "Ошибка ввода/вывода", - "Неверный параметр", - "Доступ запрещён (не хватает прав)", - "Устройство отсутствует (возможно, оно было отсоединено)", - "Элемент не найден", - "Ресурс занят", - "Истекло время ожидания операции", - "Переполнение", - "Ошибка канала", - "Системный вызов прерван (возможно, сигналом)", - "Память исчерпана", - "Операция не поддерживается данной платформой", - "Неизвестная ошибка" - } -}; - -/** \ingroup libusb_misc - * Set the language, and only the language, not the encoding! used for - * translatable libusb messages. - * - * This takes a locale string in the default setlocale format: lang[-region] - * or lang[_country_region][.codeset]. Only the lang part of the string is - * used, and only 2 letter ISO 639-1 codes are accepted for it, such as "de". - * The optional region, country_region or codeset parts are ignored. This - * means that functions which return translatable strings will NOT honor the - * specified encoding. - * All strings returned are encoded as UTF-8 strings. - * - * If libusb_setlocale() is not called, all messages will be in English. - * - * The following functions return translatable strings: libusb_strerror(). - * Note that the libusb log messages controlled through libusb_set_debug() - * are not translated, they are always in English. - * - * For POSIX UTF-8 environments if you want libusb to follow the standard - * locale settings, call libusb_setlocale(setlocale(LC_MESSAGES, NULL)), - * after your app has done its locale setup. - * - * \param locale locale-string in the form of lang[_country_region][.codeset] - * or lang[-region], where lang is a 2 letter ISO 639-1 code - * \returns LIBUSB_SUCCESS on success - * \returns LIBUSB_ERROR_INVALID_PARAM if the locale doesn't meet the requirements - * \returns LIBUSB_ERROR_NOT_FOUND if the requested language is not supported - * \returns a LIBUSB_ERROR code on other errors - */ - -int API_EXPORTED libusb_setlocale(const char *locale) -{ - size_t i; - - if ( (locale == NULL) || (strlen(locale) < 2) - || ((strlen(locale) > 2) && (locale[2] != '-') && (locale[2] != '_') && (locale[2] != '.')) ) - return LIBUSB_ERROR_INVALID_PARAM; - - for (i=0; i= ARRAYSIZE(usbi_locale_supported)) { - return LIBUSB_ERROR_NOT_FOUND; - } - - usbi_locale = i; - - return LIBUSB_SUCCESS; -} - -/** \ingroup libusb_misc - * Returns a constant string with a short description of the given error code, - * this description is intended for displaying to the end user and will be in - * the language set by libusb_setlocale(). - * - * The returned string is encoded in UTF-8. - * - * The messages always start with a capital letter and end without any dot. - * The caller must not free() the returned string. - * - * \param errcode the error code whose description is desired - * \returns a short description of the error code in UTF-8 encoding - */ -DEFAULT_VISIBILITY const char* LIBUSB_CALL libusb_strerror(enum libusb_error errcode) -{ - int errcode_index = -errcode; - - if ((errcode_index < 0) || (errcode_index >= LIBUSB_ERROR_COUNT)) { - /* "Other Error", which should always be our last message, is returned */ - errcode_index = LIBUSB_ERROR_COUNT - 1; - } - - return usbi_localized_errors[usbi_locale][errcode_index]; -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/sync.c b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/sync.c deleted file mode 100644 index a609f65f44f..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/sync.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Synchronous I/O functions for libusb - * Copyright © 2007-2008 Daniel Drake - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include - -#include "libusbi.h" - -/** - * @defgroup libusb_syncio Synchronous device I/O - * - * This page documents libusb's synchronous (blocking) API for USB device I/O. - * This interface is easy to use but has some limitations. More advanced users - * may wish to consider using the \ref libusb_asyncio "asynchronous I/O API" instead. - */ - -static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) -{ - int *completed = transfer->user_data; - *completed = 1; - usbi_dbg("actual_length=%d", transfer->actual_length); - /* caller interprets result and frees transfer */ -} - -static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) -{ - int r, *completed = transfer->user_data; - struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); - - while (!*completed) { - r = libusb_handle_events_completed(ctx, completed); - if (r < 0) { - if (r == LIBUSB_ERROR_INTERRUPTED) - continue; - usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", - libusb_error_name(r)); - libusb_cancel_transfer(transfer); - continue; - } - } -} - -/** \ingroup libusb_syncio - * Perform a USB control transfer. - * - * The direction of the transfer is inferred from the bmRequestType field of - * the setup packet. - * - * The wValue, wIndex and wLength fields values should be given in host-endian - * byte order. - * - * \param dev_handle a handle for the device to communicate with - * \param bmRequestType the request type field for the setup packet - * \param bRequest the request field for the setup packet - * \param wValue the value field for the setup packet - * \param wIndex the index field for the setup packet - * \param data a suitably-sized data buffer for either input or output - * (depending on direction bits within bmRequestType) - * \param wLength the length field for the setup packet. The data buffer should - * be at least this size. - * \param timeout timeout (in millseconds) that this function should wait - * before giving up due to no response being received. For an unlimited - * timeout, use value 0. - * \returns on success, the number of bytes actually transferred - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out - * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the - * device - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than - * the operating system and/or hardware can support - * \returns another LIBUSB_ERROR code on other failures - */ -int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, - uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout) -{ - struct libusb_transfer *transfer; - unsigned char *buffer; - int completed = 0; - int r; - - if (usbi_handling_events(HANDLE_CTX(dev_handle))) - return LIBUSB_ERROR_BUSY; - - transfer = libusb_alloc_transfer(0); - if (!transfer) - return LIBUSB_ERROR_NO_MEM; - - buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); - if (!buffer) { - libusb_free_transfer(transfer); - return LIBUSB_ERROR_NO_MEM; - } - - libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, - wLength); - if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) - memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); - - libusb_fill_control_transfer(transfer, dev_handle, buffer, - sync_transfer_cb, &completed, timeout); - transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - return r; - } - - sync_transfer_wait_for_completion(transfer); - - if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) - memcpy(data, libusb_control_transfer_get_data(transfer), - transfer->actual_length); - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - r = transfer->actual_length; - break; - case LIBUSB_TRANSFER_TIMED_OUT: - r = LIBUSB_ERROR_TIMEOUT; - break; - case LIBUSB_TRANSFER_STALL: - r = LIBUSB_ERROR_PIPE; - break; - case LIBUSB_TRANSFER_NO_DEVICE: - r = LIBUSB_ERROR_NO_DEVICE; - break; - case LIBUSB_TRANSFER_OVERFLOW: - r = LIBUSB_ERROR_OVERFLOW; - break; - case LIBUSB_TRANSFER_ERROR: - case LIBUSB_TRANSFER_CANCELLED: - r = LIBUSB_ERROR_IO; - break; - default: - usbi_warn(HANDLE_CTX(dev_handle), - "unrecognised status code %d", transfer->status); - r = LIBUSB_ERROR_OTHER; - } - - libusb_free_transfer(transfer); - return r; -} - -static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *buffer, int length, - int *transferred, unsigned int timeout, unsigned char type) -{ - struct libusb_transfer *transfer; - int completed = 0; - int r; - - if (usbi_handling_events(HANDLE_CTX(dev_handle))) - return LIBUSB_ERROR_BUSY; - - transfer = libusb_alloc_transfer(0); - if (!transfer) - return LIBUSB_ERROR_NO_MEM; - - libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, - sync_transfer_cb, &completed, timeout); - transfer->type = type; - - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - return r; - } - - sync_transfer_wait_for_completion(transfer); - - if (transferred) - *transferred = transfer->actual_length; - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - r = 0; - break; - case LIBUSB_TRANSFER_TIMED_OUT: - r = LIBUSB_ERROR_TIMEOUT; - break; - case LIBUSB_TRANSFER_STALL: - r = LIBUSB_ERROR_PIPE; - break; - case LIBUSB_TRANSFER_OVERFLOW: - r = LIBUSB_ERROR_OVERFLOW; - break; - case LIBUSB_TRANSFER_NO_DEVICE: - r = LIBUSB_ERROR_NO_DEVICE; - break; - case LIBUSB_TRANSFER_ERROR: - case LIBUSB_TRANSFER_CANCELLED: - r = LIBUSB_ERROR_IO; - break; - default: - usbi_warn(HANDLE_CTX(dev_handle), - "unrecognised status code %d", transfer->status); - r = LIBUSB_ERROR_OTHER; - } - - libusb_free_transfer(transfer); - return r; -} - -/** \ingroup libusb_syncio - * Perform a USB bulk transfer. The direction of the transfer is inferred from - * the direction bits of the endpoint address. - * - * For bulk reads, the length field indicates the maximum length of - * data you are expecting to receive. If less data arrives than expected, - * this function will return that data, so be sure to check the - * transferred output parameter. - * - * You should also check the transferred parameter for bulk writes. - * Not all of the data may have been written. - * - * Also check transferred when dealing with a timeout error code. - * libusb may have to split your transfer into a number of chunks to satisfy - * underlying O/S requirements, meaning that the timeout may expire after - * the first few chunks have completed. libusb is careful not to lose any data - * that may have been transferred; do not assume that timeout conditions - * indicate a complete lack of I/O. - * - * \param dev_handle a handle for the device to communicate with - * \param endpoint the address of a valid endpoint to communicate with - * \param data a suitably-sized data buffer for either input or output - * (depending on endpoint) - * \param length for bulk writes, the number of bytes from data to be sent. for - * bulk reads, the maximum number of bytes to receive into the data buffer. - * \param transferred output location for the number of bytes actually - * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), - * it is legal to pass a NULL pointer if you do not wish to receive this - * information. - * \param timeout timeout (in millseconds) that this function should wait - * before giving up due to no response being received. For an unlimited - * timeout, use value 0. - * - * \returns 0 on success (and populates transferred) - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out (and populates - * transferred) - * \returns LIBUSB_ERROR_PIPE if the endpoint halted - * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see - * \ref libusb_packetoverflow - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns another LIBUSB_ERROR code on other failures - */ -int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, int *transferred, - unsigned int timeout) -{ - return do_sync_bulk_transfer(dev_handle, endpoint, data, length, - transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); -} - -/** \ingroup libusb_syncio - * Perform a USB interrupt transfer. The direction of the transfer is inferred - * from the direction bits of the endpoint address. - * - * For interrupt reads, the length field indicates the maximum length - * of data you are expecting to receive. If less data arrives than expected, - * this function will return that data, so be sure to check the - * transferred output parameter. - * - * You should also check the transferred parameter for interrupt - * writes. Not all of the data may have been written. - * - * Also check transferred when dealing with a timeout error code. - * libusb may have to split your transfer into a number of chunks to satisfy - * underlying O/S requirements, meaning that the timeout may expire after - * the first few chunks have completed. libusb is careful not to lose any data - * that may have been transferred; do not assume that timeout conditions - * indicate a complete lack of I/O. - * - * The default endpoint bInterval value is used as the polling interval. - * - * \param dev_handle a handle for the device to communicate with - * \param endpoint the address of a valid endpoint to communicate with - * \param data a suitably-sized data buffer for either input or output - * (depending on endpoint) - * \param length for bulk writes, the number of bytes from data to be sent. for - * bulk reads, the maximum number of bytes to receive into the data buffer. - * \param transferred output location for the number of bytes actually - * transferred. Since version 1.0.21 (\ref LIBUSB_API_VERSION >= 0x01000105), - * it is legal to pass a NULL pointer if you do not wish to receive this - * information. - * \param timeout timeout (in millseconds) that this function should wait - * before giving up due to no response being received. For an unlimited - * timeout, use value 0. - * - * \returns 0 on success (and populates transferred) - * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out - * \returns LIBUSB_ERROR_PIPE if the endpoint halted - * \returns LIBUSB_ERROR_OVERFLOW if the device offered more data, see - * \ref libusb_packetoverflow - * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected - * \returns LIBUSB_ERROR_BUSY if called from event handling context - * \returns another LIBUSB_ERROR code on other error - */ -int API_EXPORTED libusb_interrupt_transfer( - struct libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *data, int length, int *transferred, unsigned int timeout) -{ - return do_sync_bulk_transfer(dev_handle, endpoint, data, length, - transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); -} diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/version.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/version.h deleted file mode 100644 index 6ce48a7d01a..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/version.h +++ /dev/null @@ -1,18 +0,0 @@ -/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */ -#include "version_nano.h" -#ifndef LIBUSB_MAJOR -#define LIBUSB_MAJOR 1 -#endif -#ifndef LIBUSB_MINOR -#define LIBUSB_MINOR 0 -#endif -#ifndef LIBUSB_MICRO -#define LIBUSB_MICRO 21 -#endif -#ifndef LIBUSB_NANO -#define LIBUSB_NANO 0 -#endif -/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ -#ifndef LIBUSB_RC -#define LIBUSB_RC "" -#endif diff --git a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/version_nano.h b/vendor/github.com/karalabe/gousb/internal/libusb/libusb/version_nano.h deleted file mode 100644 index 0a5d1c99264..00000000000 --- a/vendor/github.com/karalabe/gousb/internal/libusb/libusb/version_nano.h +++ /dev/null @@ -1 +0,0 @@ -#define LIBUSB_NANO 11182 diff --git a/vendor/github.com/karalabe/gousb/usb/config.go b/vendor/github.com/karalabe/gousb/usb/config.go deleted file mode 100644 index 840bce63c6d..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/config.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -/* -#ifndef OS_WINDOWS - #include "os/threads_posix.h" -#endif -#include "libusbi.h" -#include "libusb.h" -*/ -import "C" - -import ( - "fmt" - "reflect" - "unsafe" -) - -type EndpointInfo struct { - Address uint8 - Attributes uint8 - MaxPacketSize uint16 - MaxIsoPacket uint32 - PollInterval uint8 - RefreshRate uint8 - SynchAddress uint8 -} - -func (e EndpointInfo) Number() int { - return int(e.Address) & ENDPOINT_NUM_MASK -} - -func (e EndpointInfo) Direction() EndpointDirection { - return EndpointDirection(e.Address) & ENDPOINT_DIR_MASK -} - -func (e EndpointInfo) String() string { - return fmt.Sprintf("Endpoint %d %-3s %s - %s %s [%d %d]", - e.Number(), e.Direction(), - TransferType(e.Attributes)&TRANSFER_TYPE_MASK, - IsoSyncType(e.Attributes)&ISO_SYNC_TYPE_MASK, - IsoUsageType(e.Attributes)&ISO_USAGE_TYPE_MASK, - e.MaxPacketSize, e.MaxIsoPacket, - ) -} - -type InterfaceInfo struct { - Number uint8 - Setups []InterfaceSetup -} - -func (i InterfaceInfo) String() string { - return fmt.Sprintf("Interface %02x (%d setups)", i.Number, len(i.Setups)) -} - -type InterfaceSetup struct { - Number uint8 - Alternate uint8 - IfClass uint8 - IfSubClass uint8 - IfProtocol uint8 - Endpoints []EndpointInfo -} - -func (a InterfaceSetup) String() string { - return fmt.Sprintf("Interface %02x Setup %02x", a.Number, a.Alternate) -} - -type ConfigInfo struct { - Config uint8 - Attributes uint8 - MaxPower uint8 - Interfaces []InterfaceInfo -} - -func (c ConfigInfo) String() string { - return fmt.Sprintf("Config %02x", c.Config) -} - -func newConfig(dev *C.libusb_device, cfg *C.struct_libusb_config_descriptor) ConfigInfo { - c := ConfigInfo{ - Config: uint8(cfg.bConfigurationValue), - Attributes: uint8(cfg.bmAttributes), - MaxPower: uint8(cfg.MaxPower), - } - - var ifaces []C.struct_libusb_interface - *(*reflect.SliceHeader)(unsafe.Pointer(&ifaces)) = reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(cfg._interface)), - Len: int(cfg.bNumInterfaces), - Cap: int(cfg.bNumInterfaces), - } - c.Interfaces = make([]InterfaceInfo, 0, len(ifaces)) - for _, iface := range ifaces { - if iface.num_altsetting == 0 { - continue - } - - var alts []C.struct_libusb_interface_descriptor - *(*reflect.SliceHeader)(unsafe.Pointer(&alts)) = reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(iface.altsetting)), - Len: int(iface.num_altsetting), - Cap: int(iface.num_altsetting), - } - descs := make([]InterfaceSetup, 0, len(alts)) - for _, alt := range alts { - i := InterfaceSetup{ - Number: uint8(alt.bInterfaceNumber), - Alternate: uint8(alt.bAlternateSetting), - IfClass: uint8(alt.bInterfaceClass), - IfSubClass: uint8(alt.bInterfaceSubClass), - IfProtocol: uint8(alt.bInterfaceProtocol), - } - var ends []C.struct_libusb_endpoint_descriptor - *(*reflect.SliceHeader)(unsafe.Pointer(&ends)) = reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(alt.endpoint)), - Len: int(alt.bNumEndpoints), - Cap: int(alt.bNumEndpoints), - } - i.Endpoints = make([]EndpointInfo, 0, len(ends)) - for _, end := range ends { - i.Endpoints = append(i.Endpoints, EndpointInfo{ - Address: uint8(end.bEndpointAddress), - Attributes: uint8(end.bmAttributes), - MaxPacketSize: uint16(end.wMaxPacketSize), - //MaxIsoPacket: uint32(C.libusb_get_max_iso_packet_size(dev, C.uchar(end.bEndpointAddress))), - PollInterval: uint8(end.bInterval), - RefreshRate: uint8(end.bRefresh), - SynchAddress: uint8(end.bSynchAddress), - }) - } - descs = append(descs, i) - } - c.Interfaces = append(c.Interfaces, InterfaceInfo{ - Number: descs[0].Number, - Setups: descs, - }) - } - return c -} diff --git a/vendor/github.com/karalabe/gousb/usb/constants.go b/vendor/github.com/karalabe/gousb/usb/constants.go deleted file mode 100644 index 7f0287d5c93..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/constants.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -// #include "libusb.h" -import "C" - -type Class uint8 - -const ( - CLASS_PER_INTERFACE Class = C.LIBUSB_CLASS_PER_INTERFACE - CLASS_AUDIO Class = C.LIBUSB_CLASS_AUDIO - CLASS_COMM Class = C.LIBUSB_CLASS_COMM - CLASS_HID Class = C.LIBUSB_CLASS_HID - CLASS_PRINTER Class = C.LIBUSB_CLASS_PRINTER - CLASS_PTP Class = C.LIBUSB_CLASS_PTP - CLASS_MASS_STORAGE Class = C.LIBUSB_CLASS_MASS_STORAGE - CLASS_HUB Class = C.LIBUSB_CLASS_HUB - CLASS_DATA Class = C.LIBUSB_CLASS_DATA - CLASS_WIRELESS Class = C.LIBUSB_CLASS_WIRELESS - CLASS_APPLICATION Class = C.LIBUSB_CLASS_APPLICATION - CLASS_VENDOR_SPEC Class = C.LIBUSB_CLASS_VENDOR_SPEC -) - -var classDescription = map[Class]string{ - CLASS_PER_INTERFACE: "per-interface", - CLASS_AUDIO: "audio", - CLASS_COMM: "communications", - CLASS_HID: "human interface device", - CLASS_PRINTER: "printer dclass", - CLASS_PTP: "picture transfer protocol", - CLASS_MASS_STORAGE: "mass storage", - CLASS_HUB: "hub", - CLASS_DATA: "data", - CLASS_WIRELESS: "wireless", - CLASS_APPLICATION: "application", - CLASS_VENDOR_SPEC: "vendor-specific", -} - -func (c Class) String() string { - return classDescription[c] -} - -type DescriptorType uint8 - -const ( - DT_DEVICE DescriptorType = C.LIBUSB_DT_DEVICE - DT_CONFIG DescriptorType = C.LIBUSB_DT_CONFIG - DT_STRING DescriptorType = C.LIBUSB_DT_STRING - DT_INTERFACE DescriptorType = C.LIBUSB_DT_INTERFACE - DT_ENDPOINT DescriptorType = C.LIBUSB_DT_ENDPOINT - DT_HID DescriptorType = C.LIBUSB_DT_HID - DT_REPORT DescriptorType = C.LIBUSB_DT_REPORT - DT_PHYSICAL DescriptorType = C.LIBUSB_DT_PHYSICAL - DT_HUB DescriptorType = C.LIBUSB_DT_HUB -) - -var descriptorTypeDescription = map[DescriptorType]string{ - DT_DEVICE: "device", - DT_CONFIG: "configuration", - DT_STRING: "string", - DT_INTERFACE: "interface", - DT_ENDPOINT: "endpoint", - DT_HID: "HID", - DT_REPORT: "HID report", - DT_PHYSICAL: "physical", - DT_HUB: "hub", -} - -func (dt DescriptorType) String() string { - return descriptorTypeDescription[dt] -} - -type EndpointDirection uint8 - -const ( - ENDPOINT_NUM_MASK = 0x03 - ENDPOINT_DIR_IN EndpointDirection = C.LIBUSB_ENDPOINT_IN - ENDPOINT_DIR_OUT EndpointDirection = C.LIBUSB_ENDPOINT_OUT - ENDPOINT_DIR_MASK EndpointDirection = 0x80 -) - -var endpointDirectionDescription = map[EndpointDirection]string{ - ENDPOINT_DIR_IN: "IN", - ENDPOINT_DIR_OUT: "OUT", -} - -func (ed EndpointDirection) String() string { - return endpointDirectionDescription[ed] -} - -type TransferType uint8 - -const ( - TRANSFER_TYPE_CONTROL TransferType = C.LIBUSB_TRANSFER_TYPE_CONTROL - TRANSFER_TYPE_ISOCHRONOUS TransferType = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - TRANSFER_TYPE_BULK TransferType = C.LIBUSB_TRANSFER_TYPE_BULK - TRANSFER_TYPE_INTERRUPT TransferType = C.LIBUSB_TRANSFER_TYPE_INTERRUPT - TRANSFER_TYPE_MASK TransferType = 0x03 -) - -var transferTypeDescription = map[TransferType]string{ - TRANSFER_TYPE_CONTROL: "control", - TRANSFER_TYPE_ISOCHRONOUS: "isochronous", - TRANSFER_TYPE_BULK: "bulk", - TRANSFER_TYPE_INTERRUPT: "interrupt", -} - -func (tt TransferType) String() string { - return transferTypeDescription[tt] -} - -type IsoSyncType uint8 - -const ( - ISO_SYNC_TYPE_NONE IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_NONE << 2 - ISO_SYNC_TYPE_ASYNC IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ASYNC << 2 - ISO_SYNC_TYPE_ADAPTIVE IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ADAPTIVE << 2 - ISO_SYNC_TYPE_SYNC IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_SYNC << 2 - ISO_SYNC_TYPE_MASK IsoSyncType = 0x0C -) - -var isoSyncTypeDescription = map[IsoSyncType]string{ - ISO_SYNC_TYPE_NONE: "unsynchronized", - ISO_SYNC_TYPE_ASYNC: "asynchronous", - ISO_SYNC_TYPE_ADAPTIVE: "adaptive", - ISO_SYNC_TYPE_SYNC: "synchronous", -} - -func (ist IsoSyncType) String() string { - return isoSyncTypeDescription[ist] -} - -type IsoUsageType uint8 - -const ( - ISO_USAGE_TYPE_DATA IsoUsageType = C.LIBUSB_ISO_USAGE_TYPE_DATA << 4 - ISO_USAGE_TYPE_FEEDBACK IsoUsageType = C.LIBUSB_ISO_USAGE_TYPE_FEEDBACK << 4 - ISO_USAGE_TYPE_IMPLICIT IsoUsageType = C.LIBUSB_ISO_USAGE_TYPE_IMPLICIT << 4 - ISO_USAGE_TYPE_MASK IsoUsageType = 0x30 -) - -var isoUsageTypeDescription = map[IsoUsageType]string{ - ISO_USAGE_TYPE_DATA: "data", - ISO_USAGE_TYPE_FEEDBACK: "feedback", - ISO_USAGE_TYPE_IMPLICIT: "implicit data", -} - -func (iut IsoUsageType) String() string { - return isoUsageTypeDescription[iut] -} - -type RequestType uint8 - -const ( - REQUEST_TYPE_STANDARD = C.LIBUSB_REQUEST_TYPE_STANDARD - REQUEST_TYPE_CLASS = C.LIBUSB_REQUEST_TYPE_CLASS - REQUEST_TYPE_VENDOR = C.LIBUSB_REQUEST_TYPE_VENDOR - REQUEST_TYPE_RESERVED = C.LIBUSB_REQUEST_TYPE_RESERVED -) - -var requestTypeDescription = map[RequestType]string{ - REQUEST_TYPE_STANDARD: "standard", - REQUEST_TYPE_CLASS: "class", - REQUEST_TYPE_VENDOR: "vendor", - REQUEST_TYPE_RESERVED: "reserved", -} - -func (rt RequestType) String() string { - return requestTypeDescription[rt] -} diff --git a/vendor/github.com/karalabe/gousb/usb/debug.go b/vendor/github.com/karalabe/gousb/usb/debug.go deleted file mode 100644 index e7de8e522cb..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/debug.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -// To enable internal debugging: -// -ldflags "-X github.com/karalabe/gousb/usb.debugInternal true" - -import ( - "io" - "io/ioutil" - "log" // TODO(kevlar): make a logger - "os" -) - -var debug *log.Logger -var debugInternal string - -func init() { - var out io.Writer = ioutil.Discard - if debugInternal != "" { - out = os.Stderr - } - debug = log.New(out, "usb", log.LstdFlags|log.Lshortfile) -} diff --git a/vendor/github.com/karalabe/gousb/usb/descriptor.go b/vendor/github.com/karalabe/gousb/usb/descriptor.go deleted file mode 100644 index 2551dfc2343..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/descriptor.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -/* -#ifndef OS_WINDOWS - #include "os/threads_posix.h" -#endif -#include "libusbi.h" -#include "libusb.h" -*/ -import "C" - -type Descriptor struct { - // Bus information - Bus uint8 // The bus on which the device was detected - Address uint8 // The address of the device on the bus - - // Version information - Spec BCD // USB Specification Release Number - Device BCD // The device version - - // Product information - Vendor ID // The Vendor identifer - Product ID // The Product identifier - - // Protocol information - Class uint8 // The class of this device - SubClass uint8 // The sub-class (within the class) of this device - Protocol uint8 // The protocol (within the sub-class) of this device - - // Configuration information - Configs []ConfigInfo -} - -func newDescriptor(dev *C.libusb_device) (*Descriptor, error) { - var desc C.struct_libusb_device_descriptor - if errno := C.libusb_get_device_descriptor(dev, &desc); errno < 0 { - return nil, usbError(errno) - } - - // Enumerate configurations - var cfgs []ConfigInfo - for i := 0; i < int(desc.bNumConfigurations); i++ { - var cfg *C.struct_libusb_config_descriptor - if errno := C.libusb_get_config_descriptor(dev, C.uint8_t(i), &cfg); errno < 0 { - return nil, usbError(errno) - } - cfgs = append(cfgs, newConfig(dev, cfg)) - C.libusb_free_config_descriptor(cfg) - } - - return &Descriptor{ - Bus: uint8(C.libusb_get_bus_number(dev)), - Address: uint8(C.libusb_get_device_address(dev)), - Spec: BCD(desc.bcdUSB), - Device: BCD(desc.bcdDevice), - Vendor: ID(desc.idVendor), - Product: ID(desc.idProduct), - Class: uint8(desc.bDeviceClass), - SubClass: uint8(desc.bDeviceSubClass), - Protocol: uint8(desc.bDeviceProtocol), - Configs: cfgs, - }, nil -} diff --git a/vendor/github.com/karalabe/gousb/usb/device.go b/vendor/github.com/karalabe/gousb/usb/device.go deleted file mode 100644 index b4c4131fa6d..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/device.go +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -/* -#ifndef OS_WINDOWS - #include "os/threads_posix.h" -#endif -#include "libusbi.h" -#include "libusb.h" -*/ -import "C" - -import ( - "fmt" - "reflect" - "sync" - "time" - "unsafe" -) - -var DefaultReadTimeout = 1 * time.Second -var DefaultWriteTimeout = 1 * time.Second -var DefaultControlTimeout = 250 * time.Millisecond //5 * time.Second - -type Device struct { - handle *C.libusb_device_handle - - // Embed the device information for easy access - *Descriptor - - // Timeouts - ReadTimeout time.Duration - WriteTimeout time.Duration - ControlTimeout time.Duration - - // Claimed interfaces - lock *sync.Mutex - claimed map[uint8]int - - // Detached kernel interfaces - detached map[uint8]int -} - -func newDevice(handle *C.libusb_device_handle, desc *Descriptor) (*Device, error) { - ifaces := 0 - d := &Device{ - handle: handle, - Descriptor: desc, - ReadTimeout: DefaultReadTimeout, - WriteTimeout: DefaultWriteTimeout, - ControlTimeout: DefaultControlTimeout, - lock: new(sync.Mutex), - claimed: make(map[uint8]int, ifaces), - detached: make(map[uint8]int), - } - - if err := d.detachKernelDriver(); err != nil { - d.Close() - return nil, err - } - - return d, nil -} - -// detachKernelDriver detaches any active kernel drivers, if supported by the platform. -// If there are any errors, like Context.ListDevices, only the final one will be returned. -func (d *Device) detachKernelDriver() (err error) { - for _, cfg := range d.Configs { - for _, iface := range cfg.Interfaces { - switch activeErr := C.libusb_kernel_driver_active(d.handle, C.int(iface.Number)); activeErr { - case C.LIBUSB_ERROR_NOT_SUPPORTED: - // no need to do any futher checking, no platform support - return - case 0: - continue - case 1: - switch detachErr := C.libusb_detach_kernel_driver(d.handle, C.int(iface.Number)); detachErr { - case C.LIBUSB_ERROR_NOT_SUPPORTED: - // shouldn't ever get here, should be caught by the outer switch - return - case 0: - d.detached[iface.Number]++ - case C.LIBUSB_ERROR_NOT_FOUND: - // this status is returned if libusb's driver is already attached to the device - d.detached[iface.Number]++ - default: - err = fmt.Errorf("usb: detach kernel driver: %s", usbError(detachErr)) - } - default: - err = fmt.Errorf("usb: active kernel driver check: %s", usbError(activeErr)) - } - } - } - - return -} - -// attachKernelDriver re-attaches kernel drivers to any previously detached interfaces, if supported by the platform. -// If there are any errors, like Context.ListDevices, only the final one will be returned. -func (d *Device) attachKernelDriver() (err error) { - for iface := range d.detached { - switch attachErr := C.libusb_attach_kernel_driver(d.handle, C.int(iface)); attachErr { - case C.LIBUSB_ERROR_NOT_SUPPORTED: - // no need to do any futher checking, no platform support - return - case 0: - continue - default: - err = fmt.Errorf("usb: attach kernel driver: %s", usbError(attachErr)) - } - } - - return -} - -func (d *Device) Reset() error { - if errno := C.libusb_reset_device(d.handle); errno != 0 { - return usbError(errno) - } - return nil -} - -func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) { - //log.Printf("control xfer: %d:%d/%d:%d %x", idx, rType, request, val, string(data)) - dataSlice := (*reflect.SliceHeader)(unsafe.Pointer(&data)) - n := C.libusb_control_transfer( - d.handle, - C.uint8_t(rType), - C.uint8_t(request), - C.uint16_t(val), - C.uint16_t(idx), - (*C.uchar)(unsafe.Pointer(dataSlice.Data)), - C.uint16_t(len(data)), - C.uint(d.ControlTimeout/time.Millisecond)) - if n < 0 { - return int(n), usbError(n) - } - return int(n), nil -} - -// ActiveConfig returns the config id (not the index) of the active configuration. -// This corresponds to the ConfigInfo.Config field. -func (d *Device) ActiveConfig() (uint8, error) { - var cfg C.int - if errno := C.libusb_get_configuration(d.handle, &cfg); errno < 0 { - return 0, usbError(errno) - } - return uint8(cfg), nil -} - -// SetConfig attempts to change the active configuration. -// The cfg provided is the config id (not the index) of the configuration to set, -// which corresponds to the ConfigInfo.Config field. -func (d *Device) SetConfig(cfg uint8) error { - if errno := C.libusb_set_configuration(d.handle, C.int(cfg)); errno < 0 { - return usbError(errno) - } - return nil -} - -// Close the device. -func (d *Device) Close() error { - if d.handle == nil { - return fmt.Errorf("usb: double close on device") - } - d.lock.Lock() - defer d.lock.Unlock() - for iface := range d.claimed { - C.libusb_release_interface(d.handle, C.int(iface)) - } - d.attachKernelDriver() - C.libusb_close(d.handle) - d.handle = nil - return nil -} - -func (d *Device) OpenEndpoint(conf, iface, setup, epoint uint8) (Endpoint, error) { - end := &endpoint{ - Device: d, - } - - var setAlternate bool - for _, c := range d.Configs { - if c.Config != conf { - continue - } - debug.Printf("found conf: %#v\n", c) - for _, i := range c.Interfaces { - if i.Number != iface { - continue - } - debug.Printf("found iface: %#v\n", i) - for i, s := range i.Setups { - if s.Alternate != setup { - continue - } - setAlternate = i != 0 - - debug.Printf("found setup: %#v [default: %v]\n", s, !setAlternate) - for _, e := range s.Endpoints { - debug.Printf("ep %02x search: %#v\n", epoint, s) - if e.Address != epoint { - continue - } - end.InterfaceSetup = s - end.EndpointInfo = e - switch tt := TransferType(e.Attributes) & TRANSFER_TYPE_MASK; tt { - case TRANSFER_TYPE_BULK: - end.xfer = bulk_xfer - case TRANSFER_TYPE_INTERRUPT: - end.xfer = interrupt_xfer - case TRANSFER_TYPE_ISOCHRONOUS: - end.xfer = isochronous_xfer - default: - return nil, fmt.Errorf("usb: %s transfer is unsupported", tt) - } - goto found - } - return nil, fmt.Errorf("usb: unknown endpoint %02x", epoint) - } - return nil, fmt.Errorf("usb: unknown setup %02x", setup) - } - return nil, fmt.Errorf("usb: unknown interface %02x", iface) - } - return nil, fmt.Errorf("usb: unknown configuration %02x", conf) - -found: - - // Set the configuration - var activeConf C.int - if errno := C.libusb_get_configuration(d.handle, &activeConf); errno < 0 { - return nil, fmt.Errorf("usb: getcfg: %s", usbError(errno)) - } - if int(activeConf) != int(conf) { - if errno := C.libusb_set_configuration(d.handle, C.int(conf)); errno < 0 { - return nil, fmt.Errorf("usb: setcfg: %s", usbError(errno)) - } - } - - // Claim the interface - if errno := C.libusb_claim_interface(d.handle, C.int(iface)); errno < 0 { - return nil, fmt.Errorf("usb: claim: %s", usbError(errno)) - } - - // Increment the claim count - d.lock.Lock() - d.claimed[iface]++ - d.lock.Unlock() // unlock immediately because the next calls may block - - // Choose the alternate - if setAlternate { - if errno := C.libusb_set_interface_alt_setting(d.handle, C.int(iface), C.int(setup)); errno < 0 { - debug.Printf("altsetting error: %s", usbError(errno)) - return nil, fmt.Errorf("usb: setalt: %s", usbError(errno)) - } - } - - return end, nil -} - -func (d *Device) GetStringDescriptor(desc_index int) (string, error) { - - // allocate 200-byte array limited the length of string descriptor - goBuffer := make([]byte, 200) - - // get string descriptor from libusb. if errno < 0 then there are any errors. - // if errno >= 0; it is a length of result string descriptor - errno := C.libusb_get_string_descriptor_ascii( - d.handle, - C.uint8_t(desc_index), - (*C.uchar)(unsafe.Pointer(&goBuffer[0])), - 200) - - // if any errors occur - if errno < 0 { - return "", fmt.Errorf("usb: getstr: %s", usbError(errno)) - } - // convert slice of byte to string with limited length from errno - stringDescriptor := string(goBuffer[:errno]) - - return stringDescriptor, nil -} diff --git a/vendor/github.com/karalabe/gousb/usb/endpoint.go b/vendor/github.com/karalabe/gousb/usb/endpoint.go deleted file mode 100644 index 12b4ccf950b..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/endpoint.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -// #include "libusb.h" -import "C" - -import ( - "fmt" - "reflect" - "time" - "unsafe" -) - -type Endpoint interface { - Read(b []byte) (int, error) - Write(b []byte) (int, error) - Interface() InterfaceSetup - Info() EndpointInfo -} - -type endpoint struct { - *Device - InterfaceSetup - EndpointInfo - xfer func(*endpoint, []byte, time.Duration) (int, error) -} - -func (e *endpoint) Read(buf []byte) (int, error) { - if EndpointDirection(e.Address)&ENDPOINT_DIR_MASK != ENDPOINT_DIR_IN { - return 0, fmt.Errorf("usb: read: not an IN endpoint") - } - - return e.xfer(e, buf, e.ReadTimeout) -} - -func (e *endpoint) Write(buf []byte) (int, error) { - if EndpointDirection(e.Address)&ENDPOINT_DIR_MASK != ENDPOINT_DIR_OUT { - return 0, fmt.Errorf("usb: write: not an OUT endpoint") - } - - return e.xfer(e, buf, e.WriteTimeout) -} - -func (e *endpoint) Interface() InterfaceSetup { return e.InterfaceSetup } -func (e *endpoint) Info() EndpointInfo { return e.EndpointInfo } - -// TODO(kevlar): (*Endpoint).Close - -func bulk_xfer(e *endpoint, buf []byte, timeout time.Duration) (int, error) { - if len(buf) == 0 { - return 0, nil - } - - data := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data - - var cnt C.int - if errno := C.libusb_bulk_transfer( - e.handle, - C.uchar(e.Address), - (*C.uchar)(unsafe.Pointer(data)), - C.int(len(buf)), - &cnt, - C.uint(timeout/time.Millisecond)); errno < 0 { - return 0, usbError(errno) - } - return int(cnt), nil -} - -func interrupt_xfer(e *endpoint, buf []byte, timeout time.Duration) (int, error) { - if len(buf) == 0 { - return 0, nil - } - - data := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data - - var cnt C.int - if errno := C.libusb_interrupt_transfer( - e.handle, - C.uchar(e.Address), - (*C.uchar)(unsafe.Pointer(data)), - C.int(len(buf)), - &cnt, - C.uint(timeout/time.Millisecond)); errno < 0 { - return 0, usbError(errno) - } - return int(cnt), nil -} diff --git a/vendor/github.com/karalabe/gousb/usb/error.go b/vendor/github.com/karalabe/gousb/usb/error.go deleted file mode 100644 index 30d47bce37a..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/error.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -import ( - "fmt" -) - -// #include "libusb.h" -import "C" - -type usbError C.int - -func (e usbError) Error() string { - return fmt.Sprintf("libusb: %s [code %d]", usbErrorString[e], int(e)) -} - -const ( - SUCCESS usbError = C.LIBUSB_SUCCESS - ERROR_IO usbError = C.LIBUSB_ERROR_IO - ERROR_INVALID_PARAM usbError = C.LIBUSB_ERROR_INVALID_PARAM - ERROR_ACCESS usbError = C.LIBUSB_ERROR_ACCESS - ERROR_NO_DEVICE usbError = C.LIBUSB_ERROR_NO_DEVICE - ERROR_NOT_FOUND usbError = C.LIBUSB_ERROR_NOT_FOUND - ERROR_BUSY usbError = C.LIBUSB_ERROR_BUSY - ERROR_TIMEOUT usbError = C.LIBUSB_ERROR_TIMEOUT - ERROR_OVERFLOW usbError = C.LIBUSB_ERROR_OVERFLOW - ERROR_PIPE usbError = C.LIBUSB_ERROR_PIPE - ERROR_INTERRUPTED usbError = C.LIBUSB_ERROR_INTERRUPTED - ERROR_NO_MEM usbError = C.LIBUSB_ERROR_NO_MEM - ERROR_NOT_SUPPORTED usbError = C.LIBUSB_ERROR_NOT_SUPPORTED - ERROR_OTHER usbError = C.LIBUSB_ERROR_OTHER -) - -var usbErrorString = map[usbError]string{ - C.LIBUSB_SUCCESS: "success", - C.LIBUSB_ERROR_IO: "i/o error", - C.LIBUSB_ERROR_INVALID_PARAM: "invalid param", - C.LIBUSB_ERROR_ACCESS: "bad access", - C.LIBUSB_ERROR_NO_DEVICE: "no device", - C.LIBUSB_ERROR_NOT_FOUND: "not found", - C.LIBUSB_ERROR_BUSY: "device or resource busy", - C.LIBUSB_ERROR_TIMEOUT: "timeout", - C.LIBUSB_ERROR_OVERFLOW: "overflow", - C.LIBUSB_ERROR_PIPE: "pipe error", - C.LIBUSB_ERROR_INTERRUPTED: "interrupted", - C.LIBUSB_ERROR_NO_MEM: "out of memory", - C.LIBUSB_ERROR_NOT_SUPPORTED: "not supported", - C.LIBUSB_ERROR_OTHER: "unknown error", -} - -type TransferStatus uint8 - -const ( - LIBUSB_TRANSFER_COMPLETED TransferStatus = C.LIBUSB_TRANSFER_COMPLETED - LIBUSB_TRANSFER_ERROR TransferStatus = C.LIBUSB_TRANSFER_ERROR - LIBUSB_TRANSFER_TIMED_OUT TransferStatus = C.LIBUSB_TRANSFER_TIMED_OUT - LIBUSB_TRANSFER_CANCELLED TransferStatus = C.LIBUSB_TRANSFER_CANCELLED - LIBUSB_TRANSFER_STALL TransferStatus = C.LIBUSB_TRANSFER_STALL - LIBUSB_TRANSFER_NO_DEVICE TransferStatus = C.LIBUSB_TRANSFER_NO_DEVICE - LIBUSB_TRANSFER_OVERFLOW TransferStatus = C.LIBUSB_TRANSFER_OVERFLOW -) - -var transferStatusDescription = map[TransferStatus]string{ - LIBUSB_TRANSFER_COMPLETED: "transfer completed without error", - LIBUSB_TRANSFER_ERROR: "transfer failed", - LIBUSB_TRANSFER_TIMED_OUT: "transfer timed out", - LIBUSB_TRANSFER_CANCELLED: "transfer was cancelled", - LIBUSB_TRANSFER_STALL: "halt condition detected (endpoint stalled) or control request not supported", - LIBUSB_TRANSFER_NO_DEVICE: "device was disconnected", - LIBUSB_TRANSFER_OVERFLOW: "device sent more data than requested", -} - -func (ts TransferStatus) String() string { - return transferStatusDescription[ts] -} - -func (ts TransferStatus) Error() string { - return "libusb: " + ts.String() -} diff --git a/vendor/github.com/karalabe/gousb/usb/iso.c b/vendor/github.com/karalabe/gousb/usb/iso.c deleted file mode 100644 index 0544863184f..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/iso.c +++ /dev/null @@ -1,79 +0,0 @@ -#include "libusb.h" -#include -#include - -void print_xfer(struct libusb_transfer *xfer); -void iso_callback(void *); - -void callback(struct libusb_transfer *xfer) { - //printf("Callback!\n"); - //print_xfer(xfer); - iso_callback(xfer->user_data); -} - -int submit(struct libusb_transfer *xfer) { - xfer->callback = &callback; - xfer->status = -1; - //print_xfer(xfer); - //printf("Transfer submitted\n"); - - /* fake - strcpy(xfer->buffer, "hello"); - xfer->actual_length = 5; - callback(xfer); - return 0; */ - return libusb_submit_transfer(xfer); -} - -void print_xfer(struct libusb_transfer *xfer) { - int i; - - printf("Transfer:\n"); - printf(" dev_handle: %p\n", xfer->dev_handle); - printf(" flags: %08x\n", xfer->flags); - printf(" endpoint: %x\n", xfer->endpoint); - printf(" type: %x\n", xfer->type); - printf(" timeout: %dms\n", xfer->timeout); - printf(" status: %x\n", xfer->status); - printf(" length: %d (act: %d)\n", xfer->length, xfer->actual_length); - printf(" callback: %p\n", xfer->callback); - printf(" user_data: %p\n", xfer->user_data); - printf(" buffer: %p\n", xfer->buffer); - printf(" num_iso_pkts: %d\n", xfer->num_iso_packets); - printf(" packets:\n"); - for (i = 0; i < xfer->num_iso_packets; i++) { - printf(" [%04d] %d (act: %d) %x\n", i, - xfer->iso_packet_desc[i].length, - xfer->iso_packet_desc[i].actual_length, - xfer->iso_packet_desc[i].status); - } -} - -int extract_data(struct libusb_transfer *xfer, void *raw, int max, unsigned char *status) { - int i; - int copied = 0; - unsigned char *in = xfer->buffer; - unsigned char *out = raw; - for (i = 0; i < xfer->num_iso_packets; i++) { - struct libusb_iso_packet_descriptor pkt = xfer->iso_packet_desc[i]; - - // Copy the data - int len = pkt.actual_length; - if (len > max) { - len = max; - } - memcpy(out, in, len); - copied += len; - - // Increment offsets - in += pkt.length; - out += len; - - // Extract first error - if (pkt.status == 0 || *status != 0) { - continue; - } - *status = pkt.status; - } - return copied; -} diff --git a/vendor/github.com/karalabe/gousb/usb/iso.go b/vendor/github.com/karalabe/gousb/usb/iso.go deleted file mode 100644 index 1ba694e0e7f..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/iso.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -/* -#include "libusb.h" - -int submit(struct libusb_transfer *xfer); -void print_xfer(struct libusb_transfer *xfer); -int extract_data(struct libusb_transfer *xfer, void *data, int max, unsigned char *status); -*/ -import "C" - -import ( - "fmt" - "log" - "time" - "unsafe" -) - -//export iso_callback -func iso_callback(cptr unsafe.Pointer) { - ch := *(*chan struct{})(cptr) - close(ch) -} - -func (end *endpoint) allocTransfer() *Transfer { - // Use libusb_get_max_iso_packet_size ? - const ( - iso_packets = 8 // 128 // 242 - packet_size = 2 * 960 // 1760 - ) - - xfer := C.libusb_alloc_transfer(C.int(iso_packets)) - if xfer == nil { - log.Printf("usb: transfer allocation failed?!") - return nil - } - - buf := make([]byte, iso_packets*packet_size) - done := make(chan struct{}, 1) - - xfer.dev_handle = end.Device.handle - xfer.endpoint = C.uchar(end.Address) - xfer._type = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS - - xfer.buffer = (*C.uchar)((unsafe.Pointer)(&buf[0])) - xfer.length = C.int(len(buf)) - xfer.num_iso_packets = iso_packets - - C.libusb_set_iso_packet_lengths(xfer, packet_size) - /* - pkts := *(*[]C.struct_libusb_packet_descriptor)(unsafe.Pointer(&reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(&xfer.iso_packet_desc)), - Len: iso_packets, - Cap: iso_packets, - })) - */ - - t := &Transfer{ - xfer: xfer, - done: done, - buf: buf, - } - xfer.user_data = (unsafe.Pointer)(&t.done) - - return t -} - -type Transfer struct { - xfer *C.struct_libusb_transfer - pkts []*C.struct_libusb_packet_descriptor - done chan struct{} - buf []byte -} - -func (t *Transfer) Submit(timeout time.Duration) error { - //log.Printf("iso: submitting %#v", t.xfer) - t.xfer.timeout = C.uint(timeout / time.Millisecond) - if errno := C.submit(t.xfer); errno < 0 { - return usbError(errno) - } - return nil -} - -func (t *Transfer) Wait(b []byte) (n int, err error) { - select { - case <-time.After(10 * time.Second): - return 0, fmt.Errorf("wait timed out after 10s") - case <-t.done: - } - // Non-iso transfers: - //n = int(t.xfer.actual_length) - //copy(b, ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer)))[:n]) - - //C.print_xfer(t.xfer) - /* - buf, offset := ((*[1 << 16]byte)(unsafe.Pointer(t.xfer.buffer))), 0 - for i, pkt := range *t.pkts { - log.Printf("Type is %T", t.pkts) - n += copy(b[n:], buf[offset:][:pkt.actual_length]) - offset += pkt.Length - if pkt.status != 0 && err == nil { - err = error(TransferStatus(pkt.status)) - } - } - */ - var status uint8 - n = int(C.extract_data(t.xfer, unsafe.Pointer(&b[0]), C.int(len(b)), (*C.uchar)(unsafe.Pointer(&status)))) - if status != 0 { - err = TransferStatus(status) - } - return n, err -} - -func (t *Transfer) Close() error { - C.libusb_free_transfer(t.xfer) - return nil -} - -func isochronous_xfer(e *endpoint, buf []byte, timeout time.Duration) (int, error) { - t := e.allocTransfer() - defer t.Close() - - if err := t.Submit(timeout); err != nil { - log.Printf("iso: xfer failed to submit: %s", err) - return 0, err - } - - n, err := t.Wait(buf) - if err != nil { - log.Printf("iso: xfer failed: %s", err) - return 0, err - } - return n, err -} diff --git a/vendor/github.com/karalabe/gousb/usb/misc.go b/vendor/github.com/karalabe/gousb/usb/misc.go deleted file mode 100644 index 6e25431bf3d..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/misc.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package usb - -import ( - "fmt" -) - -type BCD uint16 - -const ( - USB_2_0 BCD = 0x0200 - USB_1_1 BCD = 0x0110 - USB_1_0 BCD = 0x0100 -) - -func (d BCD) Int() (i int) { - ten := 1 - for o := uint(0); o < 4; o++ { - n := ((0xF << (o * 4)) & d) >> (o * 4) - i += int(n) * ten - ten *= 10 - } - return -} - -func (d BCD) String() string { - return fmt.Sprintf("%02x.%02x", int(d>>8), int(d&0xFF)) -} - -type ID uint16 - -func (id ID) String() string { - return fmt.Sprintf("%04x", int(id)) -} diff --git a/vendor/github.com/karalabe/gousb/usb/usb.go b/vendor/github.com/karalabe/gousb/usb/usb.go deleted file mode 100644 index 366827e69a0..00000000000 --- a/vendor/github.com/karalabe/gousb/usb/usb.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package usb provides a wrapper around libusb-1.0. -package usb - -/* -#cgo CFLAGS: -I../internal/libusb/libusb -#cgo CFLAGS: -DDEFAULT_VISIBILITY="" -#cgo linux CFLAGS: -DOS_LINUX -D_GNU_SOURCE -DPOLL_NFDS_TYPE=int -#cgo darwin CFLAGS: -DOS_DARWIN -DPOLL_NFDS_TYPE=int -#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit -lobjc -#cgo openbsd CFLAGS: -DOS_OPENBSD -DPOLL_NFDS_TYPE=int -#cgo windows CFLAGS: -DOS_WINDOWS -DUSE_USBDK -DPOLL_NFDS_TYPE=int - -#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) - #include - #include "os/threads_posix.c" - #include "os/poll_posix.c" -#elif defined(OS_WINDOWS) - #include "os/threads_windows.c" - #include "os/poll_windows.c" -#endif - -#ifdef OS_LINUX - #include "os/linux_usbfs.c" - #include "os/linux_netlink.c" -#elif OS_DARWIN - #include "os/darwin_usb.c" -#elif OS_OPENBSD - #include "os/openbsd_usb.c" -#elif OS_WINDOWS - #include "os/windows_nt_common.c" - #include "os/windows_usbdk.c" -#endif - -#include "core.c" -#include "descriptor.c" -#include "hotplug.c" -#include "io.c" -#include "strerror.c" -#include "sync.c" -*/ -import "C" - -import ( - "log" - "reflect" - "unsafe" -) - -type Context struct { - ctx *C.libusb_context - done chan struct{} -} - -func (c *Context) Debug(level int) { - C.libusb_set_debug(c.ctx, C.int(level)) -} - -func NewContext() (*Context, error) { - c := &Context{ - done: make(chan struct{}), - } - - if errno := C.libusb_init(&c.ctx); errno != 0 { - return nil, usbError(errno) - } - - go func() { - tv := C.struct_timeval{ - tv_sec: 0, - tv_usec: 100000, - } - for { - select { - case <-c.done: - return - default: - } - if errno := C.libusb_handle_events_timeout_completed(c.ctx, &tv, nil); errno < 0 { - log.Printf("handle_events: error: %s", usbError(errno)) - continue - } - //log.Printf("handle_events returned") - } - }() - - return c, nil -} - -// ListDevices calls each with each enumerated device. -// If the function returns true, the device is opened and a Device is returned if the operation succeeds. -// Every Device returned (whether an error is also returned or not) must be closed. -// If there are any errors enumerating the devices, -// the final one is returned along with any successfully opened devices. -func (c *Context) ListDevices(each func(desc *Descriptor) bool) ([]*Device, error) { - var list **C.libusb_device - cnt := C.libusb_get_device_list(c.ctx, &list) - if cnt < 0 { - return nil, usbError(cnt) - } - defer C.libusb_free_device_list(list, 1) - - var slice []*C.libusb_device - *(*reflect.SliceHeader)(unsafe.Pointer(&slice)) = reflect.SliceHeader{ - Data: uintptr(unsafe.Pointer(list)), - Len: int(cnt), - Cap: int(cnt), - } - - var reterr error - var ret []*Device - for _, dev := range slice { - desc, err := newDescriptor(dev) - if err != nil { - reterr = err - continue - } - - if each(desc) { - var handle *C.libusb_device_handle - if errno := C.libusb_open(dev, &handle); errno != 0 { - reterr = usbError(errno) - continue - } - if dev, err := newDevice(handle, desc); err != nil { - reterr = err - } else { - ret = append(ret, dev) - } - } - } - return ret, reterr -} - -// OpenDeviceWithVidPid opens Device from specific VendorId and ProductId. -// If there are any errors, it'll returns at second value. -func (c *Context) OpenDeviceWithVidPid(vid, pid int) (*Device, error) { - - handle := C.libusb_open_device_with_vid_pid(c.ctx, (C.uint16_t)(vid), (C.uint16_t)(pid)) - if handle == nil { - return nil, ERROR_NOT_FOUND - } - - dev := C.libusb_get_device(handle) - if dev == nil { - return nil, ERROR_NO_DEVICE - } - - desc, err := newDescriptor(dev) - - // return an error from nil-handle and nil-device - if err != nil { - return nil, err - } - return newDevice(handle, desc) -} - -func (c *Context) Close() error { - close(c.done) - if c.ctx != nil { - C.libusb_exit(c.ctx) - } - c.ctx = nil - return nil -} diff --git a/vendor/github.com/karalabe/hid/.travis.yml b/vendor/github.com/karalabe/hid/.travis.yml index e17367c9bf9..18b20676a1b 100644 --- a/vendor/github.com/karalabe/hid/.travis.yml +++ b/vendor/github.com/karalabe/hid/.travis.yml @@ -22,3 +22,4 @@ matrix: script: - go install ./... + - go test -v ./... diff --git a/vendor/github.com/karalabe/hid/README.md b/vendor/github.com/karalabe/hid/README.md index 5c0213f3b21..2851ffe4200 100644 --- a/vendor/github.com/karalabe/hid/README.md +++ b/vendor/github.com/karalabe/hid/README.md @@ -24,6 +24,12 @@ and go-gettable. Supported platforms at the moment are Linux, macOS and Windows (exclude constraints are also specified for Android and iOS to allow smoother vendoring into cross platform projects). +## Cross-compiling + +Using `go get` the embedded C library is compiled into the binary format of your host OS. Cross compiling to a different platform or architecture entails disabling CGO by default in Go, causing device enumeration `hid.Enumerate()` to yield no results. + +To cross compile a functional version of this library, you'll need to enable CGO during cross compilation via `CGO_ENABLED=1` and you'll need to install and set a cross compilation enabled C toolkit via `CC=your-cross-gcc`. + ## Acknowledgements Although the `hid` package is an implementation from scratch, it was heavily inspired by the existing diff --git a/vendor/github.com/karalabe/hid/appveyor.yml b/vendor/github.com/karalabe/hid/appveyor.yml index 34623ddb018..f43958747c8 100644 --- a/vendor/github.com/karalabe/hid/appveyor.yml +++ b/vendor/github.com/karalabe/hid/appveyor.yml @@ -29,3 +29,4 @@ install: build_script: - go install ./... + - go test -v ./... diff --git a/vendor/github.com/karalabe/hid/hid.go b/vendor/github.com/karalabe/hid/hid.go index be75f949d85..60a40b8c24a 100644 --- a/vendor/github.com/karalabe/hid/hid.go +++ b/vendor/github.com/karalabe/hid/hid.go @@ -2,7 +2,7 @@ // Copyright (c) 2017 Péter Szilágyi. All rights reserved. // // This file is released under the 3-clause BSD license. Note however that Linux -// support depends on libusb, released under GNU GPL 2.1 or later. +// support depends on libusb, released under GNU LGPL 2.1 or later. // Package hid provides an interface for USB HID devices. package hid diff --git a/vendor/github.com/karalabe/hid/hid_disabled.go b/vendor/github.com/karalabe/hid/hid_disabled.go index d8ecc9d5a2c..1f402637917 100644 --- a/vendor/github.com/karalabe/hid/hid_disabled.go +++ b/vendor/github.com/karalabe/hid/hid_disabled.go @@ -2,7 +2,7 @@ // Copyright (c) 2017 Péter Szilágyi. All rights reserved. // // This file is released under the 3-clause BSD license. Note however that Linux -// support depends on libusb, released under GNU GPL 2.1 or later. +// support depends on libusb, released under GNU LGPL 2.1 or later. // +build !linux,!darwin,!windows ios !cgo diff --git a/vendor/github.com/karalabe/hid/hid_enabled.go b/vendor/github.com/karalabe/hid/hid_enabled.go index 3ceecce0d3e..419273be6a3 100644 --- a/vendor/github.com/karalabe/hid/hid_enabled.go +++ b/vendor/github.com/karalabe/hid/hid_enabled.go @@ -2,7 +2,7 @@ // Copyright (c) 2017 Péter Szilágyi. All rights reserved. // // This file is released under the 3-clause BSD license. Note however that Linux -// support depends on libusb, released under GNU GPL 2.1 or later. +// support depends on libusb, released under LGNU GPL 2.1 or later. // +build linux,cgo darwin,!ios,cgo windows,cgo @@ -48,6 +48,15 @@ import ( "unsafe" ) +// enumerateLock is a mutex serializing access to USB device enumeration needed +// by the macOS USB HID system calls, which require 2 consecutive method calls +// for enumeration, causing crashes if called concurrently. +// +// For more details, see: +// https://developer.apple.com/documentation/iokit/1438371-iohidmanagersetdevicematching +// > "subsequent calls will cause the hid manager to release previously enumerated devices" +var enumerateLock sync.Mutex + func init() { // Initialize the HIDAPI library C.hid_init() @@ -66,6 +75,9 @@ func Supported() bool { // - If the product id is set to 0 then any product matches. // - If the vendor and product id are both 0, all HID devices are returned. func Enumerate(vendorID uint16, productID uint16) []DeviceInfo { + enumerateLock.Lock() + defer enumerateLock.Unlock() + // Gather all device infos and ensure they are freed before returning head := C.hid_enumerate(C.ushort(vendorID), C.ushort(productID)) if head == nil { diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml index 98db8f060bd..42768b8bf3b 100644 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ b/vendor/github.com/mattn/go-colorable/.travis.yml @@ -2,8 +2,7 @@ language: go go: - tip -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover +sudo: false + script: - - $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw + - go test -v diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md index 56729a92ca6..e84226a7358 100644 --- a/vendor/github.com/mattn/go-colorable/README.md +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -1,10 +1,5 @@ # go-colorable -[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) -[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) -[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master) -[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) - Colorable writer for windows. For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.) diff --git a/vendor/github.com/mattn/go-colorable/_example/escape-seq/main.go b/vendor/github.com/mattn/go-colorable/_example/escape-seq/main.go deleted file mode 100644 index 8cbcb909760..00000000000 --- a/vendor/github.com/mattn/go-colorable/_example/escape-seq/main.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - - "github.com/mattn/go-colorable" -) - -func main() { - stdOut := bufio.NewWriter(colorable.NewColorableStdout()) - - fmt.Fprint(stdOut, "\x1B[3GMove to 3rd Column\n") - fmt.Fprint(stdOut, "\x1B[1;2HMove to 2nd Column on 1st Line\n") - stdOut.Flush() -} diff --git a/vendor/github.com/mattn/go-colorable/_example/logrus/main.go b/vendor/github.com/mattn/go-colorable/_example/logrus/main.go deleted file mode 100644 index 0da0906c7b3..00000000000 --- a/vendor/github.com/mattn/go-colorable/_example/logrus/main.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "github.com/Sirupsen/logrus" - "github.com/mattn/go-colorable" -) - -func main() { - logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true}) - logrus.SetOutput(colorable.NewColorableStdout()) - - logrus.Info("succeeded") - logrus.Warn("not correct") - logrus.Error("something error") - logrus.Fatal("panic") -} diff --git a/vendor/github.com/mattn/go-colorable/_example/title/main.go b/vendor/github.com/mattn/go-colorable/_example/title/main.go deleted file mode 100644 index e208870e779..00000000000 --- a/vendor/github.com/mattn/go-colorable/_example/title/main.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "fmt" - "os" - . "github.com/mattn/go-colorable" -) - -func main() { - out := NewColorableStdout() - fmt.Fprint(out, "\x1B]0;TITLE Changed\007(See title and hit any key)") - var c [1]byte - os.Stdin.Read(c[:]) -} diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go deleted file mode 100644 index 49343e5f601..00000000000 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ /dev/null @@ -1,27 +0,0 @@ -// +build appengine - -package colorable - -import ( - "io" - "os" -) - -// NewColorable return new instance of Writer which handle escape sequence. -func NewColorable(file *os.File) io.Writer { - if file == nil { - panic("nil passed instead of *os.File to NewColorable()") - } - - return file -} - -// NewColorableStdout return new instance of Writer which handle escape sequence for stdout. -func NewColorableStdout() io.Writer { - return os.Stdout -} - -// NewColorableStderr return new instance of Writer which handle escape sequence for stderr. -func NewColorableStderr() io.Writer { - return os.Stderr -} diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go index d28f5429da4..a7fe19a8ca0 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -1,5 +1,4 @@ // +build !windows -// +build !appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index 6194eb92d25..628ad904e59 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -1,6 +1,3 @@ -// +build windows -// +build !appengine - package colorable import ( @@ -68,13 +65,12 @@ var ( procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute") procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") - procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") ) -// Writer provide colorable Writer to the console type Writer struct { out io.Writer handle syscall.Handle + lastbuf bytes.Buffer oldattr word oldpos coord } @@ -90,8 +86,9 @@ func NewColorable(file *os.File) io.Writer { handle := syscall.Handle(file.Fd()) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}} + } else { + return file } - return file } // NewColorableStdout return new instance of Writer which handle escape sequence for stdout. @@ -363,45 +360,6 @@ var color256 = map[int]int{ 255: 0xeeeeee, } -// `\033]0;TITLESTR\007` -func doTitleSequence(er *bytes.Reader) error { - var c byte - var err error - - c, err = er.ReadByte() - if err != nil { - return err - } - if c != '0' && c != '2' { - return nil - } - c, err = er.ReadByte() - if err != nil { - return err - } - if c != ';' { - return nil - } - title := make([]byte, 0, 80) - for { - c, err = er.ReadByte() - if err != nil { - return err - } - if c == 0x07 || c == '\n' { - break - } - title = append(title, c) - } - if len(title) > 0 { - title8, err := syscall.UTF16PtrFromString(string(title)) - if err == nil { - procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8))) - } - } - return nil -} - // Write write data on console func (w *Writer) Write(data []byte) (n int, err error) { var csbi consoleScreenBufferInfo @@ -427,16 +385,12 @@ loop: } c2, err := er.ReadByte() if err != nil { + w.lastbuf.WriteByte(c1) break loop } - - if c2 == ']' { - if err := doTitleSequence(er); err != nil { - break loop - } - continue - } if c2 != 0x5b { + w.lastbuf.WriteByte(c1) + w.lastbuf.WriteByte(c2) continue } @@ -445,6 +399,9 @@ loop: for { c, err := er.ReadByte() if err != nil { + w.lastbuf.WriteByte(c1) + w.lastbuf.WriteByte(c2) + w.lastbuf.Write(buf.Bytes()) break loop } if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { @@ -454,12 +411,14 @@ loop: buf.Write([]byte(string(c))) } + var csbi consoleScreenBufferInfo switch m { case 'A': n, err = strconv.Atoi(buf.String()) if err != nil { continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.y -= short(n) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'B': @@ -467,6 +426,7 @@ loop: if err != nil { continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.y += short(n) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'C': @@ -474,6 +434,7 @@ loop: if err != nil { continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x -= short(n) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'D': @@ -483,6 +444,7 @@ loop: } if n, err = strconv.Atoi(buf.String()); err == nil { var csbi consoleScreenBufferInfo + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x += short(n) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) } @@ -491,6 +453,7 @@ loop: if err != nil { continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = 0 csbi.cursorPosition.y += short(n) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) @@ -499,6 +462,7 @@ loop: if err != nil { continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = 0 csbi.cursorPosition.y -= short(n) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) @@ -507,65 +471,50 @@ loop: if err != nil { continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = short(n - 1) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'H': - if buf.Len() > 0 { - token := strings.Split(buf.String(), ";") - switch len(token) { - case 1: - n1, err := strconv.Atoi(token[0]) - if err != nil { - continue - } - csbi.cursorPosition.y = short(n1 - 1) - case 2: - n1, err := strconv.Atoi(token[0]) - if err != nil { - continue - } - n2, err := strconv.Atoi(token[1]) - if err != nil { - continue - } - csbi.cursorPosition.x = short(n2 - 1) - csbi.cursorPosition.y = short(n1 - 1) - } - } else { - csbi.cursorPosition.y = 0 + token := strings.Split(buf.String(), ";") + if len(token) != 2 { + continue } + n1, err := strconv.Atoi(token[0]) + if err != nil { + continue + } + n2, err := strconv.Atoi(token[1]) + if err != nil { + continue + } + csbi.cursorPosition.x = short(n2 - 1) + csbi.cursorPosition.y = short(n1 - 1) procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'J': - n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } + n, err := strconv.Atoi(buf.String()) + if err != nil { + continue } - var count, written dword + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) var cursor coord switch n { case 0: cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} - count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) case 1: cursor = coord{x: csbi.window.left, y: csbi.window.top} - count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x) case 2: cursor = coord{x: csbi.window.left, y: csbi.window.top} - count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) } + var count, written dword + count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) case 'K': - n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) - if err != nil { - continue - } + n, err := strconv.Atoi(buf.String()) + if err != nil { + continue } + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) var cursor coord switch n { case 0: @@ -580,6 +529,7 @@ loop: procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) case 'm': + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) attr := csbi.attributes cs := buf.String() if cs == "" { @@ -597,7 +547,7 @@ loop: attr |= foregroundIntensity case n == 7: attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) - case n == 22 || n == 25: + case 22 == n || n == 25 || n == 25: attr |= foregroundIntensity case n == 27: attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) @@ -700,13 +650,13 @@ loop: procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) } case 's': + procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) w.oldpos = csbi.cursorPosition case 'u': procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) } } - - return len(data), nil + return len(data) - w.lastbuf.Len(), nil } type consoleColor struct { @@ -750,22 +700,22 @@ func (c consoleColor) backgroundAttr() (attr word) { } var color16 = []consoleColor{ - {0x000000, false, false, false, false}, - {0x000080, false, false, true, false}, - {0x008000, false, true, false, false}, - {0x008080, false, true, true, false}, - {0x800000, true, false, false, false}, - {0x800080, true, false, true, false}, - {0x808000, true, true, false, false}, - {0xc0c0c0, true, true, true, false}, - {0x808080, false, false, false, true}, - {0x0000ff, false, false, true, true}, - {0x00ff00, false, true, false, true}, - {0x00ffff, false, true, true, true}, - {0xff0000, true, false, false, true}, - {0xff00ff, true, false, true, true}, - {0xffff00, true, true, false, true}, - {0xffffff, true, true, true, true}, + consoleColor{0x000000, false, false, false, false}, + consoleColor{0x000080, false, false, true, false}, + consoleColor{0x008000, false, true, false, false}, + consoleColor{0x008080, false, true, true, false}, + consoleColor{0x800000, true, false, false, false}, + consoleColor{0x800080, true, false, true, false}, + consoleColor{0x808000, true, true, false, false}, + consoleColor{0xc0c0c0, true, true, true, false}, + consoleColor{0x808080, false, false, false, true}, + consoleColor{0x0000ff, false, false, true, true}, + consoleColor{0x00ff00, false, true, false, true}, + consoleColor{0x00ffff, false, true, true, true}, + consoleColor{0xff0000, true, false, false, true}, + consoleColor{0xff00ff, true, false, true, true}, + consoleColor{0xffff00, true, true, false, true}, + consoleColor{0xffffff, true, true, true, true}, } type hsv struct { diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go index 9721e16f4bf..ca588c78ac7 100644 --- a/vendor/github.com/mattn/go-colorable/noncolorable.go +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -7,7 +7,8 @@ import ( // NonColorable hold writer but remove escape sequence. type NonColorable struct { - out io.Writer + out io.Writer + lastbuf bytes.Buffer } // NewNonColorable return new instance of Writer which remove escape sequence from Writer. @@ -32,9 +33,12 @@ loop: } c2, err := er.ReadByte() if err != nil { + w.lastbuf.WriteByte(c1) break loop } if c2 != 0x5b { + w.lastbuf.WriteByte(c1) + w.lastbuf.WriteByte(c2) continue } @@ -42,6 +46,9 @@ loop: for { c, err := er.ReadByte() if err != nil { + w.lastbuf.WriteByte(c1) + w.lastbuf.WriteByte(c2) + w.lastbuf.Write(buf.Bytes()) break loop } if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { @@ -50,6 +57,5 @@ loop: buf.Write([]byte(string(c))) } } - - return len(data), nil + return len(data) - w.lastbuf.Len(), nil } diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml new file mode 100644 index 00000000000..b8111d67911 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/.travis.yml @@ -0,0 +1,8 @@ +language: go +go: + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken 3gHdORO5k5ziZcWMBxnd9LrMZaJs8m9x5 diff --git a/vendor/github.com/mattn/go-isatty/LICENSE b/vendor/github.com/mattn/go-isatty/LICENSE new file mode 100644 index 00000000000..65dc692b6b1 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) Yasuhiro MATSUMOTO + +MIT License (Expat) + +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/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md new file mode 100644 index 00000000000..8e4365f45e2 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -0,0 +1,47 @@ +# go-isatty + +[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) [![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) + +isatty for golang + +## Usage + +```go +package main + +import ( + "fmt" + "github.com/mattn/go-isatty" + "os" +) + +func main() { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Println("Is Terminal") + } else if isatty.IsCygwinTerminal(os.Stdout.Fd()) { + fmt.Println("Is Cygwin/MSYS2 Terminal") + } else { + fmt.Println("Is Not Terminal") + } +} +``` + +## Installation + +``` +$ go get github.com/mattn/go-isatty +``` + +## License + +MIT + +## Author + +Yasuhiro Matsumoto (a.k.a mattn) + +## Thanks + +* k-takata: base idea for IsCygwinTerminal + + https://github.com/k-takata/go-iscygpty diff --git a/vendor/github.com/mattn/go-isatty/doc.go b/vendor/github.com/mattn/go-isatty/doc.go new file mode 100644 index 00000000000..17d4f90ebcc --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/doc.go @@ -0,0 +1,2 @@ +// Package isatty implements interface to isatty +package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_appengine.go b/vendor/github.com/mattn/go-isatty/isatty_appengine.go new file mode 100644 index 00000000000..83c588773cf --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_appengine.go @@ -0,0 +1,9 @@ +// +build appengine + +package isatty + +// IsTerminal returns true if the file descriptor is terminal which +// is always false on on appengine classic which is a sandboxed PaaS. +func IsTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go new file mode 100644 index 00000000000..42f2514d133 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -0,0 +1,18 @@ +// +build darwin freebsd openbsd netbsd dragonfly +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TIOCGETA + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_linux.go b/vendor/github.com/mattn/go-isatty/isatty_linux.go new file mode 100644 index 00000000000..9d24bac1db3 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_linux.go @@ -0,0 +1,18 @@ +// +build linux +// +build !appengine + +package isatty + +import ( + "syscall" + "unsafe" +) + +const ioctlReadTermios = syscall.TCGETS + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_not_windows.go b/vendor/github.com/mattn/go-isatty/isatty_not_windows.go new file mode 100644 index 00000000000..616832d23eb --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_not_windows.go @@ -0,0 +1,9 @@ +// +build !windows appengine + +package isatty + +// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go new file mode 100644 index 00000000000..1f0c6bf53dc --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -0,0 +1,16 @@ +// +build solaris +// +build !appengine + +package isatty + +import ( + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +func IsTerminal(fd uintptr) bool { + var termio unix.Termio + err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + return err == nil +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go new file mode 100644 index 00000000000..af51cbcaa48 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -0,0 +1,94 @@ +// +build windows +// +build !appengine + +package isatty + +import ( + "strings" + "syscall" + "unicode/utf16" + "unsafe" +) + +const ( + fileNameInfo uintptr = 2 + fileTypePipe = 3 +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx") + procGetFileType = kernel32.NewProc("GetFileType") +) + +func init() { + // Check if GetFileInformationByHandleEx is available. + if procGetFileInformationByHandleEx.Find() != nil { + procGetFileInformationByHandleEx = nil + } +} + +// IsTerminal return true if the file descriptor is terminal. +func IsTerminal(fd uintptr) bool { + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 +} + +// Check pipe name is used for cygwin/msys2 pty. +// Cygwin/MSYS2 PTY has a name like: +// \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master +func isCygwinPipeName(name string) bool { + token := strings.Split(name, "-") + if len(token) < 5 { + return false + } + + if token[0] != `\msys` && token[0] != `\cygwin` { + return false + } + + if token[1] == "" { + return false + } + + if !strings.HasPrefix(token[2], "pty") { + return false + } + + if token[3] != `from` && token[3] != `to` { + return false + } + + if token[4] != "master" { + return false + } + + return true +} + +// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 +// terminal. +func IsCygwinTerminal(fd uintptr) bool { + if procGetFileInformationByHandleEx == nil { + return false + } + + // Cygwin/msys's pty is a pipe. + ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0) + if ft != fileTypePipe || e != 0 { + return false + } + + var buf [2 + syscall.MAX_PATH]uint16 + r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), + 4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)), + uintptr(len(buf)*2), 0, 0) + if r == 0 || e != 0 { + return false + } + + l := *(*uint32)(unsafe.Pointer(&buf)) + return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2]))) +} diff --git a/vendor/github.com/pborman/uuid/.travis.yml b/vendor/github.com/pborman/uuid/.travis.yml index a6a98db8a3f..d8156a60ba9 100644 --- a/vendor/github.com/pborman/uuid/.travis.yml +++ b/vendor/github.com/pborman/uuid/.travis.yml @@ -3,7 +3,6 @@ language: go go: - 1.4.3 - 1.5.3 - - release - tip script: diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md index f023d47ca80..b0396b2747c 100644 --- a/vendor/github.com/pborman/uuid/README.md +++ b/vendor/github.com/pborman/uuid/README.md @@ -1,7 +1,7 @@ This project was automatically exported from code.google.com/p/go-uuid # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) -The uuid package generates and inspects UUIDs based on [RFC 412](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. +The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. ###### Install `go get github.com/pborman/uuid` diff --git a/vendor/github.com/pborman/uuid/dce.go b/vendor/github.com/pborman/uuid/dce.go old mode 100755 new mode 100644 diff --git a/vendor/github.com/pborman/uuid/doc.go b/vendor/github.com/pborman/uuid/doc.go old mode 100755 new mode 100644 diff --git a/vendor/github.com/pborman/uuid/json.go b/vendor/github.com/pborman/uuid/json.go deleted file mode 100644 index 9dda1dfba97..00000000000 --- a/vendor/github.com/pborman/uuid/json.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import "errors" - -func (u UUID) MarshalJSON() ([]byte, error) { - if len(u) != 16 { - return []byte(`""`), nil - } - var js [38]byte - js[0] = '"' - encodeHex(js[1:], u) - js[37] = '"' - return js[:], nil -} - -func (u *UUID) UnmarshalJSON(data []byte) error { - if string(data) == `""` { - return nil - } - if data[0] != '"' { - return errors.New("invalid UUID format") - } - data = data[1 : len(data)-1] - uu := Parse(string(data)) - if uu == nil { - return errors.New("invalid UUID format") - } - *u = uu - return nil -} diff --git a/vendor/github.com/pborman/uuid/marshal.go b/vendor/github.com/pborman/uuid/marshal.go new file mode 100644 index 00000000000..6621dd54beb --- /dev/null +++ b/vendor/github.com/pborman/uuid/marshal.go @@ -0,0 +1,83 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "errors" + "fmt" +) + +// MarshalText implements encoding.TextMarshaler. +func (u UUID) MarshalText() ([]byte, error) { + if len(u) != 16 { + return nil, nil + } + var js [36]byte + encodeHex(js[:], u) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (u *UUID) UnmarshalText(data []byte) error { + if len(data) == 0 { + return nil + } + id := Parse(string(data)) + if id == nil { + return errors.New("invalid UUID") + } + *u = id + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (u UUID) MarshalBinary() ([]byte, error) { + return u[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (u *UUID) UnmarshalBinary(data []byte) error { + if len(data) == 0 { + return nil + } + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + var id [16]byte + copy(id[:], data) + *u = id[:] + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (u Array) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], u[:]) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (u *Array) UnmarshalText(data []byte) error { + id := Parse(string(data)) + if id == nil { + return errors.New("invalid UUID") + } + *u = id.Array() + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (u Array) MarshalBinary() ([]byte, error) { + return u[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (u *Array) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(u[:], data) + return nil +} diff --git a/vendor/github.com/pborman/uuid/node.go b/vendor/github.com/pborman/uuid/node.go old mode 100755 new mode 100644 diff --git a/vendor/github.com/pborman/uuid/time.go b/vendor/github.com/pborman/uuid/time.go old mode 100755 new mode 100644 diff --git a/vendor/github.com/pborman/uuid/uuid.go b/vendor/github.com/pborman/uuid/uuid.go index 82c9e7ee7be..7c643cf0a38 100644 --- a/vendor/github.com/pborman/uuid/uuid.go +++ b/vendor/github.com/pborman/uuid/uuid.go @@ -186,7 +186,7 @@ func (v Variant) String() string { return fmt.Sprintf("BadVariant%d", int(v)) } -// SetRand sets the random number generator to r, which implents io.Reader. +// SetRand sets the random number generator to r, which implements io.Reader. // If r.Read returns an error when the package requests random data then // a panic will be issued. // diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE similarity index 100% rename from vendor/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/LICENSE rename to vendor/github.com/pmezard/go-difflib/LICENSE diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go similarity index 95% rename from vendor/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib/difflib.go rename to vendor/github.com/pmezard/go-difflib/difflib/difflib.go index 64cc40fe1da..003e99fadb4 100644 --- a/vendor/github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib/difflib.go +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -559,10 +559,14 @@ type UnifiedDiff struct { func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() - w := func(format string, args ...interface{}) error { + wf := func(format string, args ...interface{}) error { _, err := buf.WriteString(fmt.Sprintf(format, args...)) return err } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } if len(diff.Eol) == 0 { diff.Eol = "\n" @@ -581,26 +585,28 @@ func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } - err := w("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) - if err != nil { - return err - } - err = w("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) - if err != nil { - return err + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } } } first, last := g[0], g[len(g)-1] range1 := formatRangeUnified(first.I1, last.I2) range2 := formatRangeUnified(first.J1, last.J2) - if err := w("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { return err } for _, c := range g { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 if c.Tag == 'e' { for _, line := range diff.A[i1:i2] { - if err := w(" " + line); err != nil { + if err := ws(" " + line); err != nil { return err } } @@ -608,14 +614,14 @@ func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { } if c.Tag == 'r' || c.Tag == 'd' { for _, line := range diff.A[i1:i2] { - if err := w("-" + line); err != nil { + if err := ws("-" + line); err != nil { return err } } } if c.Tag == 'r' || c.Tag == 'i' { for _, line := range diff.B[j1:j2] { - if err := w("+" + line); err != nil { + if err := ws("+" + line); err != nil { return err } } @@ -669,12 +675,18 @@ func WriteContextDiff(writer io.Writer, diff ContextDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() var diffErr error - w := func(format string, args ...interface{}) { + wf := func(format string, args ...interface{}) { _, err := buf.WriteString(fmt.Sprintf(format, args...)) if diffErr == nil && err != nil { diffErr = err } } + ws := func(s string) { + _, err := buf.WriteString(s) + if diffErr == nil && err != nil { + diffErr = err + } + } if len(diff.Eol) == 0 { diff.Eol = "\n" @@ -700,15 +712,17 @@ func WriteContextDiff(writer io.Writer, diff ContextDiff) error { if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } - w("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) - w("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + if diff.FromFile != "" || diff.ToFile != "" { + wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } } first, last := g[0], g[len(g)-1] - w("***************" + diff.Eol) + ws("***************" + diff.Eol) range1 := formatRangeContext(first.I1, last.I2) - w("*** %s ****%s", range1, diff.Eol) + wf("*** %s ****%s", range1, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'd' { for _, cc := range g { @@ -716,7 +730,7 @@ func WriteContextDiff(writer io.Writer, diff ContextDiff) error { continue } for _, line := range diff.A[cc.I1:cc.I2] { - w(prefix[cc.Tag] + line) + ws(prefix[cc.Tag] + line) } } break @@ -724,7 +738,7 @@ func WriteContextDiff(writer io.Writer, diff ContextDiff) error { } range2 := formatRangeContext(first.J1, last.J2) - w("--- %s ----%s", range2, diff.Eol) + wf("--- %s ----%s", range2, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'i' { for _, cc := range g { @@ -732,7 +746,7 @@ func WriteContextDiff(writer io.Writer, diff ContextDiff) error { continue } for _, line := range diff.B[cc.J1:cc.J2] { - w(prefix[cc.Tag] + line) + ws(prefix[cc.Tag] + line) } } break diff --git a/vendor/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go b/vendor/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go deleted file mode 100644 index dddaf4b1263..00000000000 --- a/vendor/github.com/rcrowley/go-metrics/cmd/metrics-bench/metrics-bench.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "fmt" - "github.com/rcrowley/go-metrics" - "time" -) - -func main() { - r := metrics.NewRegistry() - for i := 0; i < 10000; i++ { - r.Register(fmt.Sprintf("counter-%d", i), metrics.NewCounter()) - r.Register(fmt.Sprintf("gauge-%d", i), metrics.NewGauge()) - r.Register(fmt.Sprintf("gaugefloat64-%d", i), metrics.NewGaugeFloat64()) - r.Register(fmt.Sprintf("histogram-uniform-%d", i), metrics.NewHistogram(metrics.NewUniformSample(1028))) - r.Register(fmt.Sprintf("histogram-exp-%d", i), metrics.NewHistogram(metrics.NewExpDecaySample(1028, 0.015))) - r.Register(fmt.Sprintf("meter-%d", i), metrics.NewMeter()) - } - time.Sleep(600e9) -} diff --git a/vendor/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go b/vendor/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go deleted file mode 100644 index 66f42c0468f..00000000000 --- a/vendor/github.com/rcrowley/go-metrics/cmd/metrics-example/metrics-example.go +++ /dev/null @@ -1,154 +0,0 @@ -package main - -import ( - "errors" - "github.com/rcrowley/go-metrics" - // "github.com/rcrowley/go-metrics/stathat" - "log" - "math/rand" - "os" - // "syslog" - "time" -) - -const fanout = 10 - -func main() { - - r := metrics.NewRegistry() - - c := metrics.NewCounter() - r.Register("foo", c) - for i := 0; i < fanout; i++ { - go func() { - for { - c.Dec(19) - time.Sleep(300e6) - } - }() - go func() { - for { - c.Inc(47) - time.Sleep(400e6) - } - }() - } - - g := metrics.NewGauge() - r.Register("bar", g) - for i := 0; i < fanout; i++ { - go func() { - for { - g.Update(19) - time.Sleep(300e6) - } - }() - go func() { - for { - g.Update(47) - time.Sleep(400e6) - } - }() - } - - gf := metrics.NewGaugeFloat64() - r.Register("barfloat64", gf) - for i := 0; i < fanout; i++ { - go func() { - for { - g.Update(19.0) - time.Sleep(300e6) - } - }() - go func() { - for { - g.Update(47.0) - time.Sleep(400e6) - } - }() - } - - hc := metrics.NewHealthcheck(func(h metrics.Healthcheck) { - if 0 < rand.Intn(2) { - h.Healthy() - } else { - h.Unhealthy(errors.New("baz")) - } - }) - r.Register("baz", hc) - - s := metrics.NewExpDecaySample(1028, 0.015) - //s := metrics.NewUniformSample(1028) - h := metrics.NewHistogram(s) - r.Register("bang", h) - for i := 0; i < fanout; i++ { - go func() { - for { - h.Update(19) - time.Sleep(300e6) - } - }() - go func() { - for { - h.Update(47) - time.Sleep(400e6) - } - }() - } - - m := metrics.NewMeter() - r.Register("quux", m) - for i := 0; i < fanout; i++ { - go func() { - for { - m.Mark(19) - time.Sleep(300e6) - } - }() - go func() { - for { - m.Mark(47) - time.Sleep(400e6) - } - }() - } - - t := metrics.NewTimer() - r.Register("hooah", t) - for i := 0; i < fanout; i++ { - go func() { - for { - t.Time(func() { time.Sleep(300e6) }) - } - }() - go func() { - for { - t.Time(func() { time.Sleep(400e6) }) - } - }() - } - - metrics.RegisterDebugGCStats(r) - go metrics.CaptureDebugGCStats(r, 5e9) - - metrics.RegisterRuntimeMemStats(r) - go metrics.CaptureRuntimeMemStats(r, 5e9) - - metrics.Log(r, 60e9, log.New(os.Stderr, "metrics: ", log.Lmicroseconds)) - - /* - w, err := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics") - if nil != err { log.Fatalln(err) } - metrics.Syslog(r, 60e9, w) - */ - - /* - addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") - metrics.Graphite(r, 10e9, "metrics", addr) - */ - - /* - stathat.Stathat(r, 10e9, "example@example.com") - */ - -} diff --git a/vendor/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go b/vendor/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go deleted file mode 100644 index dc175b778e8..00000000000 --- a/vendor/github.com/rcrowley/go-metrics/cmd/never-read/never-read.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "log" - "net" -) - -func main() { - addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") - l, err := net.ListenTCP("tcp", addr) - if nil != err { - log.Fatalln(err) - } - log.Println("listening", l.Addr()) - for { - c, err := l.AcceptTCP() - if nil != err { - log.Fatalln(err) - } - log.Println("accepted", c.RemoteAddr()) - } -} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge.go b/vendor/github.com/rcrowley/go-metrics/gauge.go index d618c455335..cb57a93889f 100644 --- a/vendor/github.com/rcrowley/go-metrics/gauge.go +++ b/vendor/github.com/rcrowley/go-metrics/gauge.go @@ -44,7 +44,6 @@ func NewFunctionalGauge(f func() int64) Gauge { return &FunctionalGauge{value: f} } - // NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { c := NewFunctionalGauge(f) @@ -101,6 +100,7 @@ func (g *StandardGauge) Update(v int64) { func (g *StandardGauge) Value() int64 { return atomic.LoadInt64(&g.value) } + // FunctionalGauge returns value from given function type FunctionalGauge struct { value func() int64 @@ -117,4 +117,4 @@ func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } // Update panics. func (FunctionalGauge) Update(int64) { panic("Update called on a FunctionalGauge") -} \ No newline at end of file +} diff --git a/vendor/github.com/rcrowley/go-metrics/librato/client.go b/vendor/github.com/rcrowley/go-metrics/librato/client.go deleted file mode 100644 index 8c0c850e386..00000000000 --- a/vendor/github.com/rcrowley/go-metrics/librato/client.go +++ /dev/null @@ -1,102 +0,0 @@ -package librato - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" -) - -const Operations = "operations" -const OperationsShort = "ops" - -type LibratoClient struct { - Email, Token string -} - -// property strings -const ( - // display attributes - Color = "color" - DisplayMax = "display_max" - DisplayMin = "display_min" - DisplayUnitsLong = "display_units_long" - DisplayUnitsShort = "display_units_short" - DisplayStacked = "display_stacked" - DisplayTransform = "display_transform" - // special gauge display attributes - SummarizeFunction = "summarize_function" - Aggregate = "aggregate" - - // metric keys - Name = "name" - Period = "period" - Description = "description" - DisplayName = "display_name" - Attributes = "attributes" - - // measurement keys - MeasureTime = "measure_time" - Source = "source" - Value = "value" - - // special gauge keys - Count = "count" - Sum = "sum" - Max = "max" - Min = "min" - SumSquares = "sum_squares" - - // batch keys - Counters = "counters" - Gauges = "gauges" - - MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics" -) - -type Measurement map[string]interface{} -type Metric map[string]interface{} - -type Batch struct { - Gauges []Measurement `json:"gauges,omitempty"` - Counters []Measurement `json:"counters,omitempty"` - MeasureTime int64 `json:"measure_time"` - Source string `json:"source"` -} - -func (self *LibratoClient) PostMetrics(batch Batch) (err error) { - var ( - js []byte - req *http.Request - resp *http.Response - ) - - if len(batch.Counters) == 0 && len(batch.Gauges) == 0 { - return nil - } - - if js, err = json.Marshal(batch); err != nil { - return - } - - if req, err = http.NewRequest("POST", MetricsPostUrl, bytes.NewBuffer(js)); err != nil { - return - } - - req.Header.Set("Content-Type", "application/json") - req.SetBasicAuth(self.Email, self.Token) - - if resp, err = http.DefaultClient.Do(req); err != nil { - return - } - - if resp.StatusCode != http.StatusOK { - var body []byte - if body, err = ioutil.ReadAll(resp.Body); err != nil { - body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err)) - } - err = fmt.Errorf("Unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body)) - } - return -} diff --git a/vendor/github.com/rcrowley/go-metrics/librato/librato.go b/vendor/github.com/rcrowley/go-metrics/librato/librato.go deleted file mode 100644 index d7c0574684c..00000000000 --- a/vendor/github.com/rcrowley/go-metrics/librato/librato.go +++ /dev/null @@ -1,235 +0,0 @@ -package librato - -import ( - "fmt" - "log" - "math" - "regexp" - "time" - - "github.com/rcrowley/go-metrics" -) - -// a regexp for extracting the unit from time.Duration.String -var unitRegexp = regexp.MustCompile("[^\\d]+$") - -// a helper that turns a time.Duration into librato display attributes for timer metrics -func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) { - attrs = make(map[string]interface{}) - attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d)) - attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String()))) - return -} - -type Reporter struct { - Email, Token string - Namespace string - Source string - Interval time.Duration - Registry metrics.Registry - Percentiles []float64 // percentiles to report on histogram metrics - TimerAttributes map[string]interface{} // units in which timers will be displayed - intervalSec int64 -} - -func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter { - return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)} -} - -func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) { - NewReporter(r, d, e, t, s, p, u).Run() -} - -func (self *Reporter) Run() { - log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015") - ticker := time.Tick(self.Interval) - metricsApi := &LibratoClient{self.Email, self.Token} - for now := range ticker { - var metrics Batch - var err error - if metrics, err = self.BuildRequest(now, self.Registry); err != nil { - log.Printf("ERROR constructing librato request body %s", err) - continue - } - if err := metricsApi.PostMetrics(metrics); err != nil { - log.Printf("ERROR sending metrics to librato %s", err) - continue - } - } -} - -// calculate sum of squares from data provided by metrics.Histogram -// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods -func sumSquares(s metrics.Sample) float64 { - count := float64(s.Count()) - sumSquared := math.Pow(count*s.Mean(), 2) - sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count - if math.IsNaN(sumSquares) { - return 0.0 - } - return sumSquares -} -func sumSquaresTimer(t metrics.Timer) float64 { - count := float64(t.Count()) - sumSquared := math.Pow(count*t.Mean(), 2) - sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count - if math.IsNaN(sumSquares) { - return 0.0 - } - return sumSquares -} - -func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) { - snapshot = Batch{ - // coerce timestamps to a stepping fn so that they line up in Librato graphs - MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec, - Source: self.Source, - } - snapshot.Gauges = make([]Measurement, 0) - snapshot.Counters = make([]Measurement, 0) - histogramGaugeCount := 1 + len(self.Percentiles) - r.Each(func(name string, metric interface{}) { - if self.Namespace != "" { - name = fmt.Sprintf("%s.%s", self.Namespace, name) - } - measurement := Measurement{} - measurement[Period] = self.Interval.Seconds() - switch m := metric.(type) { - case metrics.Counter: - if m.Count() > 0 { - measurement[Name] = fmt.Sprintf("%s.%s", name, "count") - measurement[Value] = float64(m.Count()) - measurement[Attributes] = map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - } - snapshot.Counters = append(snapshot.Counters, measurement) - } - case metrics.Gauge: - measurement[Name] = name - measurement[Value] = float64(m.Value()) - snapshot.Gauges = append(snapshot.Gauges, measurement) - case metrics.GaugeFloat64: - measurement[Name] = name - measurement[Value] = float64(m.Value()) - snapshot.Gauges = append(snapshot.Gauges, measurement) - case metrics.Histogram: - if m.Count() > 0 { - gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount) - s := m.Sample() - measurement[Name] = fmt.Sprintf("%s.%s", name, "hist") - measurement[Count] = uint64(s.Count()) - measurement[Max] = float64(s.Max()) - measurement[Min] = float64(s.Min()) - measurement[Sum] = float64(s.Sum()) - measurement[SumSquares] = sumSquares(s) - gauges[0] = measurement - for i, p := range self.Percentiles { - gauges[i+1] = Measurement{ - Name: fmt.Sprintf("%s.%.2f", measurement[Name], p), - Value: s.Percentile(p), - Period: measurement[Period], - } - } - snapshot.Gauges = append(snapshot.Gauges, gauges...) - } - case metrics.Meter: - measurement[Name] = name - measurement[Value] = float64(m.Count()) - snapshot.Counters = append(snapshot.Counters, measurement) - snapshot.Gauges = append(snapshot.Gauges, - Measurement{ - Name: fmt.Sprintf("%s.%s", name, "1min"), - Value: m.Rate1(), - Period: int64(self.Interval.Seconds()), - Attributes: map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - }, - }, - Measurement{ - Name: fmt.Sprintf("%s.%s", name, "5min"), - Value: m.Rate5(), - Period: int64(self.Interval.Seconds()), - Attributes: map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - }, - }, - Measurement{ - Name: fmt.Sprintf("%s.%s", name, "15min"), - Value: m.Rate15(), - Period: int64(self.Interval.Seconds()), - Attributes: map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - }, - }, - ) - case metrics.Timer: - measurement[Name] = name - measurement[Value] = float64(m.Count()) - snapshot.Counters = append(snapshot.Counters, measurement) - if m.Count() > 0 { - libratoName := fmt.Sprintf("%s.%s", name, "timer.mean") - gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount) - gauges[0] = Measurement{ - Name: libratoName, - Count: uint64(m.Count()), - Sum: m.Mean() * float64(m.Count()), - Max: float64(m.Max()), - Min: float64(m.Min()), - SumSquares: sumSquaresTimer(m), - Period: int64(self.Interval.Seconds()), - Attributes: self.TimerAttributes, - } - for i, p := range self.Percentiles { - gauges[i+1] = Measurement{ - Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100), - Value: m.Percentile(p), - Period: int64(self.Interval.Seconds()), - Attributes: self.TimerAttributes, - } - } - snapshot.Gauges = append(snapshot.Gauges, gauges...) - snapshot.Gauges = append(snapshot.Gauges, - Measurement{ - Name: fmt.Sprintf("%s.%s", name, "rate.1min"), - Value: m.Rate1(), - Period: int64(self.Interval.Seconds()), - Attributes: map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - }, - }, - Measurement{ - Name: fmt.Sprintf("%s.%s", name, "rate.5min"), - Value: m.Rate5(), - Period: int64(self.Interval.Seconds()), - Attributes: map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - }, - }, - Measurement{ - Name: fmt.Sprintf("%s.%s", name, "rate.15min"), - Value: m.Rate15(), - Period: int64(self.Interval.Seconds()), - Attributes: map[string]interface{}{ - DisplayUnitsLong: Operations, - DisplayUnitsShort: OperationsShort, - DisplayMin: "0", - }, - }, - ) - } - } - }) - return -} diff --git a/vendor/github.com/rcrowley/go-metrics/registry.go b/vendor/github.com/rcrowley/go-metrics/registry.go index 9086dcbdd14..2bb7a1e7d0f 100644 --- a/vendor/github.com/rcrowley/go-metrics/registry.go +++ b/vendor/github.com/rcrowley/go-metrics/registry.go @@ -167,9 +167,9 @@ func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { // Call the given function for each registered metric. func (r *PrefixedRegistry) Each(fn func(string, interface{})) { - wrappedFn := func (prefix string) func(string, interface{}) { + wrappedFn := func(prefix string) func(string, interface{}) { return func(name string, iface interface{}) { - if strings.HasPrefix(name,prefix) { + if strings.HasPrefix(name, prefix) { fn(name, iface) } else { return @@ -184,7 +184,7 @@ func (r *PrefixedRegistry) Each(fn func(string, interface{})) { func findPrefix(registry Registry, prefix string) (Registry, string) { switch r := registry.(type) { case *PrefixedRegistry: - return findPrefix(r.underlying, r.prefix + prefix) + return findPrefix(r.underlying, r.prefix+prefix) case *StandardRegistry: return r, prefix } diff --git a/vendor/github.com/rcrowley/go-metrics/sample.go b/vendor/github.com/rcrowley/go-metrics/sample.go index 5f6a37788ed..fecee5ef68b 100644 --- a/vendor/github.com/rcrowley/go-metrics/sample.go +++ b/vendor/github.com/rcrowley/go-metrics/sample.go @@ -33,7 +33,7 @@ type Sample interface { // priority reservoir. See Cormode et al's "Forward Decay: A Practical Time // Decay Model for Streaming Systems". // -// +// type ExpDecaySample struct { alpha float64 count int64 @@ -302,6 +302,13 @@ type SampleSnapshot struct { values []int64 } +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + // Clear panics. func (*SampleSnapshot) Clear() { panic("Clear called on a SampleSnapshot") diff --git a/vendor/github.com/rcrowley/go-metrics/stathat/stathat.go b/vendor/github.com/rcrowley/go-metrics/stathat/stathat.go deleted file mode 100644 index 0afcb484821..00000000000 --- a/vendor/github.com/rcrowley/go-metrics/stathat/stathat.go +++ /dev/null @@ -1,69 +0,0 @@ -// Metrics output to StatHat. -package stathat - -import ( - "github.com/rcrowley/go-metrics" - "github.com/stathat/go" - "log" - "time" -) - -func Stathat(r metrics.Registry, d time.Duration, userkey string) { - for { - if err := sh(r, userkey); nil != err { - log.Println(err) - } - time.Sleep(d) - } -} - -func sh(r metrics.Registry, userkey string) error { - r.Each(func(name string, i interface{}) { - switch metric := i.(type) { - case metrics.Counter: - stathat.PostEZCount(name, userkey, int(metric.Count())) - case metrics.Gauge: - stathat.PostEZValue(name, userkey, float64(metric.Value())) - case metrics.GaugeFloat64: - stathat.PostEZValue(name, userkey, float64(metric.Value())) - case metrics.Histogram: - h := metric.Snapshot() - ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) - stathat.PostEZCount(name+".count", userkey, int(h.Count())) - stathat.PostEZValue(name+".min", userkey, float64(h.Min())) - stathat.PostEZValue(name+".max", userkey, float64(h.Max())) - stathat.PostEZValue(name+".mean", userkey, float64(h.Mean())) - stathat.PostEZValue(name+".std-dev", userkey, float64(h.StdDev())) - stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0])) - stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1])) - stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2])) - stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3])) - stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4])) - case metrics.Meter: - m := metric.Snapshot() - stathat.PostEZCount(name+".count", userkey, int(m.Count())) - stathat.PostEZValue(name+".one-minute", userkey, float64(m.Rate1())) - stathat.PostEZValue(name+".five-minute", userkey, float64(m.Rate5())) - stathat.PostEZValue(name+".fifteen-minute", userkey, float64(m.Rate15())) - stathat.PostEZValue(name+".mean", userkey, float64(m.RateMean())) - case metrics.Timer: - t := metric.Snapshot() - ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) - stathat.PostEZCount(name+".count", userkey, int(t.Count())) - stathat.PostEZValue(name+".min", userkey, float64(t.Min())) - stathat.PostEZValue(name+".max", userkey, float64(t.Max())) - stathat.PostEZValue(name+".mean", userkey, float64(t.Mean())) - stathat.PostEZValue(name+".std-dev", userkey, float64(t.StdDev())) - stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0])) - stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1])) - stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2])) - stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3])) - stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4])) - stathat.PostEZValue(name+".one-minute", userkey, float64(t.Rate1())) - stathat.PostEZValue(name+".five-minute", userkey, float64(t.Rate5())) - stathat.PostEZValue(name+".fifteen-minute", userkey, float64(t.Rate15())) - stathat.PostEZValue(name+".mean-rate", userkey, float64(t.RateMean())) - } - }) - return nil -} diff --git a/vendor/github.com/rjeczalik/notify/.gitignore b/vendor/github.com/rjeczalik/notify/.gitignore index 86d4fa8b191..32c6eb987a6 100644 --- a/vendor/github.com/rjeczalik/notify/.gitignore +++ b/vendor/github.com/rjeczalik/notify/.gitignore @@ -6,7 +6,8 @@ .LSOverride # Icon must end with two \r -Icon +Icon + # Thumbnails ._* @@ -86,3 +87,6 @@ Session.vim .netrwhist *~ +### JetBrains files ### +.idea/ +*.iml \ No newline at end of file diff --git a/vendor/github.com/rjeczalik/notify/.travis.yml b/vendor/github.com/rjeczalik/notify/.travis.yml index 4f1f5f25e49..0f38a35359a 100644 --- a/vendor/github.com/rjeczalik/notify/.travis.yml +++ b/vendor/github.com/rjeczalik/notify/.travis.yml @@ -1,8 +1,7 @@ language: go go: - - 1.4.3 - - 1.6 + - 1.7.5 os: - linux @@ -11,7 +10,7 @@ os: matrix: include: - os: osx - go: 1.6 + go: 1.7.5 env: - GOFLAGS="-tags kqueue" @@ -21,10 +20,9 @@ env: - PATH=$HOME/bin:$PATH install: - - go get golang.org/x/tools/cmd/vet - go get -t -v ./... script: - - go tool vet -all . + - "(go version | grep -q 1.4) || go tool vet -all ." - go install $GOFLAGS ./... - go test -v -race $GOFLAGS ./... diff --git a/vendor/github.com/rjeczalik/notify/appveyor.yml b/vendor/github.com/rjeczalik/notify/appveyor.yml index 16d09ac3b57..8e762d05cb8 100644 --- a/vendor/github.com/rjeczalik/notify/appveyor.yml +++ b/vendor/github.com/rjeczalik/notify/appveyor.yml @@ -11,7 +11,6 @@ environment: install: - go version - - go get golang.org/x/tools/cmd/vet - go get -v -t ./... build_script: diff --git a/vendor/github.com/rjeczalik/notify/event_fen.go b/vendor/github.com/rjeczalik/notify/event_fen.go index a3079385d7d..767f04fa876 100644 --- a/vendor/github.com/rjeczalik/notify/event_fen.go +++ b/vendor/github.com/rjeczalik/notify/event_fen.go @@ -20,16 +20,27 @@ const ( ) const ( - FileAccess = fileAccess - FileModified = fileModified - FileAttrib = fileAttrib - FileDelete = fileDelete - FileRenameTo = fileRenameTo + // FileAccess is an event reported when monitored file/directory was accessed. + FileAccess = fileAccess + // FileModified is an event reported when monitored file/directory was modified. + FileModified = fileModified + // FileAttrib is an event reported when monitored file/directory's ATTRIB + // was changed. + FileAttrib = fileAttrib + // FileDelete is an event reported when monitored file/directory was deleted. + FileDelete = fileDelete + // FileRenameTo to is an event reported when monitored file/directory was renamed. + FileRenameTo = fileRenameTo + // FileRenameFrom is an event reported when monitored file/directory was renamed. FileRenameFrom = fileRenameFrom - FileTrunc = fileTrunc - FileNoFollow = fileNoFollow - Unmounted = unmounted - MountedOver = mountedOver + // FileTrunc is an event reported when monitored file/directory was truncated. + FileTrunc = fileTrunc + // FileNoFollow is an flag to indicate not to follow symbolic links. + FileNoFollow = fileNoFollow + // Unmounted is an event reported when monitored filesystem was unmounted. + Unmounted = unmounted + // MountedOver is an event reported when monitored file/directory was mounted on. + MountedOver = mountedOver ) var osestr = map[Event]string{ diff --git a/vendor/github.com/rjeczalik/notify/event_kqueue.go b/vendor/github.com/rjeczalik/notify/event_kqueue.go index 82e2d8ccae8..422ac87f66f 100644 --- a/vendor/github.com/rjeczalik/notify/event_kqueue.go +++ b/vendor/github.com/rjeczalik/notify/event_kqueue.go @@ -26,7 +26,7 @@ const ( ) const ( - // NoteDelete is an even reported when the unlink() system call was called + // NoteDelete is an event reported when the unlink() system call was called // on the file referenced by the descriptor. NoteDelete = Event(syscall.NOTE_DELETE) // NoteWrite is an event reported when a write occurred on the file diff --git a/vendor/github.com/rjeczalik/notify/node.go b/vendor/github.com/rjeczalik/notify/node.go index 4302071bb28..29c1bb20af4 100644 --- a/vendor/github.com/rjeczalik/notify/node.go +++ b/vendor/github.com/rjeczalik/notify/node.go @@ -6,6 +6,7 @@ package notify import ( "errors" + "fmt" "io/ioutil" "os" "path/filepath" @@ -70,7 +71,7 @@ Traverse: case errSkip: continue Traverse default: - return err + return fmt.Errorf("error while traversing %q: %v", nd.Name, err) } // TODO(rjeczalik): tolerate open failures - add failed names to // AddDirError and notify users which names are not added to the tree. diff --git a/vendor/github.com/rjeczalik/notify/notify.go b/vendor/github.com/rjeczalik/notify/notify.go index dbf1e7bc244..7d2eec3a247 100644 --- a/vendor/github.com/rjeczalik/notify/notify.go +++ b/vendor/github.com/rjeczalik/notify/notify.go @@ -4,7 +4,7 @@ // BUG(rjeczalik): Notify does not collect watchpoints, when underlying watches // were removed by their os-specific watcher implementations. Instead users are -// advised to listen on persistant paths to have guarantee they receive events +// advised to listen on persistent paths to have guarantee they receive events // for the whole lifetime of their applications (to discuss see #69). // BUG(ppknap): Linux (inotify) does not support watcher behavior masks like @@ -58,7 +58,7 @@ var defaultTree = newTree() // If a directory which path was used to create recursive watch under Windows // gets deleted, the OS will not report such event. It is advised to keep in // mind this limitation while setting recursive watchpoints for your application, -// e.g. use persistant paths like %userprofile% or watch additionally parent +// e.g. use persistent paths like %userprofile% or watch additionally parent // directory of a recursive watchpoint in order to receive delete events for it. func Watch(path string, c chan<- EventInfo, events ...Event) error { return defaultTree.Watch(path, c, events...) @@ -67,7 +67,7 @@ func Watch(path string, c chan<- EventInfo, events ...Event) error { // Stop removes all watchpoints registered for c. All underlying watches are // also removed, for which c was the last channel listening for events. // -// Stop does not close c. When Stop returns, it is guranteed that c will +// Stop does not close c. When Stop returns, it is guaranteed that c will // receive no more signals. func Stop(c chan<- EventInfo) { defaultTree.Stop(c) diff --git a/vendor/github.com/rjeczalik/notify/watcher_fen.go b/vendor/github.com/rjeczalik/notify/watcher_fen.go index 60e9a36da6f..dd069f2a26f 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fen.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fen.go @@ -45,7 +45,7 @@ type watched struct { // Stop implements trigger. func (f *fen) Stop() error { - return f.cf.port_alert(f.p) + return f.cf.portAlert(f.p) } // Close implements trigger. @@ -92,7 +92,7 @@ func (f *fen) Watched(n interface{}) (*watched, int64, error) { // init initializes FEN. func (f *fen) Init() (err error) { - f.p, err = f.cf.port_create() + f.p, err = f.cf.portCreate() return } @@ -106,12 +106,12 @@ func fi2fo(fi os.FileInfo, p string) FileObj { // Unwatch implements trigger. func (f *fen) Unwatch(w *watched) error { - return f.cf.port_dissociate(f.p, FileObj{Name: w.p}) + return f.cf.portDissociate(f.p, FileObj{Name: w.p}) } // Watch implements trigger. func (f *fen) Watch(fi os.FileInfo, w *watched, e int64) error { - return f.cf.port_associate(f.p, fi2fo(fi, w.p), int(e)) + return f.cf.portAssociate(f.p, fi2fo(fi, w.p), int(e)) } // Wait implements trigger. @@ -120,7 +120,7 @@ func (f *fen) Wait() (interface{}, error) { pe PortEvent err error ) - err = f.cf.port_get(f.p, &pe) + err = f.cf.portGet(f.p, &pe) return pe, err } @@ -130,16 +130,14 @@ func (f *fen) IsStop(n interface{}, err error) bool { } func init() { - encode = func(e Event) (o int64) { + encode = func(e Event, dir bool) (o int64) { // Create event is not supported by FEN. Instead FileModified event will // be registered. If this event will be reported on dir which is to be // monitored for Create, dir will be rescanned and Create events will // be generated and returned for new files. In case of files, // if not requested FileModified event is reported, it will be ignored. - if e&Create != 0 { - o = (o &^ int64(Create)) | int64(FileModified) - } - if e&Write != 0 { + o = int64(e &^ Create) + if (e&Create != 0 && dir) || e&Write != 0 { o = (o &^ int64(Write)) | int64(FileModified) } // Following events are 'exception events' and as such cannot be requested diff --git a/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go b/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go index 58ac8e8c679..8ec8ead3439 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go @@ -67,7 +67,7 @@ func unix2C(sec int64, nsec int64) (C.time_t, C.long) { return C.time_t(sec), C.long(nsec) } -func (c *cfen) port_associate(p int, fo FileObj, e int) (err error) { +func (c *cfen) portAssociate(p int, fo FileObj, e int) (err error) { cfo := C.newFo() cfo.fo_atime.tv_sec, cfo.fo_atime.tv_nsec = unix2C(fo.Atim.Unix()) cfo.fo_mtime.tv_sec, cfo.fo_mtime.tv_nsec = unix2C(fo.Mtim.Unix()) @@ -78,7 +78,7 @@ func (c *cfen) port_associate(p int, fo FileObj, e int) (err error) { return } -func (c *cfen) port_dissociate(port int, fo FileObj) (err error) { +func (c *cfen) portDissociate(port int, fo FileObj) (err error) { cfo, ok := c.p2fo[fo.Name] if !ok { return errNotWatched @@ -104,7 +104,7 @@ func cfo2fo(cfo *C.struct_file_obj) *FileObj { return &fo } -func (c *cfen) port_get(port int, pe *PortEvent) (err error) { +func (c *cfen) portGet(port int, pe *PortEvent) (err error) { cpe := C.newPe() if _, err = C.port_get(C.int(port), cpe, nil); err != nil { C.free(unsafe.Pointer(cpe)) @@ -118,12 +118,12 @@ func (c *cfen) port_get(port int, pe *PortEvent) (err error) { return } -func (c *cfen) port_create() (int, error) { +func (c *cfen) portCreate() (int, error) { p, err := C.port_create() return int(p), err } -func (c *cfen) port_alert(p int) (err error) { +func (c *cfen) portAlert(p int) (err error) { _, err = C.port_alert(C.int(p), alertSet, C.int(666), nil) return } diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go index 54334912ec4..9062c17c7f4 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go @@ -133,7 +133,7 @@ func (w *watch) Dispatch(ev []FSEvent) { ev[i].Flags, ev[i].Path, i, ev[i].ID, len(ev)) if ev[i].Flags&failure != 0 { // TODO(rjeczalik): missing error handling - panic("unhandled error: " + Event(ev[i].Flags).String()) + continue } if !strings.HasPrefix(ev[i].Path, w.path) { continue diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go index ee9631a61f7..5be64632e8a 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go +++ b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go @@ -144,7 +144,7 @@ type stream struct { } // NewStream creates a stream for given path, listening for file events and -// calling fn upon receving any. +// calling fn upon receiving any. func newStream(path string, fn streamFunc) *stream { return &stream{ path: path, diff --git a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go index d5f7788c4a5..6d500b700d7 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go +++ b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go @@ -157,14 +157,15 @@ func (k *kq) IsStop(n interface{}, err error) bool { } func init() { - encode = func(e Event) (o int64) { + encode = func(e Event, dir bool) (o int64) { // Create event is not supported by kqueue. Instead NoteWrite event will - // be registered. If this event will be reported on dir which is to be - // monitored for Create, dir will be rescanned and Create events will - // be generated and returned for new files. In case of files, - // if not requested NoteRename event is reported, it will be ignored. + // be registered for a directory. If this event will be reported on dir + // which is to be monitored for Create, dir will be rescanned + // and Create events will be generated and returned for new files. + // In case of files, if not requested NoteRename event is reported, + // it will be ignored. o = int64(e &^ Create) - if e&Write != 0 { + if (e&Create != 0 && dir) || e&Write != 0 { o = (o &^ int64(Write)) | int64(NoteWrite) } if e&Rename != 0 { diff --git a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go index e8359bba4f6..5923bfddae5 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go +++ b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go @@ -377,7 +377,7 @@ func (r *readdcw) loopevent(n uint32, overEx *overlappedEx) { var currOffset uint32 for { raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&overEx.parent.buffer[currOffset])) - name := syscall.UTF16ToString((*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))[:raw.FileNameLength>>1]) + name := syscall.UTF16ToString((*[syscall.MAX_LONG_PATH]uint16)(unsafe.Pointer(&raw.FileName))[:raw.FileNameLength>>1]) events = append(events, &event{ pathw: overEx.parent.pathw, filter: overEx.parent.filter, diff --git a/vendor/github.com/rjeczalik/notify/watcher_trigger.go b/vendor/github.com/rjeczalik/notify/watcher_trigger.go index f25a6fcbf4c..d079d59b0a1 100644 --- a/vendor/github.com/rjeczalik/notify/watcher_trigger.go +++ b/vendor/github.com/rjeczalik/notify/watcher_trigger.go @@ -58,7 +58,7 @@ type trigger interface { // encode Event to native representation. Implementation is to be provided by // platform specific implementation. -var encode func(Event) int64 +var encode func(Event, bool) int64 var ( // nat2not matches native events to notify's ones. To be initialized by @@ -145,13 +145,7 @@ func (t *trg) singlewatch(p string, e Event, direct mode, fi os.FileInfo) (err e w.eDir |= e w.eNonDir |= e } - var ee int64 - // Native Write event is added to wait for Create events (Write event on - // directory triggers it's rescan). - if e&Create != 0 && fi.IsDir() { - ee = int64(not2nat[Write]) - } - if err = t.t.Watch(fi, w, encode(w.eDir|w.eNonDir)|ee); err != nil { + if err = t.t.Watch(fi, w, encode(w.eDir|w.eNonDir, fi.IsDir())); err != nil { return } if !ok { @@ -290,7 +284,7 @@ func (t *trg) dir(w *watched, n interface{}, e, ge Event) (evn []event) { // However events for rename must be generated for all monitored files // inside of moved directory, because native impl does not report it independently // for each file descriptor being moved in result of move action on - // parent dirLiczba dostępnych dni urlopowych: 0ectory. + // parent directory. if (ge & (not2nat[Rename] | not2nat[Remove])) != 0 { // Write is reported also for Remove on directory. Because of that // we have to filter it out explicitly. @@ -399,7 +393,7 @@ func (t *trg) monitor() { } } -// process event returned by port_get call. +// process event returned by native call. func (t *trg) process(n interface{}) (evn []event) { t.Lock() w, ge, err := t.t.Watched(n) @@ -414,13 +408,13 @@ func (t *trg) process(n interface{}) (evn []event) { switch fi, err := os.Stat(w.p); { case err != nil: default: - if err = t.t.Watch(fi, w, (encode(w.eDir | w.eNonDir))); err != nil { + if err = t.t.Watch(fi, w, encode(w.eDir|w.eNonDir, fi.IsDir())); err != nil { dbgprintf("trg: %q is no longer watched: %q", w.p, err) t.t.Del(w) } } } - if e == Event(0) { + if e == Event(0) && (!w.fi.IsDir() || (ge&int64(not2nat[Write])) == 0) { t.Unlock() return } diff --git a/vendor/github.com/rjeczalik/notify/watchpoint_other.go b/vendor/github.com/rjeczalik/notify/watchpoint_other.go index 881631c99d4..9bb381db776 100644 --- a/vendor/github.com/rjeczalik/notify/watchpoint_other.go +++ b/vendor/github.com/rjeczalik/notify/watchpoint_other.go @@ -15,7 +15,7 @@ func eventmask(ei EventInfo, extra Event) Event { // matches reports a match only when: // // - for user events, when event is present in the given set -// - for internal events, when additionaly both event and set have omit bit set +// - for internal events, when additionally both event and set have omit bit set // // Internal events must not be sent to user channels and vice versa. func matches(set, event Event) bool { diff --git a/vendor/github.com/robertkrimen/otto/.gitignore b/vendor/github.com/robertkrimen/otto/.gitignore new file mode 100644 index 00000000000..8c2a16949e5 --- /dev/null +++ b/vendor/github.com/robertkrimen/otto/.gitignore @@ -0,0 +1,5 @@ +/.test +/otto/otto +/otto/otto-* +/test/test-*.js +/test/tester diff --git a/vendor/github.com/robertkrimen/otto/README.markdown b/vendor/github.com/robertkrimen/otto/README.markdown index 30f734ea3a4..a1ae7d1ae60 100644 --- a/vendor/github.com/robertkrimen/otto/README.markdown +++ b/vendor/github.com/robertkrimen/otto/README.markdown @@ -88,7 +88,7 @@ Set a Go function that returns something useful ```go vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { right, _ := call.Argument(0).ToInteger() - return, _ := vm.ToValue(2 + right) + result, _ := vm.ToValue(2 + right) return result }) ``` @@ -114,7 +114,7 @@ http://godoc.org/github.com/robertkrimen/otto/parser Parse and return an AST ```go -filenamee := "" // A filename is optional +filename := "" // A filename is optional src := ` // Sample xyzzy example (function(){ @@ -167,6 +167,7 @@ The following are some limitations with otto: * "use strict" will parse, but does nothing. * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. + * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. ### Regular Expression Incompatibility diff --git a/vendor/github.com/robertkrimen/otto/array_test.go b/vendor/github.com/robertkrimen/otto/array_test.go deleted file mode 100644 index f07fbcceefa..00000000000 --- a/vendor/github.com/robertkrimen/otto/array_test.go +++ /dev/null @@ -1,718 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestArray(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = [ undefined, "Nothing happens." ]; - abc.length; - `, 2) - - test(` - abc = ""+[0, 1, 2, 3]; - def = [].toString(); - ghi = [null, 4, "null"].toString(); - [ abc, def, ghi ]; - `, "0,1,2,3,,,4,null") - - test(`new Array(0).length`, 0) - - test(`new Array(11).length`, 11) - - test(`new Array(11, 1).length`, 2) - - test(` - abc = [0, 1, 2, 3]; - abc.xyzzy = "Nothing happens."; - delete abc[1]; - var xyzzy = delete abc.xyzzy; - [ abc, xyzzy, abc.xyzzy ]; - `, "0,,2,3,true,") - - test(` - var abc = [0, 1, 2, 3, 4]; - abc.length = 2; - abc; - `, "0,1") - - test(`raise: - [].length = 3.14159; - `, "RangeError") - - test(`raise: - new Array(3.14159); - `, "RangeError") - - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); - abc = [101]; - abc.hasOwnProperty("0") && abc[0] === 101; - `, true) - - test(` - abc = [,,undefined]; - [ abc.hasOwnProperty(0), abc.hasOwnProperty(1), abc.hasOwnProperty(2) ]; - `, "false,false,true") - - test(` - abc = Object.getOwnPropertyDescriptor(Array, "prototype"); - [ [ typeof Array.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") - }) -} - -func TestArray_toString(t *testing.T) { - tt(t, func() { - { - test(` - Array.prototype.toString = function() { - return "Nothing happens."; - } - abc = Array.prototype.toString(); - def = [].toString(); - ghi = [null, 4, "null"].toString(); - - [ abc, def, ghi ].join(","); - `, "Nothing happens.,Nothing happens.,Nothing happens.") - } - - { - test(` - Array.prototype.join = undefined - abc = Array.prototype.toString() - def = [].toString() - ghi = [null, 4, "null"].toString() - - abc + "," + def + "," + ghi; - `, "[object Array],[object Array],[object Array]") - } - }) -} - -func TestArray_toLocaleString(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - [ 3.14159, "abc", undefined, new Date(0) ].toLocaleString(); - `, "3.14159,abc,,1970-01-01 00:00:00") - - test(`raise: - [ { toLocaleString: undefined } ].toLocaleString(); - `, "TypeError") - }) -} - -func TestArray_concat(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0, 1, 2]; - def = [-1, -2, -3]; - ghi = abc.concat(def); - jkl = abc.concat(def, 3, 4, 5); - mno = def.concat(-4, -5, abc); - - [ ghi, jkl, mno ].join(";"); - `, "0,1,2,-1,-2,-3;0,1,2,-1,-2,-3,3,4,5;-1,-2,-3,-4,-5,0,1,2") - - test(` - var abc = [,1]; - var def = abc.concat([], [,]); - - def.getClass = Object.prototype.toString; - - [ def.getClass(), typeof def[0], def[1], typeof def[2], def.length ]; - `, "[object Array],undefined,1,undefined,3") - - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); - - var abc = Array.prototype.concat.call(101); - - var hasProperty = abc.hasOwnProperty("0"); - var instanceOfVerify = typeof abc[0] === "object"; - var verifyValue = false; - verifyValue = abc[0] == 101; - - var verifyEnumerable = false; - for (var property in abc) { - if (property === "0" && abc.hasOwnProperty("0")) { - verifyEnumerable = true; - } - } - - var verifyWritable = false; - abc[0] = 12; - verifyWritable = abc[0] === 12; - - var verifyConfigurable = false; - delete abc[0]; - verifyConfigurable = abc.hasOwnProperty("0"); - - [ hasProperty, instanceOfVerify, verifyValue, !verifyConfigurable, verifyEnumerable, verifyWritable ]; - `, "true,true,true,true,true,true") - }) -} - -func TestArray_splice(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0, 1, 2]; - def = abc.splice(1, 2, 3, 4, 5); - ghi = [].concat(abc); - jkl = ghi.splice(17, 21, 7, 8, 9); - [ abc, def, ghi, jkl ].join(";"); - `, "0,3,4,5;1,2;0,3,4,5,7,8,9;") - }) -} - -func TestArray_shift(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0, 1, 2]; - def = abc.shift(); - ghi = [].concat(abc); - jkl = abc.shift(); - mno = [].concat(abc); - pqr = abc.shift(); - stu = [].concat(abc); - vwx = abc.shift(); - - [ abc, def, ghi, jkl, mno, pqr, stu, vwx ].join(";"); - `, ";0;1,2;1;2;2;;") - }) -} - -func TestArray_push(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0]; - def = abc.push(1); - ghi = [].concat(abc); - jkl = abc.push(2,3,4); - - [ abc, def, ghi, jkl ].join(";"); - `, "0,1,2,3,4;2;0,1;5") - }) -} - -func TestArray_pop(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0,1]; - def = abc.pop(); - ghi = [].concat(abc); - jkl = abc.pop(); - mno = [].concat(abc); - pqr = abc.pop(); - - [ abc, def, ghi, jkl, mno, pqr ].join(";"); - `, ";1;0;0;;") - }) -} - -func TestArray_slice(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0,1,2,3]; - def = abc.slice(); - ghi = abc.slice(1); - jkl = abc.slice(3,-1); - mno = abc.slice(2,-1); - pqr = abc.slice(-1, -10); - - [ abc, def, ghi, jkl, mno, pqr ].join(";"); - `, "0,1,2,3;0,1,2,3;1,2,3;;2;") - - // Array.protoype.slice is generic - test(` - abc = { 0: 0, 1: 1, 2: 2, 3: 3 }; - abc.length = 4; - def = Array.prototype.slice.call(abc); - ghi = Array.prototype.slice.call(abc,1); - jkl = Array.prototype.slice.call(abc,3,-1); - mno = Array.prototype.slice.call(abc,2,-1); - pqr = Array.prototype.slice.call(abc,-1,-10); - - [ abc, def, ghi, jkl, pqr ].join(";"); - `, "[object Object];0,1,2,3;1,2,3;;") - }) -} - -func TestArray_sliceArguments(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - (function(){ - return Array.prototype.slice.call(arguments, 1) - })({}, 1, 2, 3); - `, "1,2,3") - }) -} - -func TestArray_unshift(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = []; - def = abc.unshift(0); - ghi = [].concat(abc); - jkl = abc.unshift(1,2,3,4); - - [ abc, def, ghi, jkl ].join(";"); - `, "1,2,3,4,0;1;0;5") - }) -} - -func TestArray_reverse(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0,1,2,3].reverse(); - def = [0,1,2].reverse(); - - [ abc, def ]; - `, "3,2,1,0,2,1,0") - }) -} - -func TestArray_sort(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [0,1,2,3].sort(); - def = [3,2,1,0].sort(); - ghi = [].sort(); - jkl = [0].sort(); - mno = [1,0].sort(); - pqr = [1,5,-10, 100, 8, 72, 401, 0.05].sort(); - stu = [1,5,-10, 100, 8, 72, 401, 0.05].sort(function(x, y){ - return x == y ? 0 : x < y ? -1 : 1 - }); - vwx = [1,2,3,1,2,3].sort(); - yza = [1,2,3,1,0,1,-1,0].sort(); - - [ abc, def, ghi, jkl, mno, pqr, stu, vwx, yza ].join(";"); - `, "0,1,2,3;0,1,2,3;;0;0,1;-10,0.05,1,100,401,5,72,8;-10,0.05,1,5,8,72,100,401;1,1,2,2,3,3;-1,0,0,1,1,1,2,3") - - test(`Array.prototype.sort.length`, 1) - }) -} - -func TestArray_isArray(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ Array.isArray.length, Array.isArray(), Array.isArray([]), Array.isArray({}) ]; - `, "1,false,true,false") - - test(`Array.isArray(Math)`, false) - }) -} - -func TestArray_indexOf(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`['a', 'b', 'c', 'b'].indexOf('b')`, 1) - - test(`['a', 'b', 'c', 'b'].indexOf('b', 2)`, 3) - - test(`['a', 'b', 'c', 'b'].indexOf('b', -2)`, 3) - - test(` - Object.prototype.indexOf = Array.prototype.indexOf; - var abc = {0: 'a', 1: 'b', 2: 'c', length: 3}; - abc.indexOf('c'); - `, 2) - - test(`[true].indexOf(true, "-Infinity")`, 0) - - test(` - var target = {}; - Math[3] = target; - Math.length = 5; - Array.prototype.indexOf.call(Math, target) === 3; - `, true) - - test(` - var _NaN = NaN; - var abc = new Array("NaN", undefined, 0, false, null, {toString:function(){return NaN}}, "false", _NaN, NaN); - abc.indexOf(NaN); - `, -1) - - test(` - var abc = {toString:function (){return 0}}; - var def = 1; - var ghi = -(4/3); - var jkl = new Array(false, undefined, null, "0", abc, -1.3333333333333, "string", -0, true, +0, def, 1, 0, false, ghi, -(4/3)); - [ jkl.indexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ]; - `, "14,7,7,10") - }) -} - -func TestArray_lastIndexOf(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`['a', 'b', 'c', 'b'].lastIndexOf('b')`, 3) - - test(`['a', 'b', 'c', 'b'].lastIndexOf('b', 2)`, 1) - - test(`['a', 'b', 'c', 'b'].lastIndexOf('b', -2)`, 1) - - test(` - Object.prototype.lastIndexOf = Array.prototype.lastIndexOf; - var abc = {0: 'a', 1: 'b', 2: 'c', 3: 'b', length: 4}; - abc.lastIndexOf('b'); - `, 3) - - test(` - var target = {}; - Math[3] = target; - Math.length = 5; - [ Array.prototype.lastIndexOf.call(Math, target) === 3 ]; - `, "true") - - test(` - var _NaN = NaN; - var abc = new Array("NaN", undefined, 0, false, null, {toString:function(){return NaN}}, "false", _NaN, NaN); - abc.lastIndexOf(NaN); - `, -1) - - test(` - var abc = {toString:function (){return 0}}; - var def = 1; - var ghi = -(4/3); - var jkl = new Array(false, undefined, null, "0", abc, -1.3333333333333, "string", -0, true, +0, def, 1, 0, false, ghi, -(4/3)); - [ jkl.lastIndexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ]; - `, "15,7,7,10") - }) -} - -func TestArray_every(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].every()`, "TypeError") - - test(`raise: [].every("abc")`, "TypeError") - - test(`[].every(function() { return false })`, true) - - test(`[1,2,3].every(function() { return false })`, false) - - test(`[1,2,3].every(function() { return true })`, true) - - test(`[1,2,3].every(function(_, index) { if (index === 1) return true })`, false) - - test(` - var abc = function(value, index, object) { - return ('[object Math]' !== Object.prototype.toString.call(object)); - }; - - Math.length = 1; - Math[0] = 1; - !Array.prototype.every.call(Math, abc); - `, true) - - test(` - var def = false; - - var abc = function(value, index, object) { - def = true; - return this === Math; - }; - - [11].every(abc, Math) && def; - `, true) - - test(` - var def = false; - - var abc = function(value, index, object) { - def = true; - return Math; - }; - - [11].every(abc) && def; - `, true) - }) -} - -func TestArray_some(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].some("abc")`, "TypeError") - - test(`[].some(function() { return true })`, false) - - test(`[1,2,3].some(function() { return false })`, false) - - test(`[1,2,3].some(function() { return true })`, true) - - test(`[1,2,3].some(function(_, index) { if (index === 1) return true })`, true) - - test(` - var abc = function(value, index, object) { - return ('[object Math]' !== Object.prototype.toString.call(object)); - }; - - Math.length = 1; - Math[0] = 1; - !Array.prototype.some.call(Math, abc); - `, true) - - test(` - var abc = function(value, index, object) { - return this === Math; - }; - - [11].some(abc, Math); - `, true) - - test(` - var abc = function(value, index, object) { - return Math; - }; - - [11].some(abc); - `, true) - }) -} - -func TestArray_forEach(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].forEach("abc")`, "TypeError") - - test(` - var abc = 0; - [].forEach(function(value) { - abc += value; - }); - abc; - `, 0) - - test(` - abc = 0; - var def = []; - [1,2,3].forEach(function(value, index) { - abc += value; - def.push(index); - }); - [ abc, def ]; - `, "6,0,1,2") - - test(` - var def = false; - var abc = function(value, index, object) { - def = ('[object Math]' === Object.prototype.toString.call(object)); - }; - - Math.length = 1; - Math[0] = 1; - Array.prototype.forEach.call(Math, abc); - def; - `, true) - - test(` - var def = false; - var abc = function(value, index, object) { - def = this === Math; - }; - - [11].forEach(abc, Math); - def; - `, true) - }) -} - -func TestArray_indexing(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = new Array(0, 1); - var def = abc.length; - abc[4294967296] = 10; // 2^32 => 0 - abc[4294967297] = 11; // 2^32+1 => 1 - [ def, abc.length, abc[0], abc[1], abc[4294967296] ]; - `, "2,2,0,1,10") - - test(` - abc = new Array(0, 1); - def = abc.length; - abc[4294967295] = 10; - var ghi = abc.length; - abc[4294967299] = 12; - var jkl = abc.length; - abc[4294967294] = 11; - [ def, ghi, jkl, abc.length, abc[4294967295], abc[4294967299] ]; - `, "2,2,2,4294967295,10,12") - }) -} - -func TestArray_map(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].map("abc")`, "TypeError") - - test(`[].map(function() { return 1 }).length`, 0) - - test(`[1,2,3].map(function(value) { return value * value })`, "1,4,9") - - test(`[1,2,3].map(function(value) { return 1 })`, "1,1,1") - - test(` - var abc = function(value, index, object) { - return ('[object Math]' === Object.prototype.toString.call(object)); - }; - - Math.length = 1; - Math[0] = 1; - Array.prototype.map.call(Math, abc)[0]; - `, true) - - test(` - var abc = function(value, index, object) { - return this === Math; - }; - - [11].map(abc, Math)[0]; - `, true) - }) -} - -func TestArray_filter(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].filter("abc")`, "TypeError") - - test(`[].filter(function() { return 1 }).length`, 0) - - test(`[1,2,3].filter(function() { return false }).length`, 0) - - test(`[1,2,3].filter(function() { return true })`, "1,2,3") - }) -} - -func TestArray_reduce(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].reduce("abc")`, "TypeError") - - test(`raise: [].reduce(function() {})`, "TypeError") - - test(`[].reduce(function() {}, 0)`, 0) - - test(`[].reduce(function() {}, undefined)`, "undefined") - - test(`['a','b','c'].reduce(function(result, value) { return result+', '+value })`, "a, b, c") - - test(`[1,2,3].reduce(function(result, value) { return result + value }, 4)`, 10) - - test(`[1,2,3].reduce(function(result, value) { return result + value })`, 6) - }) -} - -func TestArray_reduceRight(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: [].reduceRight("abc")`, "TypeError") - - test(`raise: [].reduceRight(function() {})`, "TypeError") - - test(`[].reduceRight(function() {}, 0)`, 0) - - test(`[].reduceRight(function() {}, undefined)`, "undefined") - - test(`['a','b','c'].reduceRight(function(result, value) { return result+', '+value })`, "c, b, a") - - test(`[1,2,3].reduceRight(function(result, value) { return result + value }, 4)`, 10) - - test(`[1,2,3].reduceRight(function(result, value) { return result + value })`, 6) - }) -} - -func TestArray_defineOwnProperty(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = []; - Object.defineProperty(abc, "length", { - writable: false - }); - abc.length; - `, 0) - - test(`raise: - var abc = []; - var exception; - Object.defineProperty(abc, "length", { - writable: false - }); - Object.defineProperty(abc, "length", { - writable: true - }); - `, "TypeError") - }) -} - -func TestArray_new(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = new Array(null); - var def = new Array(undefined); - [ abc.length, abc[0] === null, def.length, def[0] === undefined ] - `, "1,true,1,true") - - test(` - var abc = new Array(new Number(0)); - var def = new Array(new Number(4294967295)); - [ abc.length, typeof abc[0], abc[0] == 0, def.length, typeof def[0], def[0] == 4294967295 ] - `, "1,object,true,1,object,true") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/ast/comments_test.go b/vendor/github.com/robertkrimen/otto/ast/comments_test.go deleted file mode 100644 index 86d41b192eb..00000000000 --- a/vendor/github.com/robertkrimen/otto/ast/comments_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package ast - -import ( - "github.com/robertkrimen/otto/file" - "testing" -) - -func TestCommentMap(t *testing.T) { - statement := &EmptyStatement{file.Idx(1)} - comment := &Comment{1, "test", LEADING} - - cm := CommentMap{} - cm.AddComment(statement, comment) - - if cm.Size() != 1 { - t.Errorf("the number of comments is %v, not 1", cm.Size()) - } - - if len(cm[statement]) != 1 { - t.Errorf("the number of comments is %v, not 1", cm.Size()) - } - - if cm[statement][0].Text != "test" { - t.Errorf("the text is %v, not \"test\"", cm[statement][0].Text) - } -} - -func TestCommentMap_move(t *testing.T) { - statement1 := &EmptyStatement{file.Idx(1)} - statement2 := &EmptyStatement{file.Idx(2)} - comment := &Comment{1, "test", LEADING} - - cm := CommentMap{} - cm.AddComment(statement1, comment) - - if cm.Size() != 1 { - t.Errorf("the number of comments is %v, not 1", cm.Size()) - } - - if len(cm[statement1]) != 1 { - t.Errorf("the number of comments is %v, not 1", cm.Size()) - } - - if len(cm[statement2]) != 0 { - t.Errorf("the number of comments is %v, not 0", cm.Size()) - } - - cm.MoveComments(statement1, statement2, LEADING) - - if cm.Size() != 1 { - t.Errorf("the number of comments is %v, not 1", cm.Size()) - } - - if len(cm[statement2]) != 1 { - t.Errorf("the number of comments is %v, not 1", cm.Size()) - } - - if len(cm[statement1]) != 0 { - t.Errorf("the number of comments is %v, not 0", cm.Size()) - } -} diff --git a/vendor/github.com/robertkrimen/otto/bug_test.go b/vendor/github.com/robertkrimen/otto/bug_test.go deleted file mode 100644 index 2aac193c167..00000000000 --- a/vendor/github.com/robertkrimen/otto/bug_test.go +++ /dev/null @@ -1,649 +0,0 @@ -package otto - -import ( - "testing" - "time" -) - -func Test_issue116(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [1,-1].sort(function(a, b) { - return a - b; - }); - `, "-1,1") - }) -} - -func Test_262(t *testing.T) { - tt(t, func() { - test, _ := test() - - // 11.13.1-1-1 - test(`raise: - eval("42 = 42;"); - `, "ReferenceError: Invalid left-hand side in assignment") - }) -} - -func Test_issue5(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`'abc' === 'def'`, false) - test(`'\t' === '\r'`, false) - }) -} - -func Test_issue13(t *testing.T) { - tt(t, func() { - test, tester := test() - vm := tester.vm - - value, err := vm.ToValue(map[string]interface{}{ - "string": "Xyzzy", - "number": 42, - "array": []string{"def", "ghi"}, - }) - if err != nil { - t.Error(err) - t.FailNow() - } - - fn, err := vm.Object(` - (function(value){ - return ""+[value.string, value.number, value.array] - }) - `) - if err != nil { - t.Error(err) - t.FailNow() - } - - result, err := fn.Value().Call(fn.Value(), value) - if err != nil { - t.Error(err) - t.FailNow() - } - is(result.string(), "Xyzzy,42,def,ghi") - - anything := struct { - Abc interface{} - }{ - Abc: map[string]interface{}{ - "def": []interface{}{ - []interface{}{ - "a", "b", "c", "", "d", "e", - }, - map[string]interface{}{ - "jkl": "Nothing happens.", - }, - }, - "ghi": -1, - }, - } - - vm.Set("anything", anything) - test(` - [ - anything, - "~", - anything.Abc, - "~", - anything.Abc.def, - "~", - anything.Abc.def[1].jkl, - "~", - anything.Abc.ghi, - ]; - `, "[object Object],~,[object Object],~,a,b,c,,d,e,[object Object],~,Nothing happens.,~,-1") - }) -} - -func Test_issue16(t *testing.T) { - tt(t, func() { - test, vm := test() - - test(` - var def = { - "abc": ["abc"], - "xyz": ["xyz"] - }; - def.abc.concat(def.xyz); - `, "abc,xyz") - - vm.Set("ghi", []string{"jkl", "mno"}) - - test(` - def.abc.concat(def.xyz).concat(ghi); - `, "abc,xyz,jkl,mno") - - test(` - ghi.concat(def.abc.concat(def.xyz)); - `, "jkl,mno,abc,xyz") - - vm.Set("pqr", []interface{}{"jkl", 42, 3.14159, true}) - - test(` - pqr.concat(ghi, def.abc, def, def.xyz); - `, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz") - - test(` - pqr.concat(ghi, def.abc, def, def.xyz).length; - `, 9) - }) -} - -func Test_issue21(t *testing.T) { - tt(t, func() { - vm1 := New() - vm1.Run(` - abc = {} - abc.ghi = "Nothing happens."; - var jkl = 0; - abc.def = function() { - jkl += 1; - return 1; - } - `) - abc, err := vm1.Get("abc") - is(err, nil) - - vm2 := New() - vm2.Set("cba", abc) - _, err = vm2.Run(` - var pqr = 0; - cba.mno = function() { - pqr -= 1; - return 1; - } - cba.def(); - cba.def(); - cba.def(); - `) - is(err, nil) - - jkl, err := vm1.Get("jkl") - is(err, nil) - is(jkl, 3) - - _, err = vm1.Run(` - abc.mno(); - abc.mno(); - abc.mno(); - `) - is(err, nil) - - pqr, err := vm2.Get("pqr") - is(err, nil) - is(pqr, -3) - }) -} - -func Test_issue24(t *testing.T) { - tt(t, func() { - _, vm := test() - - { - vm.Set("abc", []string{"abc", "def", "ghi"}) - value, err := vm.Get("abc") - is(err, nil) - export, _ := value.Export() - { - value, valid := export.([]string) - is(valid, true) - - is(value[0], "abc") - is(value[2], "ghi") - } - } - - { - vm.Set("abc", [...]string{"abc", "def", "ghi"}) - value, err := vm.Get("abc") - is(err, nil) - export, _ := value.Export() - { - value, valid := export.([3]string) - is(valid, true) - - is(value[0], "abc") - is(value[2], "ghi") - } - } - - { - vm.Set("abc", &[...]string{"abc", "def", "ghi"}) - value, err := vm.Get("abc") - is(err, nil) - export, _ := value.Export() - { - value, valid := export.(*[3]string) - is(valid, true) - - is(value[0], "abc") - is(value[2], "ghi") - } - } - - { - vm.Set("abc", map[int]string{0: "abc", 1: "def", 2: "ghi"}) - value, err := vm.Get("abc") - is(err, nil) - export, _ := value.Export() - { - value, valid := export.(map[int]string) - is(valid, true) - - is(value[0], "abc") - is(value[2], "ghi") - } - } - - { - vm.Set("abc", _abcStruct{Abc: true, Ghi: "Nothing happens."}) - value, err := vm.Get("abc") - is(err, nil) - export, _ := value.Export() - { - value, valid := export.(_abcStruct) - is(valid, true) - - is(value.Abc, true) - is(value.Ghi, "Nothing happens.") - } - } - - { - vm.Set("abc", &_abcStruct{Abc: true, Ghi: "Nothing happens."}) - value, err := vm.Get("abc") - is(err, nil) - export, _ := value.Export() - { - value, valid := export.(*_abcStruct) - is(valid, true) - - is(value.Abc, true) - is(value.Ghi, "Nothing happens.") - } - } - }) -} - -func Test_issue39(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 0, def = [], ghi = function() { - if (abc < 10) return ++abc; - return undefined; - } - for (var jkl; (jkl = ghi());) def.push(jkl); - def; - `, "1,2,3,4,5,6,7,8,9,10") - - test(` - var abc = ["1", "2", "3", "4"]; - var def = []; - for (var ghi; (ghi = abc.shift());) { - def.push(ghi); - } - def; - `, "1,2,3,4") - }) -} - -func Test_issue64(t *testing.T) { - tt(t, func() { - test, vm := test() - - defer mockTimeLocal(time.UTC)() - - abc := map[string]interface{}{ - "time": time.Unix(0, 0), - } - vm.Set("abc", abc) - - def := struct { - Public string - private string - }{ - "Public", "private", - } - vm.Set("def", def) - - test(`"sec" in abc.time`, false) - - test(` - [ "Public" in def, "private" in def, def.Public, def.private ]; - `, "true,false,Public,") - - test(`JSON.stringify(abc)`, `{"time":"1970-01-01T00:00:00Z"}`) - }) -} - -func Test_issue73(t *testing.T) { - tt(t, func() { - test, vm := test() - - vm.Set("abc", [4]int{3, 2, 1, 0}) - - test(` - var def = [ 0, 1, 2, 3 ]; - JSON.stringify(def) + JSON.stringify(abc); - `, "[0,1,2,3][3,2,1,0]") - }) -} - -func Test_7_3_1(t *testing.T) { - tt(t, func() { - test(` - eval("var test7_3_1\u2028abc = 66;"); - [ abc, typeof test7_3_1 ]; - `, "66,undefined") - }) -} - -func Test_7_3_3(t *testing.T) { - tt(t, func() { - test(`raise: - eval("//\u2028 =;"); - `, "SyntaxError: Unexpected token =") - }) -} - -func Test_S7_3_A2_1_T1(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - eval("'\u000Astr\u000Aing\u000A'") - `, "SyntaxError: Unexpected token ILLEGAL") - }) -} - -func Test_S7_8_3_A2_1_T1(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ .0 === 0.0, .0, .1 === 0.1, .1 ] - `, "true,0,true,0.1") - }) -} - -func Test_S7_8_4_A4_2_T3(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - "\a" - `, "a") - }) -} - -func Test_S7_9_A1(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var def; - abc: for (var i = 0; i <= 0; i++) { - for (var j = 0; j <= 1; j++) { - if (j === 0) { - continue abc; - } else { - def = true; - } - } - } - [ def, i, j ]; - `, ",1,0") - }) -} - -func Test_S7_9_A3(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - (function(){ - return - 1; - })() - `, "undefined") - }) -} - -func Test_7_3_10(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - eval("var \u0061\u0062\u0063 = 3.14159;"); - abc; - `, 3.14159) - - test(` - abc = undefined; - eval("var \\u0061\\u0062\\u0063 = 3.14159;"); - abc; - `, 3.14159) - }) -} - -func Test_bug(t *testing.T) { - tt(t, func() { - test, _ := test() - - // 10.4.2-1-5 - test(` - "abc\ -def" - `, "abcdef") - - test(` - eval("'abc';\ - 'def'") - `, "def") - - // S12.6.1_A10 - test(` - var abc = 0; - do { - if(typeof(def) === "function"){ - abc = -1; - break; - } else { - abc = 1; - break; - } - } while(function def(){}); - abc; - `, 1) - - // S12.7_A7 - test(`raise: - abc: - while (true) { - eval("continue abc"); - } - `, "SyntaxError: Undefined label 'abc'") - - // S15.1.2.1_A3.3_T3 - test(`raise: - eval("return"); - `, "SyntaxError: Illegal return statement") - - // 15.2.3.3-2-33 - test(` - var abc = { "AB\n\\cd": 1 }; - Object.getOwnPropertyDescriptor(abc, "AB\n\\cd").value; - `, 1) - - // S15.3_A2_T1 - test(`raise: - Function.call(this, "var x / = 1;"); - `, "SyntaxError: Unexpected token /") - - // ? - test(` - (function(){ - var abc = []; - (function(){ - abc.push(0); - abc.push(1); - })(undefined); - if ((function(){ return true; })()) { - (function(){ - abc.push(2); - })(); - } - return abc; - })(); - `, "0,1,2") - - if false { - // 15.9.5.43-0-10 - // Should be an invalid date - test(` - date = new Date(1970, 0, -99999999, 0, 0, 0, 1); - `, "") - } - - // S7.8.3_A1.2_T1 - test(` - [ 0e1, 1e1, 2e1, 3e1, 4e1, 5e1, 6e1, 7e1, 8e1, 9e1 ]; - `, "0,10,20,30,40,50,60,70,80,90") - - // S15.10.2.7_A3_T2 - test(` - var abc = /\s+abc\s+/.exec("\t abc def"); - [ abc.length, abc.index, abc.input, abc ]; - `, "1,0,\t abc def,\t abc ") - }) -} - -func Test_issue79(t *testing.T) { - tt(t, func() { - test, vm := test() - - vm.Set("abc", []_abcStruct{ - { - Ghi: "一", - Def: 1, - }, - { - Def: 3, - Ghi: "三", - }, - { - Def: 2, - Ghi: "二", - }, - { - Def: 4, - Ghi: "四", - }, - }) - - test(` - abc.sort(function(a,b){ return b.Def-a.Def }); - def = []; - for (i = 0; i < abc.length; i++) { - def.push(abc[i].String()) - } - def; - `, "四,三,二,一") - }) -} - -func Test_issue80(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - JSON.stringify([ - 1401868959, - 14018689591, - 140186895901, - 1401868959001, - 14018689590001, - 140186895900001, - 1401868959000001, - 1401868959000001.5, - 14018689590000001, - 140186895900000001, - 1401868959000000001, - 14018689590000000001, - 140186895900000000001, - 140186895900000000001.5 - ]); - `, "[1401868959,14018689591,140186895901,1401868959001,14018689590001,140186895900001,1401868959000001,1.4018689590000015e+15,14018689590000001,140186895900000001,1401868959000000001,1.401868959e+19,1.401868959e+20,1.401868959e+20]") - }) -} - -func Test_issue86(t *testing.T) { - tt(t, func() { - test, tester := test() - - test(` - var obj = Object.create({}, { - abc: { - get: function(){ - return 1; - } - } - }); - obj.abc; - `, 1) - - v, err := tester.vm.Copy().Run(`obj.abc;`) - is(is(v, 1), is(nil, err)) - }) -} - -func Test_issue87(t *testing.T) { - tt(t, func() { - test, vm := test() - - test(` - var def = 0; - abc: { - for (;;) { - def = !1; - break abc; - } - def = !0; - } - def; - `, false) - - _, err := vm.Run(` -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(h,s){var f={},g=f.lib={},q=function(){},m=g.Base={extend:function(a){q.prototype=this;var c=new q;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -r=g.WordArray=m.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=s?c:4*a.length},toString:function(a){return(a||k).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>3]|=parseInt(a.substr(b, -2),16)<<24-4*(b%8);return new r.init(d,c/2)}},n=l.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new r.init(d,c)}},j=l.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}}, -u=g.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var g=0;gn;){var j;a:{j=k;for(var u=h.sqrt(j),t=2;t<=u;t++)if(!(j%t)){j=!1;break a}j=!0}j&&(8>n&&(m[n]=l(h.pow(k,0.5))),r[n]=l(h.pow(k,1/3)),n++);k++}var a=[],f=f.SHA256=q.extend({_doReset:function(){this._hash=new g.init(m.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],g=b[2],j=b[3],h=b[4],m=b[5],n=b[6],q=b[7],p=0;64>p;p++){if(16>p)a[p]= -c[d+p]|0;else{var k=a[p-15],l=a[p-2];a[p]=((k<<25|k>>>7)^(k<<14|k>>>18)^k>>>3)+a[p-7]+((l<<15|l>>>17)^(l<<13|l>>>19)^l>>>10)+a[p-16]}k=q+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&m^~h&n)+r[p]+a[p];l=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&g^f&g);q=n;n=m;m=h;h=j+k|0;j=g;g=f;f=e;e=k+l|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+g|0;b[3]=b[3]+j|0;b[4]=b[4]+h|0;b[5]=b[5]+m|0;b[6]=b[6]+n|0;b[7]=b[7]+q|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; -d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=q.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=q._createHelper(f);s.HmacSHA256=q._createHmacHelper(f)})(Math); -(function(){var h=CryptoJS,s=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(f,g){f=this._hasher=new f.init;"string"==typeof g&&(g=s.parse(g));var h=f.blockSize,m=4*h;g.sigBytes>m&&(g=f.finalize(g));g.clamp();for(var r=this._oKey=g.clone(),l=this._iKey=g.clone(),k=r.words,n=l.words,j=0;j 0 { - is(value, expect[0]) - } - } - } - - test(``, Value{}) - - test(`var abc = 1; abc;`, 1) - - test(`var abc = 1 + 1; abc;`, 2) - - test(`1 + 2;`, 3) - }) -} - -func TestParse_cmpl(t *testing.T) { - tt(t, func() { - - test := func(src string) { - program, err := parser.ParseFile(nil, "", src, 0) - is(err, nil) - is(cmpl_parse(program), "!=", nil) - } - - test(``) - - test(`var abc = 1; abc;`) - - test(` - function abc() { - return; - } - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/date_test.go b/vendor/github.com/robertkrimen/otto/date_test.go deleted file mode 100644 index a9c71edde4f..00000000000 --- a/vendor/github.com/robertkrimen/otto/date_test.go +++ /dev/null @@ -1,481 +0,0 @@ -package otto - -import ( - "math" - "testing" - "time" -) - -func mockTimeLocal(location *time.Location) func() { - local := time.Local - time.Local = location - return func() { - time.Local = local - } -} - -// Passing or failing should not be dependent on what time zone we're in -func mockUTC() func() { - return mockTimeLocal(time.UTC) -} - -func TestDate(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - time0 := time.Unix(1348616313, 47*1000*1000).Local() - - test(`Date`, "function Date() { [native code] }") - test(`new Date(0).toUTCString()`, "Thu, 01 Jan 1970 00:00:00 UTC") - test(`new Date(0).toGMTString()`, "Thu, 01 Jan 1970 00:00:00 GMT") - if false { - // TODO toLocale{Date,Time}String - test(`new Date(0).toLocaleString()`, "") - test(`new Date(0).toLocaleDateString()`, "") - test(`new Date(0).toLocaleTimeString()`, "") - } - test(`new Date(1348616313).getTime()`, 1348616313) - test(`new Date(1348616313).toUTCString()`, "Fri, 16 Jan 1970 14:36:56 UTC") - test(`abc = new Date(1348616313047); abc.toUTCString()`, "Tue, 25 Sep 2012 23:38:33 UTC") - test(`abc.getYear()`, time0.Year()-1900) - test(`abc.getFullYear()`, time0.Year()) - test(`abc.getUTCFullYear()`, 2012) - test(`abc.getMonth()`, int(time0.Month())-1) // Remember, the JavaScript month is 0-based - test(`abc.getUTCMonth()`, 8) - test(`abc.getDate()`, time0.Day()) - test(`abc.getUTCDate()`, 25) - test(`abc.getDay()`, int(time0.Weekday())) - test(`abc.getUTCDay()`, 2) - test(`abc.getHours()`, time0.Hour()) - test(`abc.getUTCHours()`, 23) - test(`abc.getMinutes()`, time0.Minute()) - test(`abc.getUTCMinutes()`, 38) - test(`abc.getSeconds()`, time0.Second()) - test(`abc.getUTCSeconds()`, 33) - test(`abc.getMilliseconds()`, time0.Nanosecond()/(1000*1000)) // In honor of the 47% - test(`abc.getUTCMilliseconds()`, 47) - _, offset := time0.Zone() - test(`abc.getTimezoneOffset()`, offset/-60) - - test(`new Date("Xyzzy").getTime()`, math.NaN()) - - test(`abc.setFullYear(2011); abc.toUTCString()`, "Sun, 25 Sep 2011 23:38:33 UTC") - test(`new Date(12564504e5).toUTCString()`, "Sun, 25 Oct 2009 06:00:00 UTC") - test(`new Date(2009, 9, 25).toUTCString()`, "Sun, 25 Oct 2009 00:00:00 UTC") - test(`+(new Date(2009, 9, 25))`, 1256428800000) - - format := "Mon, 2 Jan 2006 15:04:05 MST" - - time1 := time.Unix(1256450400, 0) - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), 2001*1000*1000, time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMilliseconds(2001); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), 61, time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setSeconds("61"); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), 61, time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMinutes("61"); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), 5, time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setHours("5"); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(time1.Year(), time1.Month(), 26, time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setDate("26"); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(time1.Year(), 10, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMonth(9); abc.toUTCString()`, time0.Format(format)) - test(`abc = new Date(12564504e5); abc.setMonth("09"); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(time1.Year(), 11, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setMonth("10"); abc.toUTCString()`, time0.Format(format)) - - time0 = time.Date(2010, time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC() - test(`abc = new Date(12564504e5); abc.setFullYear(2010); abc.toUTCString()`, time0.Format(format)) - - test(`new Date("2001-01-01T10:01:02.000").getTime()`, 978343262000) - - // Date() - test(`typeof Date()`, "string") - test(`typeof Date(2006, 1, 2)`, "string") - - test(` - abc = Object.getOwnPropertyDescriptor(Date, "parse"); - [ abc.value === Date.parse, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") - - test(` - abc = Object.getOwnPropertyDescriptor(Date.prototype, "toTimeString"); - [ abc.value === Date.prototype.toTimeString, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") - - test(` - var abc = Object.getOwnPropertyDescriptor(Date, "prototype"); - [ [ typeof Date.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") - }) -} - -func TestDate_parse(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(`Date.parse("2001-01-01T10:01:02.000")`, 978343262000) - - test(`Date.parse("2006-01-02T15:04:05.000")`, 1136214245000) - - test(`Date.parse("2006")`, 1136073600000) - - test(`Date.parse("1970-01-16T14:36:56+00:00")`, 1348616000) - - test(`Date.parse("1970-01-16T14:36:56.313+00:00")`, 1348616313) - - test(`Date.parse("1970-01-16T14:36:56.000")`, 1348616000) - - test(`Date.parse.length`, 1) - }) -} - -func TestDate_UTC(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(`Date.UTC(2009, 9, 25)`, 1256428800000) - - test(`Date.UTC.length`, 7) - }) -} - -func TestDate_now(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - // FIXME I think this too risky - test(`+(""+Date.now()).substr(0, 10)`, float64(epochToInteger(timeToEpoch(time.Now()))/1000)) - - test(`Date.now() - Date.now(1,2,3) < 24 * 60 * 60`, true) - }) -} - -func TestDate_toISOString(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(`new Date(0).toISOString()`, "1970-01-01T00:00:00.000Z") - }) -} - -func TestDate_toJSON(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(`new Date(0).toJSON()`, "1970-01-01T00:00:00.000Z") - }) -} - -func TestDate_setYear(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(`new Date(12564504e5).setYear(96)`, 846223200000) - - test(`new Date(12564504e5).setYear(1996)`, 846223200000) - - test(`new Date(12564504e5).setYear(2000)`, 972453600000) - }) -} - -func TestDateDefaultValue(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - var date = new Date(); - date + 0 === date.toString() + "0"; - `, true) - }) -} - -func TestDate_April1978(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - var abc = new Date(1978,3); - [ abc.getYear(), abc.getMonth(), abc.valueOf() ]; - `, "78,3,260236800000") - }) -} - -func TestDate_setMilliseconds(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = new Date(); - def = abc.setMilliseconds(); - [ abc, def ]; - `, "Invalid Date,NaN") - }) -} - -func TestDate_new(t *testing.T) { - // FIXME? - // This is probably incorrect, due to differences in Go date/time handling - // versus ECMA date/time handling, but we'll leave this here for - // future reference - - if true { - return - } - - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - [ - new Date(1899, 11).valueOf(), - new Date(1899, 12).valueOf(), - new Date(1900, 0).valueOf() - ] - `, "-2211638400000,-2208960000000,-2208960000000") - }) -} - -func TestDateComparison(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - var now0 = Date.now(); - var now1 = (new Date()).toString(); - [ now0 === now1, Math.abs(now0 - Date.parse(now1)) <= 1000 ]; - `, "false,true") - }) -} - -func TestDate_setSeconds(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setSeconds(10, 12); - - def.setSeconds(10); - def.setMilliseconds(12); - - abc.valueOf() === def.valueOf(); - `, true) - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setUTCSeconds(10, 12); - - def.setUTCSeconds(10); - def.setUTCMilliseconds(12); - - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setSeconds.length`, 2) - test(`Date.prototype.setUTCSeconds.length`, 2) - }) -} - -func TestDate_setMinutes(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setMinutes(8, 10, 12); - - def.setMinutes(8); - def.setSeconds(10); - def.setMilliseconds(12); - - abc.valueOf() === def.valueOf(); - `, true) - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setUTCMinutes(8, 10, 12); - - def.setUTCMinutes(8); - def.setUTCSeconds(10); - def.setUTCMilliseconds(12); - - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setMinutes.length`, 3) - test(`Date.prototype.setUTCMinutes.length`, 3) - }) -} - -func TestDate_setHours(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setHours(6, 8, 10, 12); - - def.setHours(6); - def.setMinutes(8); - def.setSeconds(10); - def.setMilliseconds(12); - - abc.valueOf() === def.valueOf(); - `, true) - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setUTCHours(6, 8, 10, 12); - - def.setUTCHours(6); - def.setUTCMinutes(8); - def.setUTCSeconds(10); - def.setUTCMilliseconds(12); - - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setHours.length`, 4) - test(`Date.prototype.setUTCHours.length`, 4) - }) -} - -func TestDate_setMonth(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setMonth(6, 8); - - def.setMonth(6); - def.setDate(8); - - abc.valueOf() === def.valueOf(); - `, true) - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setUTCMonth(6, 8); - - def.setUTCMonth(6); - def.setUTCDate(8); - - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setMonth.length`, 2) - test(`Date.prototype.setUTCMonth.length`, 2) - }) -} - -func TestDate_setFullYear(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setFullYear(1981, 6, 8); - - def.setFullYear(1981); - def.setMonth(6); - def.setDate(8); - - abc.valueOf() === def.valueOf(); - `, true) - - test(` - abc = new Date(1980, 10); - def = new Date(abc); - - abc.setUTCFullYear(1981, 6, 8); - - def.setUTCFullYear(1981); - def.setUTCMonth(6); - def.setUTCDate(8); - - abc.valueOf() === def.valueOf(); - `, true) - - test(`Date.prototype.setFullYear.length`, 3) - test(`Date.prototype.setUTCFullYear.length`, 3) - }) -} - -func TestDate_setTime(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - var abc = new Date(1999, 6, 1); - var def = new Date(); - def.setTime(abc.getTime()); - [ def, abc.valueOf() == def.valueOf() ]; - `, "Thu, 01 Jul 1999 00:00:00 UTC,true") - - test(`Date.prototype.setTime.length`, 1) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/documentation_test.go b/vendor/github.com/robertkrimen/otto/documentation_test.go deleted file mode 100644 index 04646117fc7..00000000000 --- a/vendor/github.com/robertkrimen/otto/documentation_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package otto - -import ( - "fmt" -) - -func ExampleSynopsis() { - - vm := New() - vm.Run(` - abc = 2 + 2; - console.log("The value of abc is " + abc); // 4 - `) - - value, _ := vm.Get("abc") - { - value, _ := value.ToInteger() - fmt.Println(value) - } - - vm.Set("def", 11) - vm.Run(` - console.log("The value of def is " + def); - `) - - vm.Set("xyzzy", "Nothing happens.") - vm.Run(` - console.log(xyzzy.length); - `) - - value, _ = vm.Run("xyzzy.length") - { - value, _ := value.ToInteger() - fmt.Println(value) - } - - value, err := vm.Run("abcdefghijlmnopqrstuvwxyz.length") - fmt.Println(value) - fmt.Println(err) - - vm.Set("sayHello", func(call FunctionCall) Value { - fmt.Printf("Hello, %s.\n", call.Argument(0).String()) - return UndefinedValue() - }) - - vm.Set("twoPlus", func(call FunctionCall) Value { - right, _ := call.Argument(0).ToInteger() - result, _ := vm.ToValue(2 + right) - return result - }) - - value, _ = vm.Run(` - sayHello("Xyzzy"); - sayHello(); - - result = twoPlus(2.0); - `) - fmt.Println(value) - - // Output: - // The value of abc is 4 - // 4 - // The value of def is 11 - // 16 - // 16 - // undefined - // ReferenceError: 'abcdefghijlmnopqrstuvwxyz' is not defined - // Hello, Xyzzy. - // Hello, undefined. - // 4 -} - -func ExampleConsole() { - - vm := New() - console := map[string]interface{}{ - "log": func(call FunctionCall) Value { - fmt.Println("console.log:", formatForConsole(call.ArgumentList)) - return UndefinedValue() - }, - } - - err := vm.Set("console", console) - - value, err := vm.Run(` - console.log("Hello, World."); - `) - fmt.Println(value) - fmt.Println(err) - - // Output: - // console.log: Hello, World. - // undefined - // -} diff --git a/vendor/github.com/robertkrimen/otto/error_native_test.go b/vendor/github.com/robertkrimen/otto/error_native_test.go deleted file mode 100644 index f6579ca07ac..00000000000 --- a/vendor/github.com/robertkrimen/otto/error_native_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package otto - -import ( - "testing" -) - -// this is its own file because the tests in it rely on the line numbers of -// some of the functions defined here. putting it in with the rest of the -// tests would probably be annoying. - -func TestErrorContextNative(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("N", func(c FunctionCall) Value { - v, err := c.Argument(0).Call(NullValue()) - if err != nil { - panic(err) - } - return v - }) - - s, _ := vm.Compile("test.js", ` - function F() { throw new Error('wow'); } - function G() { return N(F); } - `) - - vm.Run(s) - - f1, _ := vm.Get("G") - _, err := f1.Call(NullValue()) - err1 := err.(*Error) - is(err1.message, "wow") - is(len(err1.trace), 3) - is(err1.trace[0].location(), "F (test.js:2:29)") - is(err1.trace[1].location(), "github.com/robertkrimen/otto.TestErrorContextNative.func1.1 (error_native_test.go:15)") - is(err1.trace[2].location(), "G (test.js:3:26)") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/error_test.go b/vendor/github.com/robertkrimen/otto/error_test.go deleted file mode 100644 index d44fedf1ea7..00000000000 --- a/vendor/github.com/robertkrimen/otto/error_test.go +++ /dev/null @@ -1,479 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestError(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty("message") ]; - `, "Error,,true") - }) -} - -func TestError_instanceof(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`(new TypeError()) instanceof Error`, true) - }) -} - -func TestPanicValue(t *testing.T) { - tt(t, func() { - test, vm := test() - - vm.Set("abc", func(call FunctionCall) Value { - value, err := call.Otto.Run(`({ def: 3.14159 })`) - is(err, nil) - panic(value) - }) - - test(` - try { - abc(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def ]; - `, "false,,3.14159") - }) -} - -func Test_catchPanic(t *testing.T) { - tt(t, func() { - vm := New() - - _, err := vm.Run(` - A syntax error that - does not define - var; - abc; - `) - is(err, "!=", nil) - - _, err = vm.Call(`abc.def`, nil) - is(err, "!=", nil) - }) -} - -func TestErrorContext(t *testing.T) { - tt(t, func() { - vm := New() - - _, err := vm.Run(` - undefined(); - `) - { - err := err.(*Error) - is(err.message, "'undefined' is not a function") - is(len(err.trace), 1) - is(err.trace[0].location(), ":2:13") - } - - _, err = vm.Run(` - ({}).abc(); - `) - { - err := err.(*Error) - is(err.message, "'abc' is not a function") - is(len(err.trace), 1) - is(err.trace[0].location(), ":2:14") - } - - _, err = vm.Run(` - ("abc").abc(); - `) - { - err := err.(*Error) - is(err.message, "'abc' is not a function") - is(len(err.trace), 1) - is(err.trace[0].location(), ":2:14") - } - - _, err = vm.Run(` - var ghi = "ghi"; - ghi(); - `) - { - err := err.(*Error) - is(err.message, "'ghi' is not a function") - is(len(err.trace), 1) - is(err.trace[0].location(), ":3:13") - } - - _, err = vm.Run(` - function def() { - undefined(); - } - function abc() { - def(); - } - abc(); - `) - { - err := err.(*Error) - is(err.message, "'undefined' is not a function") - is(len(err.trace), 3) - is(err.trace[0].location(), "def (:3:17)") - is(err.trace[1].location(), "abc (:6:17)") - is(err.trace[2].location(), ":8:13") - } - - _, err = vm.Run(` - function abc() { - xyz(); - } - abc(); - `) - { - err := err.(*Error) - is(err.message, "'xyz' is not defined") - is(len(err.trace), 2) - is(err.trace[0].location(), "abc (:3:17)") - is(err.trace[1].location(), ":5:13") - } - - _, err = vm.Run(` - mno + 1; - `) - { - err := err.(*Error) - is(err.message, "'mno' is not defined") - is(len(err.trace), 1) - is(err.trace[0].location(), ":2:13") - } - - _, err = vm.Run(` - eval("xyz();"); - `) - { - err := err.(*Error) - is(err.message, "'xyz' is not defined") - is(len(err.trace), 1) - is(err.trace[0].location(), ":1:1") - } - - _, err = vm.Run(` - xyzzy = "Nothing happens." - eval("xyzzy();"); - `) - { - err := err.(*Error) - is(err.message, "'xyzzy' is not a function") - is(len(err.trace), 1) - is(err.trace[0].location(), ":1:1") - } - - _, err = vm.Run(` - throw Error("xyzzy"); - `) - { - err := err.(*Error) - is(err.message, "xyzzy") - is(len(err.trace), 1) - is(err.trace[0].location(), ":2:19") - } - - _, err = vm.Run(` - throw new Error("xyzzy"); - `) - { - err := err.(*Error) - is(err.message, "xyzzy") - is(len(err.trace), 1) - is(err.trace[0].location(), ":2:23") - } - - script1, err := vm.Compile("file1.js", - `function A() { - throw new Error("test"); - } - - function C() { - var o = null; - o.prop = 1; - } - `) - is(err, nil) - - _, err = vm.Run(script1) - is(err, nil) - - script2, err := vm.Compile("file2.js", - `function B() { - A() - } - `) - is(err, nil) - - _, err = vm.Run(script2) - is(err, nil) - - script3, err := vm.Compile("file3.js", "B()") - is(err, nil) - - _, err = vm.Run(script3) - { - err := err.(*Error) - is(err.message, "test") - is(len(err.trace), 3) - is(err.trace[0].location(), "A (file1.js:2:15)") - is(err.trace[1].location(), "B (file2.js:2:5)") - is(err.trace[2].location(), "file3.js:1:1") - } - - { - f, _ := vm.Get("B") - _, err := f.Call(UndefinedValue()) - err1 := err.(*Error) - is(err1.message, "test") - is(len(err1.trace), 2) - is(err1.trace[0].location(), "A (file1.js:2:15)") - is(err1.trace[1].location(), "B (file2.js:2:5)") - } - - { - f, _ := vm.Get("C") - _, err := f.Call(UndefinedValue()) - err1 := err.(*Error) - is(err1.message, "Cannot access member 'prop' of null") - is(len(err1.trace), 1) - is(err1.trace[0].location(), "C (file1.js:7:5)") - } - - }) -} - -func TestMakeCustomErrorReturn(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("A", func(c FunctionCall) Value { - return vm.MakeCustomError("CarrotError", "carrots is life, carrots is love") - }) - - s, _ := vm.Compile("test.js", ` - function B() { return A(); } - function C() { return B(); } - function D() { return C(); } - `) - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - v, err := vm.Call("D", nil) - if err != nil { - panic(err) - } - - is(v.Class(), "Error") - - name, err := v.Object().Get("name") - if err != nil { - panic(err) - } - is(name.String(), "CarrotError") - - message, err := v.Object().Get("message") - if err != nil { - panic(err) - } - is(message.String(), "carrots is life, carrots is love") - - str, err := v.Object().Call("toString") - if err != nil { - panic(err) - } - is(str, "CarrotError: carrots is life, carrots is love") - - i, err := v.Export() - if err != nil { - panic(err) - } - t.Logf("%#v\n", i) - }) -} - -func TestMakeCustomError(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("A", func(c FunctionCall) Value { - panic(vm.MakeCustomError("CarrotError", "carrots is life, carrots is love")) - - return UndefinedValue() - }) - - s, _ := vm.Compile("test.js", ` - function B() { A(); } - function C() { B(); } - function D() { C(); } - `) - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "CarrotError: carrots is life, carrots is love") - - er := err.(*Error) - - is(er.name, "CarrotError") - is(er.message, "carrots is life, carrots is love") - }) -} - -func TestMakeCustomErrorFreshVM(t *testing.T) { - tt(t, func() { - vm := New() - e := vm.MakeCustomError("CarrotError", "carrots is life, carrots is love") - - str, err := e.ToString() - if err != nil { - panic(err) - } - - is(str, "CarrotError: carrots is life, carrots is love") - }) -} - -func TestMakeTypeError(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("A", func(c FunctionCall) Value { - panic(vm.MakeTypeError("these aren't my glasses")) - - return UndefinedValue() - }) - - s, _ := vm.Compile("test.js", ` - function B() { A(); } - function C() { B(); } - function D() { C(); } - `) - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "TypeError: these aren't my glasses") - - er := err.(*Error) - - is(er.name, "TypeError") - is(er.message, "these aren't my glasses") - }) -} - -func TestMakeRangeError(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("A", func(c FunctionCall) Value { - panic(vm.MakeRangeError("too many")) - - return UndefinedValue() - }) - - s, _ := vm.Compile("test.js", ` - function B() { A(); } - function C() { B(); } - function D() { C(); } - `) - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "RangeError: too many") - - er := err.(*Error) - - is(er.name, "RangeError") - is(er.message, "too many") - }) -} - -func TestMakeSyntaxError(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("A", func(c FunctionCall) Value { - panic(vm.MakeSyntaxError("i think you meant \"you're\"")) - - return UndefinedValue() - }) - - s, _ := vm.Compile("test.js", ` - function B() { A(); } - function C() { B(); } - function D() { C(); } - `) - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "SyntaxError: i think you meant \"you're\"") - - er := err.(*Error) - - is(er.name, "SyntaxError") - is(er.message, "i think you meant \"you're\"") - }) -} - -func TestErrorStackProperty(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.Compile("test.js", ` - function A() { throw new TypeError('uh oh'); } - function B() { return A(); } - function C() { return B(); } - - var s = null; - - try { C(); } catch (e) { s = e.stack; } - - s; - `) - if err != nil { - panic(err) - } - - v, err := vm.Run(s) - if err != nil { - panic(err) - } - - is(v.String(), "TypeError: uh oh\n at A (test.js:2:29)\n at B (test.js:3:26)\n at C (test.js:4:26)\n at test.js:8:10\n") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/function_stack_test.go b/vendor/github.com/robertkrimen/otto/function_stack_test.go deleted file mode 100644 index b230f5ce71b..00000000000 --- a/vendor/github.com/robertkrimen/otto/function_stack_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package otto - -import ( - "testing" -) - -// this is its own file because the tests in it rely on the line numbers of -// some of the functions defined here. putting it in with the rest of the -// tests would probably be annoying. - -func TestFunction_stack(t *testing.T) { - tt(t, func() { - vm := New() - - s, _ := vm.Compile("fake.js", `function X(fn1, fn2, fn3) { fn1(fn2, fn3); }`) - vm.Run(s) - - expected := []_frame{ - {native: true, nativeFile: "function_stack_test.go", nativeLine: 30, offset: 0, callee: "github.com/robertkrimen/otto.TestFunction_stack.func1.2"}, - {native: true, nativeFile: "function_stack_test.go", nativeLine: 25, offset: 0, callee: "github.com/robertkrimen/otto.TestFunction_stack.func1.1"}, - {native: false, nativeFile: "", nativeLine: 0, offset: 29, callee: "X", file: s.program.file}, - {native: false, nativeFile: "", nativeLine: 0, offset: 29, callee: "X", file: s.program.file}, - } - - vm.Set("A", func(c FunctionCall) Value { - c.Argument(0).Call(UndefinedValue()) - return UndefinedValue() - }) - - vm.Set("B", func(c FunctionCall) Value { - depth := 0 - for scope := c.Otto.runtime.scope; scope != nil; scope = scope.outer { - is(scope.frame, expected[depth]) - depth++ - } - - is(depth, 4) - - return UndefinedValue() - }) - - x, _ := vm.Get("X") - a, _ := vm.Get("A") - b, _ := vm.Get("B") - - x.Call(UndefinedValue(), x, a, b) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/function_test.go b/vendor/github.com/robertkrimen/otto/function_test.go deleted file mode 100644 index c10bf8592ae..00000000000 --- a/vendor/github.com/robertkrimen/otto/function_test.go +++ /dev/null @@ -1,280 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestFunction(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = Object.getOwnPropertyDescriptor(Function, "prototype"); - [ [ typeof Function.prototype, typeof Function.prototype.length, Function.prototype.length ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "function,number,0,false,false,false") - }) -} - -func Test_argumentList2parameterList(t *testing.T) { - tt(t, func() { - is(argumentList2parameterList([]Value{toValue("abc, def"), toValue("ghi")}), []string{"abc", "def", "ghi"}) - }) -} - -func TestFunction_new(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - new Function({}); - `, "SyntaxError: Unexpected identifier") - - test(` - var abc = Function("def, ghi", "jkl", "return def+ghi+jkl"); - [ typeof abc, abc instanceof Function, abc("ab", "ba", 1) ]; - `, "function,true,abba1") - - test(`raise: - var abc = { - toString: function() { throw 1; } - }; - var def = { - toString: function() { throw 2; } - }; - var ghi = new Function(abc, def); - ghi; - `, "1") - - // S15.3.2.1_A3_T10 - test(`raise: - var abc = { - toString: function() { return "z;x"; } - }; - var def = "return this"; - var ghi = new Function(abc, def); - ghi; - `, "SyntaxError: Unexpected token ;") - - test(`raise: - var abc; - var def = "return true"; - var ghi = new Function(null, def); - ghi; - `, "SyntaxError: Unexpected token null") - }) -} - -func TestFunction_apply(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Function.prototype.apply.length`, 2) - test(`String.prototype.substring.apply("abc", [1, 11])`, "bc") - }) -} - -func TestFunction_call(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Function.prototype.call.length`, 1) - test(`String.prototype.substring.call("abc", 1, 11)`, "bc") - }) -} - -func TestFunctionArguments(t *testing.T) { - tt(t, func() { - test, _ := test() - - // Should not be able to delete arguments - test(` - function abc(def, arguments){ - delete def; - return def; - } - abc(1); - `, 1) - - // Again, should not be able to delete arguments - test(` - function abc(def){ - delete def; - return def; - } - abc(1); - `, 1) - - // Test typeof of a function argument - test(` - function abc(def, ghi, jkl){ - return typeof jkl - } - abc("1st", "2nd", "3rd", "4th", "5th"); - `, "string") - - test(` - function abc(def, ghi, jkl){ - arguments[0] = 3.14; - arguments[1] = 'Nothing happens'; - arguments[2] = 42; - if (3.14 === def && 'Nothing happens' === ghi && 42 === jkl) - return true; - } - abc(-1, 4.2, 314); - `, true) - }) -} - -func TestFunctionDeclarationInFunction(t *testing.T) { - tt(t, func() { - test, _ := test() - - // Function declarations happen AFTER parameter/argument declarations - // That is, a function declared within a function will shadow/overwrite - // declared parameters - - test(` - function abc(def){ - return def; - function def(){ - return 1; - } - } - typeof abc(); - `, "function") - }) -} - -func TestArguments_defineOwnProperty(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc; - var def = true; - var ghi = {}; - (function (a, b, c) { - Object.defineProperty(arguments, "0", { - value: 42, - writable: false, - enumerable: false, - configurable: false - }); - Object.defineProperty(arguments, "1", { - value: 3.14, - configurable: true, - enumerable: true - }); - abc = Object.getOwnPropertyDescriptor(arguments, "0"); - for (var name in arguments) { - ghi[name] = (ghi[name] || 0) + 1; - if (name === "0") { - def = false; - } - } - }(0, 1, 2)); - [ abc.value, abc.writable, abc.enumerable, abc.configurable, def, ghi["1"] ]; - `, "42,false,false,false,true,1") - }) -} - -func TestFunction_bind(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - abc = function(){ - return "abc"; - }; - def = abc.bind(); - [ typeof def.prototype, typeof def.hasOwnProperty, def.hasOwnProperty("caller"), def.hasOwnProperty("arguments"), def() ]; - `, "object,function,true,true,abc") - - test(` - abc = function(){ - return arguments[1]; - }; - def = abc.bind(undefined, "abc"); - ghi = abc.bind(undefined, "abc", "ghi"); - [ def(), def("def"), ghi("def") ]; - `, ",def,ghi") - - test(` - var abc = function () {}; - var ghi; - try { - Object.defineProperty(Function.prototype, "xyzzy", { - value: 1001, - writable: true, - enumerable: true, - configurable: true - }); - var def = abc.bind({}); - ghi = !def.hasOwnProperty("xyzzy") && ghi.xyzzy === 1001; - } finally { - delete Function.prototype.xyzzy; - } - [ ghi ]; - `, "true") - - test(` - var abc = function (def, ghi) {}; - var jkl = abc.bind({}); - var mno = abc.bind({}, 1, 2); - [ jkl.length, mno.length ]; - `, "2,0") - - test(`raise: - Math.bind(); - `, "TypeError: 'bind' is not a function") - - test(` - function construct(fn, arguments) { - var bound = Function.prototype.bind.apply(fn, [null].concat(arguments)); - return new bound(); - } - var abc = construct(Date, [1957, 4, 27]); - Object.prototype.toString.call(abc); - `, "[object Date]") - - test(` - var fn = function (x, y, z) { - var result = {}; - result.abc = x + y + z; - result.def = arguments[0] === "a" && arguments.length === 3; - return result; - }; - var newFn = Function.prototype.bind.call(fn, {}, "a", "b", "c"); - var result = new newFn(); - [ result.hasOwnProperty("abc"), result.hasOwnProperty("def"), result.abc, result.def ]; - `, "true,true,abc,true") - - test(` - abc = function(){ - return "abc"; - }; - def = abc.bind(); - def.toString(); - `, "function () { [native code] }") - }) -} - -func TestFunction_toString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - Function.prototype.toString.call(undefined); - `, "TypeError") - - test(` - abc = function() { return -1 ; -} - 1; - abc.toString(); - `, "function() { return -1 ;\n}") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/global_test.go b/vendor/github.com/robertkrimen/otto/global_test.go deleted file mode 100644 index 9257b58c372..00000000000 --- a/vendor/github.com/robertkrimen/otto/global_test.go +++ /dev/null @@ -1,355 +0,0 @@ -package otto - -import ( - "fmt" - "math" - "strings" - "testing" -) - -func TestGlobal(t *testing.T) { - tt(t, func() { - test, vm := test() - - runtime := vm.vm.runtime - - { - call := func(object interface{}, src string, argumentList ...interface{}) Value { - var tgt *Object - switch object := object.(type) { - case Value: - tgt = object.Object() - case *Object: - tgt = object - case *_object: - tgt = toValue_object(object).Object() - default: - panic("Here be dragons.") - } - value, err := tgt.Call(src, argumentList...) - is(err, nil) - return value - } - - // FIXME enterGlobalScope - if false { - value := runtime.scope.lexical.getBinding("Object", false)._object().call(UndefinedValue(), []Value{toValue(runtime.newObject())}, false, nativeFrame) - is(value.IsObject(), true) - is(value, "[object Object]") - is(value._object().prototype == runtime.global.ObjectPrototype, true) - is(value._object().prototype == runtime.global.Object.get("prototype")._object(), true) - is(value._object().get("toString"), "function toString() { [native code] }") - is(call(value.Object(), "hasOwnProperty", "hasOwnProperty"), false) - - is(call(value._object().get("toString")._object().prototype, "toString"), "function () { [native code] }") // TODO Is this right? - is(value._object().get("toString")._object().get("toString"), "function toString() { [native code] }") - is(value._object().get("toString")._object().get("toString")._object(), "function toString() { [native code] }") - - is(call(value._object(), "propertyIsEnumerable", "isPrototypeOf"), false) - value._object().put("xyzzy", toValue_string("Nothing happens."), false) - is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) - is(call(value, "propertyIsEnumerable", "xyzzy"), true) - is(value._object().get("xyzzy"), "Nothing happens.") - - is(call(runtime.scope.lexical.getBinding("Object", false), "isPrototypeOf", value), false) - is(call(runtime.scope.lexical.getBinding("Object", false)._object().get("prototype"), "isPrototypeOf", value), true) - is(call(runtime.scope.lexical.getBinding("Function", false), "isPrototypeOf", value), false) - - is(runtime.newObject().prototype == runtime.global.Object.get("prototype")._object(), true) - - abc := runtime.newBoolean(toValue_bool(true)) - is(toValue_object(abc), "true") // TODO Call primitive? - - //def := runtime.localGet("Boolean")._object().Construct(UndefinedValue(), []Value{}) - //is(def, "false") // TODO Call primitive? - } - } - - test(`new Number().constructor == Number`, true) - - test(`this.hasOwnProperty`, "function hasOwnProperty() { [native code] }") - - test(`eval.length === 1`, true) - test(`eval.prototype === undefined`, true) - test(`raise: new eval()`, "TypeError: function eval() { [native code] } is not a constructor") - - test(` - [ - [ delete undefined, undefined ], - [ delete NaN, NaN ], - [ delete Infinity, Infinity ], - ]; - `, "false,,false,NaN,false,Infinity") - - test(` - Object.getOwnPropertyNames(Function('return this')()).sort(); - `, "Array,Boolean,Date,Error,EvalError,Function,Infinity,JSON,Math,NaN,Number,Object,RangeError,ReferenceError,RegExp,String,SyntaxError,TypeError,URIError,console,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,eval,isFinite,isNaN,parseFloat,parseInt,undefined,unescape") - - // __defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf - test(` - Object.getOwnPropertyNames(Object.prototype).sort(); - `, "constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf") - - // arguments,caller,length,name,prototype - test(` - Object.getOwnPropertyNames(EvalError).sort(); - `, "length,prototype") - - test(` - var abc = []; - var def = [EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError]; - for (constructor in def) { - abc.push(def[constructor] === def[constructor].prototype.constructor); - } - def = [Array, Boolean, Date, Function, Number, Object, RegExp, String, SyntaxError]; - for (constructor in def) { - abc.push(def[constructor] === def[constructor].prototype.constructor); - } - abc; - `, "true,true,true,true,true,true,true,true,true,true,true,true,true,true,true") - - test(` - [ Array.prototype.constructor === Array, Array.constructor === Function ]; - `, "true,true") - - test(` - [ Number.prototype.constructor === Number, Number.constructor === Function ]; - `, "true,true") - - test(` - [ Function.prototype.constructor === Function, Function.constructor === Function ]; - `, "true,true") - }) -} - -func TestGlobalLength(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ Object.length, Function.length, RegExp.length, Math.length ]; - `, "1,1,2,") - }) -} - -func TestGlobalError(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ TypeError.length, TypeError(), TypeError("Nothing happens.") ]; - `, "1,TypeError,TypeError: Nothing happens.") - - test(` - [ URIError.length, URIError(), URIError("Nothing happens.") ]; - `, "1,URIError,URIError: Nothing happens.") - }) -} - -func TestGlobalReadOnly(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Number.POSITIVE_INFINITY`, math.Inf(1)) - - test(` - Number.POSITIVE_INFINITY = 1; - `, 1) - - test(`Number.POSITIVE_INFINITY`, math.Inf(1)) - - test(` - Number.POSITIVE_INFINITY = 1; - Number.POSITIVE_INFINITY; - `, math.Inf(1)) - }) -} - -func Test_isNaN(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`isNaN(0)`, false) - test(`isNaN("Xyzzy")`, true) - test(`isNaN()`, true) - test(`isNaN(NaN)`, true) - test(`isNaN(Infinity)`, false) - - test(`isNaN.length === 1`, true) - test(`isNaN.prototype === undefined`, true) - }) -} - -func Test_isFinite(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`isFinite(0)`, true) - test(`isFinite("Xyzzy")`, false) - test(`isFinite()`, false) - test(`isFinite(NaN)`, false) - test(`isFinite(Infinity)`, false) - test(`isFinite(new Number(451));`, true) - - test(`isFinite.length === 1`, true) - test(`isFinite.prototype === undefined`, true) - }) -} - -func Test_parseInt(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`parseInt("0")`, 0) - test(`parseInt("11")`, 11) - test(`parseInt(" 11")`, 11) - test(`parseInt("11 ")`, 11) - test(`parseInt(" 11 ")`, 11) - test(`parseInt(" 11\n")`, 11) - test(`parseInt(" 11\n", 16)`, 17) - - test(`parseInt("Xyzzy")`, _NaN) - - test(`parseInt(" 0x11\n", 16)`, 17) - test(`parseInt("0x0aXyzzy", 16)`, 10) - test(`parseInt("0x1", 0)`, 1) - test(`parseInt("0x10000000000000000000", 16)`, float64(75557863725914323419136)) - - test(`parseInt.length === 2`, true) - test(`parseInt.prototype === undefined`, true) - }) -} - -func Test_parseFloat(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`parseFloat("0")`, 0) - test(`parseFloat("11")`, 11) - test(`parseFloat(" 11")`, 11) - test(`parseFloat("11 ")`, 11) - test(`parseFloat(" 11 ")`, 11) - test(`parseFloat(" 11\n")`, 11) - test(`parseFloat(" 11\n", 16)`, 11) - test(`parseFloat("11.1")`, 11.1) - - test(`parseFloat("Xyzzy")`, _NaN) - - test(`parseFloat(" 0x11\n", 16)`, 0) - test(`parseFloat("0x0a")`, 0) - test(`parseFloat("0x0aXyzzy")`, 0) - test(`parseFloat("Infinity")`, _Infinity) - test(`parseFloat("infinity")`, _NaN) - test(`parseFloat("0x")`, 0) - test(`parseFloat("11x")`, 11) - test(`parseFloat("Infinity1")`, _Infinity) - - test(`parseFloat.length === 1`, true) - test(`parseFloat.prototype === undefined`, true) - }) -} - -func Test_encodeURI(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`encodeURI("http://example.com/ Nothing happens.")`, "http://example.com/%20Nothing%20happens.") - test(`encodeURI("http://example.com/ _^#")`, "http://example.com/%20_%5E#") - test(`encodeURI(String.fromCharCode("0xE000"))`, "%EE%80%80") - test(`encodeURI(String.fromCharCode("0xFFFD"))`, "%EF%BF%BD") - test(`raise: encodeURI(String.fromCharCode("0xDC00"))`, "URIError: URI malformed") - - test(`encodeURI.length === 1`, true) - test(`encodeURI.prototype === undefined`, true) - }) -} - -func Test_encodeURIComponent(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`encodeURIComponent("http://example.com/ Nothing happens.")`, "http%3A%2F%2Fexample.com%2F%20Nothing%20happens.") - test(`encodeURIComponent("http://example.com/ _^#")`, "http%3A%2F%2Fexample.com%2F%20_%5E%23") - }) -} - -func Test_decodeURI(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`decodeURI(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") - test(`decodeURI(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") - test(`raise: decodeURI("http://example.com/ _^#%")`, "URIError: URI malformed") - test(`raise: decodeURI("%DF%7F")`, "URIError: URI malformed") - for _, check := range strings.Fields("+ %3B %2F %3F %3A %40 %26 %3D %2B %24 %2C %23") { - test(fmt.Sprintf(`decodeURI("%s")`, check), check) - } - - test(`decodeURI.length === 1`, true) - test(`decodeURI.prototype === undefined`, true) - }) -} - -func Test_decodeURIComponent(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`decodeURIComponent(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") - test(`decodeURIComponent(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") - - test(`decodeURIComponent.length === 1`, true) - test(`decodeURIComponent.prototype === undefined`, true) - - test(` - var global = Function('return this')(); - var abc = Object.getOwnPropertyDescriptor(global, "decodeURIComponent"); - [ abc.value === global.decodeURIComponent, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") - }) -} - -func TestGlobal_skipEnumeration(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var found = []; - for (var test in this) { - if (false || - test === 'NaN' || - test === 'undefined' || - test === 'Infinity' || - false) { - found.push(test) - } - } - found.length; - `, 0) - - test(` - var found = []; - for (var test in this) { - if (false || - test === 'Object' || - test === 'Function' || - test === 'String' || - test === 'Number' || - test === 'Array' || - test === 'Boolean' || - test === 'Date' || - test === 'RegExp' || - test === 'Error' || - test === 'EvalError' || - test === 'RangeError' || - test === 'ReferenceError' || - test === 'SyntaxError' || - test === 'TypeError' || - test === 'URIError' || - false) { - found.push(test) - } - } - found.length; - `, 0) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/json_test.go b/vendor/github.com/robertkrimen/otto/json_test.go deleted file mode 100644 index 4dd2ed7bf6f..00000000000 --- a/vendor/github.com/robertkrimen/otto/json_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package otto - -import ( - "testing" -) - -func BenchmarkJSON_parse(b *testing.B) { - vm := New() - for i := 0; i < b.N; i++ { - vm.Run(`JSON.parse("1")`) - vm.Run(`JSON.parse("[1,2,3]")`) - vm.Run(`JSON.parse('{"a":{"x":100,"y":110},"b":[10,20,30],"c":"zazazaza"}')`) - vm.Run(`JSON.parse("[1,2,3]", function(k, v) { return undefined })`) - } -} - -func TestJSON_parse(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - JSON.parse("1"); - `, 1) - - test(` - JSON.parse("null"); - `, "null") // TODO Can we make this nil? - - test(` - var abc = JSON.parse('"a\uFFFFbc"'); - [ abc[0], abc[2], abc[3], abc.length ]; - `, "a,b,c,4") - - test(` - JSON.parse("[1, 2, 3]"); - `, "1,2,3") - - test(` - JSON.parse('{ "abc": 1, "def":2 }').abc; - `, 1) - - test(` - JSON.parse('{ "abc": { "x": 100, "y": 110 }, "def": [ 10, 20 ,30 ], "ghi": "zazazaza" }').def; - `, "10,20,30") - - test(`raise: - JSON.parse("12\t\r\n 34"); - `, "SyntaxError: invalid character '3' after top-level value") - - test(` - JSON.parse("[1, 2, 3]", function() { return undefined }); - `, "undefined") - - test(`raise: - JSON.parse(""); - `, "SyntaxError: unexpected end of JSON input") - - test(`raise: - JSON.parse("[1, 2, 3"); - `, "SyntaxError: unexpected end of JSON input") - - test(`raise: - JSON.parse("[1, 2, ; abc=10"); - `, "SyntaxError: invalid character ';' looking for beginning of value") - - test(`raise: - JSON.parse("[1, 2, function(){}]"); - `, "SyntaxError: invalid character 'u' in literal false (expecting 'a')") - }) -} - -func TestJSON_stringify(t *testing.T) { - tt(t, func() { - test, _ := test() - - defer mockUTC()() - - test(` - JSON.stringify(function(){}); - `, "undefined") - - test(` - JSON.stringify(new Boolean(false)); - `, "false") - - test(` - JSON.stringify({a1: {b1: [1,2,3,4], b2: {c1: 1, c2: 2}}, a2: 'a2'}, null, -5); - `, `{"a1":{"b1":[1,2,3,4],"b2":{"c1":1,"c2":2}},"a2":"a2"}`) - - test(` - JSON.stringify(undefined); - `, "undefined") - - test(` - JSON.stringify(1); - `, "1") - - test(` - JSON.stringify("abc def"); - `, "\"abc def\"") - - test(` - JSON.stringify(3.14159); - `, "3.14159") - - test(` - JSON.stringify([]); - `, "[]") - - test(` - JSON.stringify([1, 2, 3]); - `, "[1,2,3]") - - test(` - JSON.stringify([true, false, null]); - `, "[true,false,null]") - - test(` - JSON.stringify({ - abc: { x: 100, y: 110 }, - def: [ 10, 20, 30 ], - ghi: "zazazaza" - }); - `, `{"abc":{"x":100,"y":110},"def":[10,20,30],"ghi":"zazazaza"}`) - - test(` - JSON.stringify([ - 'e', - {pluribus: 'unum'} - ], null, '\t'); - `, "[\n\t\"e\",\n\t{\n\t\t\"pluribus\": \"unum\"\n\t}\n]") - - test(` - JSON.stringify(new Date(0)); - `, `"1970-01-01T00:00:00.000Z"`) - - test(` - JSON.stringify([ new Date(0) ], function(key, value){ - return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value - }); - `, `["Date(Thu, 01 Jan 1970 00:00:00 UTC)"]`) - - test(` - JSON.stringify({ - abc: 1, - def: 2, - ghi: 3 - }, ['abc','def']); - `, `{"abc":1,"def":2}`) - - test(`raise: - var abc = { - def: null - }; - abc.def = abc; - JSON.stringify(abc) - `, "TypeError: Converting circular structure to JSON") - - test(`raise: - var abc= [ null ]; - abc[0] = abc; - JSON.stringify(abc); - `, "TypeError: Converting circular structure to JSON") - - test(`raise: - var abc = { - def: {} - }; - abc.def.ghi = abc; - JSON.stringify(abc) - `, "TypeError: Converting circular structure to JSON") - - test(` - var ghi = { "pi": 3.14159 }; - var abc = { - def: {} - }; - abc.ghi = ghi; - abc.def.ghi = ghi; - JSON.stringify(abc); - `, `{"def":{"ghi":{"pi":3.14159}},"ghi":{"pi":3.14159}}`) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/math_test.go b/vendor/github.com/robertkrimen/otto/math_test.go deleted file mode 100644 index 499998b14e5..00000000000 --- a/vendor/github.com/robertkrimen/otto/math_test.go +++ /dev/null @@ -1,303 +0,0 @@ -package otto - -import ( - "math" - "testing" -) - -var _NaN = math.NaN() -var _Infinity = math.Inf(1) - -func TestMath_toString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.toString()`, "[object Math]") - }) -} - -func TestMath_abs(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.abs(NaN)`, _NaN) - test(`Math.abs(2)`, 2) - test(`Math.abs(-2)`, 2) - test(`Math.abs(-Infinity)`, _Infinity) - - test(`Math.acos(0.5)`, 1.0471975511965976) - - test(`Math.abs('-1')`, 1) - test(`Math.abs(-2)`, 2) - test(`Math.abs(null)`, 0) - test(`Math.abs("string")`, _NaN) - test(`Math.abs()`, _NaN) - }) -} - -func TestMath_acos(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.acos(NaN)`, _NaN) - test(`Math.acos(2)`, _NaN) - test(`Math.acos(-2)`, _NaN) - test(`1/Math.acos(1)`, _Infinity) - - test(`Math.acos(0.5)`, 1.0471975511965976) - }) -} - -func TestMath_asin(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.asin(NaN)`, _NaN) - test(`Math.asin(2)`, _NaN) - test(`Math.asin(-2)`, _NaN) - test(`1/Math.asin(0)`, _Infinity) - test(`1/Math.asin(-0)`, -_Infinity) - - test(`Math.asin(0.5)`, 0.5235987755982989) - }) -} - -func TestMath_atan(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.atan(NaN)`, _NaN) - test(`1/Math.atan(0)`, _Infinity) - test(`1/Math.atan(-0)`, -_Infinity) - test(`Math.atan(Infinity)`, 1.5707963267948966) - test(`Math.atan(-Infinity)`, -1.5707963267948966) - - // freebsd/386 1.03 => 0.4636476090008061 - // darwin 1.03 => 0.46364760900080604 - test(`Math.atan(0.5).toPrecision(10)`, "0.463647609") - }) -} - -func TestMath_atan2(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.atan2()`, _NaN) - test(`Math.atan2(NaN)`, _NaN) - test(`Math.atan2(0, NaN)`, _NaN) - - test(`Math.atan2(1, 0)`, 1.5707963267948966) - test(`Math.atan2(1, -0)`, 1.5707963267948966) - - test(`1/Math.atan2(0, 1)`, _Infinity) - test(`1/Math.atan2(0, 0)`, _Infinity) - test(`Math.atan2(0, -0)`, 3.141592653589793) - test(`Math.atan2(0, -1)`, 3.141592653589793) - - test(`1/Math.atan2(-0, 1)`, -_Infinity) - test(`1/Math.atan2(-0, 0)`, -_Infinity) - test(`Math.atan2(-0, -0)`, -3.141592653589793) - test(`Math.atan2(-0, -1)`, -3.141592653589793) - - test(`Math.atan2(-1, 0)`, -1.5707963267948966) - test(`Math.atan2(-1, -0)`, -1.5707963267948966) - - test(`1/Math.atan2(1, Infinity)`, _Infinity) - test(`Math.atan2(1, -Infinity)`, 3.141592653589793) - test(`1/Math.atan2(-1, Infinity)`, -_Infinity) - test(`Math.atan2(-1, -Infinity)`, -3.141592653589793) - - test(`Math.atan2(Infinity, 1)`, 1.5707963267948966) - test(`Math.atan2(-Infinity, 1)`, -1.5707963267948966) - - test(`Math.atan2(Infinity, Infinity)`, 0.7853981633974483) - test(`Math.atan2(Infinity, -Infinity)`, 2.356194490192345) - test(`Math.atan2(-Infinity, Infinity)`, -0.7853981633974483) - test(`Math.atan2(-Infinity, -Infinity)`, -2.356194490192345) - }) -} - -func TestMath_ceil(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.ceil(NaN)`, _NaN) - test(`Math.ceil(+0)`, 0) - test(`1/Math.ceil(-0)`, -_Infinity) - test(`Math.ceil(Infinity)`, _Infinity) - test(`Math.ceil(-Infinity)`, -_Infinity) - test(`1/Math.ceil(-0.5)`, -_Infinity) - - test(`Math.ceil(-11)`, -11) - test(`Math.ceil(-0.5)`, 0) - test(`Math.ceil(1.5)`, 2) - }) -} - -func TestMath_cos(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.cos(NaN)`, _NaN) - test(`Math.cos(+0)`, 1) - test(`Math.cos(-0)`, 1) - test(`Math.cos(Infinity)`, _NaN) - test(`Math.cos(-Infinity)`, _NaN) - - test(`Math.cos(0.5)`, 0.8775825618903728) - }) -} - -func TestMath_exp(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.exp(NaN)`, _NaN) - test(`Math.exp(+0)`, 1) - test(`Math.exp(-0)`, 1) - test(`Math.exp(Infinity)`, _Infinity) - test(`Math.exp(-Infinity)`, 0) - }) -} - -func TestMath_floor(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.floor(NaN)`, _NaN) - test(`Math.floor(+0)`, 0) - test(`1/Math.floor(-0)`, -_Infinity) - test(`Math.floor(Infinity)`, _Infinity) - test(`Math.floor(-Infinity)`, -_Infinity) - - test(`Math.floor(-11)`, -11) - test(`Math.floor(-0.5)`, -1) - test(`Math.floor(1.5)`, 1) - }) -} - -func TestMath_log(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.log(NaN)`, _NaN) - test(`Math.log(-1)`, _NaN) - test(`Math.log(+0)`, -_Infinity) - test(`Math.log(-0)`, -_Infinity) - test(`1/Math.log(1)`, _Infinity) - test(`Math.log(Infinity)`, _Infinity) - - test(`Math.log(0.5)`, -0.6931471805599453) - }) -} - -func TestMath_max(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.max(-11, -1, 0, 1, 2, 3, 11)`, 11) - }) -} - -func TestMath_min(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.min(-11, -1, 0, 1, 2, 3, 11)`, -11) - }) -} - -func TestMath_pow(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.pow(0, NaN)`, _NaN) - test(`Math.pow(0, 0)`, 1) - test(`Math.pow(NaN, 0)`, 1) - test(`Math.pow(0, -0)`, 1) - test(`Math.pow(NaN, -0)`, 1) - test(`Math.pow(NaN, 1)`, _NaN) - test(`Math.pow(2, Infinity)`, _Infinity) - test(`1/Math.pow(2, -Infinity)`, _Infinity) - test(`Math.pow(1, Infinity)`, _NaN) - test(`Math.pow(1, -Infinity)`, _NaN) - test(`1/Math.pow(0.1, Infinity)`, _Infinity) - test(`Math.pow(0.1, -Infinity)`, _Infinity) - test(`Math.pow(Infinity, 1)`, _Infinity) - test(`1/Math.pow(Infinity, -1)`, _Infinity) - test(`Math.pow(-Infinity, 1)`, -_Infinity) - test(`Math.pow(-Infinity, 2)`, _Infinity) - test(`1/Math.pow(-Infinity, -1)`, -_Infinity) - test(`1/Math.pow(-Infinity, -2)`, _Infinity) - test(`1/Math.pow(0, 1)`, _Infinity) - test(`Math.pow(0, -1)`, _Infinity) - test(`1/Math.pow(-0, 1)`, -_Infinity) - test(`1/Math.pow(-0, 2)`, _Infinity) - test(`Math.pow(-0, -1)`, -_Infinity) - test(`Math.pow(-0, -2)`, _Infinity) - test(`Math.pow(-1, 0.1)`, _NaN) - - test(` - [ Math.pow(-1, +Infinity), Math.pow(1, Infinity) ]; - `, "NaN,NaN") - }) -} - -func TestMath_round(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.round(NaN)`, _NaN) - test(`1/Math.round(0)`, _Infinity) - test(`1/Math.round(-0)`, -_Infinity) - test(`Math.round(Infinity)`, _Infinity) - test(`Math.round(-Infinity)`, -_Infinity) - test(`1/Math.round(0.1)`, _Infinity) - test(`1/Math.round(-0.1)`, -_Infinity) - - test(`Math.round(3.5)`, 4) - test(`Math.round(-3.5)`, -3) - }) -} - -func TestMath_sin(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.sin(NaN)`, _NaN) - test(`1/Math.sin(+0)`, _Infinity) - test(`1/Math.sin(-0)`, -_Infinity) - test(`Math.sin(Infinity)`, _NaN) - test(`Math.sin(-Infinity)`, _NaN) - - test(`Math.sin(0.5)`, 0.479425538604203) - }) -} - -func TestMath_sqrt(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.sqrt(NaN)`, _NaN) - test(`Math.sqrt(-1)`, _NaN) - test(`1/Math.sqrt(+0)`, _Infinity) - test(`1/Math.sqrt(-0)`, -_Infinity) - test(`Math.sqrt(Infinity)`, _Infinity) - - test(`Math.sqrt(2)`, 1.4142135623730951) - }) -} - -func TestMath_tan(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Math.tan(NaN)`, _NaN) - test(`1/Math.tan(+0)`, _Infinity) - test(`1/Math.tan(-0)`, -_Infinity) - test(`Math.tan(Infinity)`, _NaN) - test(`Math.tan(-Infinity)`, _NaN) - - test(`Math.tan(0.5)`, 0.5463024898437905) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/native_stack_test.go b/vendor/github.com/robertkrimen/otto/native_stack_test.go deleted file mode 100644 index 649358e6b27..00000000000 --- a/vendor/github.com/robertkrimen/otto/native_stack_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestNativeStackFrames(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.Compile("input.js", ` - function A() { ext1(); } - function B() { ext2(); } - A(); - `) - if err != nil { - panic(err) - } - - vm.Set("ext1", func(c FunctionCall) Value { - if _, err := c.Otto.Eval("B()"); err != nil { - panic(err) - } - - return UndefinedValue() - }) - - vm.Set("ext2", func(c FunctionCall) Value { - { - // no limit, include innermost native frames - ctx := c.Otto.ContextSkip(-1, false) - - is(ctx.Stacktrace, []string{ - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.2 (native_stack_test.go:28)", - "B (input.js:3:22)", - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)", - "A (input.js:2:22)", "input.js:4:7", - }) - - is(ctx.Callee, "github.com/robertkrimen/otto.TestNativeStackFrames.func1.2") - is(ctx.Filename, "native_stack_test.go") - is(ctx.Line, 28) - is(ctx.Column, 0) - } - - { - // no limit, skip innermost native frames - ctx := c.Otto.ContextSkip(-1, true) - - is(ctx.Stacktrace, []string{ - "B (input.js:3:22)", - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)", - "A (input.js:2:22)", "input.js:4:7", - }) - - is(ctx.Callee, "B") - is(ctx.Filename, "input.js") - is(ctx.Line, 3) - is(ctx.Column, 22) - } - - if _, err := c.Otto.Eval("ext3()"); err != nil { - panic(err) - } - - return UndefinedValue() - }) - - vm.Set("ext3", func(c FunctionCall) Value { - { - // no limit, include innermost native frames - ctx := c.Otto.ContextSkip(-1, false) - - is(ctx.Stacktrace, []string{ - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.3 (native_stack_test.go:69)", - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.2 (native_stack_test.go:28)", - "B (input.js:3:22)", - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)", - "A (input.js:2:22)", "input.js:4:7", - }) - - is(ctx.Callee, "github.com/robertkrimen/otto.TestNativeStackFrames.func1.3") - is(ctx.Filename, "native_stack_test.go") - is(ctx.Line, 69) - is(ctx.Column, 0) - } - - { - // no limit, skip innermost native frames - ctx := c.Otto.ContextSkip(-1, true) - - is(ctx.Stacktrace, []string{ - "B (input.js:3:22)", - "github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)", - "A (input.js:2:22)", "input.js:4:7", - }) - - is(ctx.Callee, "B") - is(ctx.Filename, "input.js") - is(ctx.Line, 3) - is(ctx.Column, 22) - } - - return UndefinedValue() - }) - - if _, err := vm.Run(s); err != nil { - panic(err) - } - }) -} diff --git a/vendor/github.com/robertkrimen/otto/number_test.go b/vendor/github.com/robertkrimen/otto/number_test.go deleted file mode 100644 index 070cf157ac4..00000000000 --- a/vendor/github.com/robertkrimen/otto/number_test.go +++ /dev/null @@ -1,165 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestNumber(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = Object.getOwnPropertyDescriptor(Number, "prototype"); - [ [ typeof Number.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") - }) -} - -func TestNumber_toString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - new Number(451).toString(); - `, "451") - - test(` - new Number(451).toString(10); - `, "451") - - test(` - new Number(451).toString(8); - `, "703") - - test(`raise: - new Number(451).toString(1); - `, "RangeError: toString() radix must be between 2 and 36") - - test(`raise: - new Number(451).toString(Infinity); - `, "RangeError: toString() radix must be between 2 and 36") - - test(` - new Number(NaN).toString() - `, "NaN") - - test(` - new Number(Infinity).toString() - `, "Infinity") - - test(` - new Number(Infinity).toString(16) - `, "Infinity") - - test(` - [ - Number.prototype.toString(undefined), - new Number().toString(undefined), - new Number(0).toString(undefined), - new Number(-1).toString(undefined), - new Number(1).toString(undefined), - new Number(Number.NaN).toString(undefined), - new Number(Number.POSITIVE_INFINITY).toString(undefined), - new Number(Number.NEGATIVE_INFINITY).toString(undefined) - ] - `, "0,0,0,-1,1,NaN,Infinity,-Infinity") - }) -} - -func TestNumber_toFixed(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`new Number(451).toFixed(2)`, "451.00") - test(`12345.6789.toFixed()`, "12346") - test(`12345.6789.toFixed(1)`, "12345.7") - test(`12345.6789.toFixed(6)`, "12345.678900") - test(`(1.23e-20).toFixed(2)`, "0.00") - test(`2.34.toFixed(1)`, "2.3") // FIXME Wtf? "2.3" - test(`-2.34.toFixed(1)`, -2.3) // FIXME Wtf? -2.3 - test(`(-2.34).toFixed(1)`, "-2.3") - - test(`raise: - new Number("a").toFixed(Number.POSITIVE_INFINITY); - `, "RangeError: toFixed() precision must be between 0 and 20") - - test(` - [ - new Number(1e21).toFixed(), - new Number(1e21).toFixed(0), - new Number(1e21).toFixed(1), - new Number(1e21).toFixed(1.1), - new Number(1e21).toFixed(0.9), - new Number(1e21).toFixed("1"), - new Number(1e21).toFixed("1.1"), - new Number(1e21).toFixed("0.9"), - new Number(1e21).toFixed(Number.NaN), - new Number(1e21).toFixed("some string") - ]; - `, "1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21") - - test(`raise: - new Number(1e21).toFixed(Number.POSITIVE_INFINITY); - `, "RangeError: toFixed() precision must be between 0 and 20") - }) -} - -func TestNumber_toExponential(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`new Number(451).toExponential(2)`, "4.51e+02") - test(`77.1234.toExponential()`, "7.71234e+01") - test(`77.1234.toExponential(4)`, "7.7123e+01") - test(`77.1234.toExponential(2)`, "7.71e+01") - test(`77 .toExponential()`, "7.7e+01") - }) -} - -func TestNumber_toPrecision(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`new Number(451).toPrecision()`, "451") - test(`new Number(451).toPrecision(1)`, "5e+02") - test(`5.123456.toPrecision()`, "5.123456") - test(`5.123456.toPrecision(5)`, "5.1235") - test(`5.123456.toPrecision(2)`, "5.1") - test(`5.123456.toPrecision(1)`, "5") - }) -} - -func TestNumber_toLocaleString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ - new Number(451).toLocaleString(), - new Number(451).toLocaleString(10), - new Number(451).toLocaleString(8) - ]; - `, "451,451,703") - }) -} - -func TestValue_number(t *testing.T) { - tt(t, func() { - nm := toValue(0.0).number() - is(nm.kind, numberInteger) - - nm = toValue(3.14159).number() - is(nm.kind, numberFloat) - }) -} - -func Test_NaN(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ NaN === NaN, NaN == NaN ]; - `, "false,false") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/object_test.go b/vendor/github.com/robertkrimen/otto/object_test.go deleted file mode 100644 index d1e90680bdc..00000000000 --- a/vendor/github.com/robertkrimen/otto/object_test.go +++ /dev/null @@ -1,639 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestObject_(t *testing.T) { - tt(t, func() { - test, _ := test() - - object := newObject(nil, "") - is(object != nil, true) - - object.put("xyzzy", toValue("Nothing happens."), true) - is(object.get("xyzzy"), "Nothing happens.") - - test(` - var abc = Object.getOwnPropertyDescriptor(Object, "prototype"); - [ [ typeof Object.prototype, abc.writable, abc.enumerable, abc.configurable ], - ]; - `, "object,false,false,false") - }) -} - -func TestStringObject(t *testing.T) { - tt(t, func() { - object := New().runtime.newStringObject(toValue("xyzzy")) - is(object.get("1"), "y") - is(object.get("10"), "undefined") - is(object.get("2"), "z") - }) -} - -func TestObject_getPrototypeOf(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = {}; - def = Object.getPrototypeOf(abc); - ghi = Object.getPrototypeOf(def); - [abc,def,ghi,ghi+""]; - `, "[object Object],[object Object],,null") - - test(` - abc = Object.getOwnPropertyDescriptor(Object, "getPrototypeOf"); - [ abc.value === Object.getPrototypeOf, abc.writable, abc.enumerable, abc.configurable ]; - `, "true,true,false,true") - }) -} - -func TestObject_new(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ new Object("abc"), new Object(2+2) ]; - `, "abc,4") - }) -} - -func TestObject_create(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: Object.create()`, "TypeError") - - test(` - var abc = Object.create(null) - var def = Object.create({x: 10, y: 20}) - var ghi = Object.create(Object.prototype) - - var jkl = Object.create({x: 10, y: 20}, { - z: { - value: 30, - writable: true - }, - // sum: { - // get: function() { - // return this.x + this.y + this.z - // } - // } - }); - [ abc.prototype, def.x, def.y, ghi, jkl.x, jkl.y, jkl.z ] - `, ",10,20,[object Object],10,20,30") - - test(` - var properties = {}; - Object.defineProperty(properties, "abc", { - value: {}, - enumerable: false - }); - var mno = Object.create({}, properties); - mno.hasOwnProperty("abc"); - `, false) - }) -} - -func TestObject_toLocaleString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - ({}).toLocaleString(); - `, "[object Object]") - - test(` - object = { - toString: function() { - return "Nothing happens."; - } - }; - object.toLocaleString(); - `, "Nothing happens.") - }) -} - -func TestObject_isExtensible(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - Object.isExtensible(); - `, "TypeError") - - // FIXME terst, Why raise? - test(`raise: - Object.isExtensible({}); - `, true) - - test(`Object.isExtensible.length`, 1) - test(`Object.isExtensible.prototype`, "undefined") - }) -} - -func TestObject_preventExtensions(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - Object.preventExtensions() - `, "TypeError") - - test(`raise: - var abc = { def: true }; - var ghi = Object.preventExtensions(abc); - [ ghi.def === true, Object.isExtensible(abc), Object.isExtensible(ghi) ]; - `, "true,false,false") - - test(` - var abc = new String(); - var def = Object.isExtensible(abc); - Object.preventExtensions(abc); - var ghi = false; - try { - Object.defineProperty(abc, "0", { value: "~" }); - } catch (err) { - ghi = err instanceof TypeError; - } - [ def, ghi, abc.hasOwnProperty("0"), typeof abc[0] ]; - `, "true,true,false,undefined") - - test(`Object.preventExtensions.length`, 1) - test(`Object.preventExtensions.prototype`, "undefined") - }) -} - -func TestObject_isSealed(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Object.isSealed.length`, 1) - test(`Object.isSealed.prototype`, "undefined") - }) -} - -func TestObject_seal(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: Object.seal()`, "TypeError") - - test(` - var abc = {a:1,b:1,c:3}; - var sealed = Object.isSealed(abc); - Object.seal(abc); - [sealed, Object.isSealed(abc)]; - `, "false,true") - - test(` - var abc = {a:1,b:1,c:3}; - var sealed = Object.isSealed(abc); - var caught = false; - Object.seal(abc); - abc.b = 5; - Object.defineProperty(abc, "a", {value:4}); - try { - Object.defineProperty(abc, "a", {value:42,enumerable:false}); - } catch (e) { - caught = e instanceof TypeError; - } - [sealed, Object.isSealed(abc), caught, abc.a, abc.b]; - `, "false,true,true,4,5") - - test(`Object.seal.length`, 1) - test(`Object.seal.prototype`, "undefined") - }) -} - -func TestObject_isFrozen(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: Object.isFrozen()`, "TypeError") - test(`Object.isFrozen(Object.preventExtensions({a:1}))`, false) - test(`Object.isFrozen({})`, false) - - test(` - var abc = {}; - Object.defineProperty(abc, "def", { - value: "def", - writable: true, - configurable: false - }); - Object.preventExtensions(abc); - !Object.isFrozen(abc); - `, true) - - test(`Object.isFrozen.length`, 1) - test(`Object.isFrozen.prototype`, "undefined") - }) -} - -func TestObject_freeze(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: Object.freeze()`, "TypeError") - - test(` - var abc = {a:1,b:2,c:3}; - var frozen = Object.isFrozen(abc); - Object.freeze(abc); - abc.b = 5; - [frozen, Object.isFrozen(abc), abc.b]; - `, "false,true,2") - - test(` - var abc = {a:1,b:2,c:3}; - var frozen = Object.isFrozen(abc); - var caught = false; - Object.freeze(abc); - abc.b = 5; - try { - Object.defineProperty(abc, "a", {value:4}); - } catch (e) { - caught = e instanceof TypeError; - } - [frozen, Object.isFrozen(abc), caught, abc.a, abc.b]; - `, "false,true,true,1,2") - - test(`Object.freeze.length`, 1) - test(`Object.freeze.prototype`, "undefined") - }) -} - -func TestObject_defineProperty(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - (function(abc, def, ghi){ - Object.defineProperty(arguments, "0", { - enumerable: false - }); - return true; - })(0, 1, 2); - `, true) - - test(` - var abc = {}; - abc.def = 3.14; // Default: writable: true, enumerable: true, configurable: true - - Object.defineProperty(abc, "def", { - value: 42 - }); - - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ ghi.value, ghi.writable, ghi.enumerable, ghi.configurable ]; - `, "42,true,true,true") - - // Test that we handle the case of DefineOwnProperty - // where [[Writable]] is something but [[Value]] is not - test(` - var abc = []; - Object.defineProperty(abc, "0", { writable: false }); - 0 in abc; - `, true) - - // Test that we handle the case of DefineOwnProperty - // where [[Writable]] is something but [[Value]] is not - // (and the property originally had something for [[Value]] - test(` - abc = { - def: 42 - }; - Object.defineProperty(abc, "def", { writable: false }); - abc.def; - `, 42) - }) -} - -func TestObject_keys(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Object.keys({ abc:undefined, def:undefined })`, "abc,def") - - test(` - function abc() { - this.abc = undefined; - this.def = undefined; - } - Object.keys(new abc()) - `, "abc,def") - - test(` - function def() { - this.ghi = undefined; - } - def.prototype = new abc(); - Object.keys(new def()); - `, "ghi") - - test(` - var ghi = Object.create( - { - abc: undefined, - def: undefined - }, - { - ghi: { value: undefined, enumerable: true }, - jkl: { value: undefined, enumerable: false } - } - ); - Object.keys(ghi); - `, "ghi") - - test(` - (function(abc, def, ghi){ - return Object.keys(arguments) - })(undefined, undefined); - `, "0,1") - - test(` - (function(abc, def, ghi){ - return Object.keys(arguments) - })(undefined, undefined, undefined, undefined); - `, "0,1,2,3") - }) -} - -func TestObject_getOwnPropertyNames(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`Object.getOwnPropertyNames({ abc:undefined, def:undefined })`, "abc,def") - - test(` - var ghi = Object.create( - { - abc: undefined, - def: undefined - }, - { - ghi: { value: undefined, enumerable: true }, - jkl: { value: undefined, enumerable: false } - } - ); - Object.getOwnPropertyNames(ghi) - `, "ghi,jkl") - }) -} - -func TestObjectGetterSetter(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - Object.create({}, { - abc: { - get: function(){ - return "true"; - }, - writable: true - } - }).abc; - `, "TypeError") - - test(`raise: - Object.create({}, { - abc: { - get: function(){ - return "true"; - }, - writable: false - } - }).abc; - `, "TypeError") - - test(` - Object.create({}, { - abc: { - get: function(){ - return "true"; - } - } - }).abc; - `, "true") - - test(` - Object.create({xyz:true},{abc:{get:function(){return this.xyx}}}).abc; - Object.create({ - xyz: true - }, { - abc: { - get: function(){ - return this.xyz; - } - } - }).abc; - `, true) - - test(` - var abc = false; - var def = Object.create({}, { - xyz: { - set: function(value) { - abc = value; - } - } - }); - def.xyz = true; - [ abc ]; - `, "true") - - test(` - var abc = {}; - Object.defineProperty(abc, "def", { - value: "xyzzy", - configurable: true - }); - Object.preventExtensions(abc); - Object.defineProperty(abc, "def", { - get: function() { - return 5; - } - }); - var def = Object.getOwnPropertyDescriptor(abc, "def"); - [ abc.def, typeof def.get, typeof def.set, typeof def.value, def.configurable, def.enumerable, typeof def.writable ]; - `, "5,function,undefined,undefined,true,false,undefined") - - test(` - var abc = {}; - Object.defineProperty(abc, "def", { - get: function() { - return 5; - } - configurable: true - }); - Object.preventExtensions(abc); - Object.defineProperty(abc, "def", { - value: "xyzzy", - }); - var def = Object.getOwnPropertyDescriptor(abc, "def"); - [ abc.def, typeof def.get, typeof def.set, def.value, def.configurable, def.enumerable, def.writable ]; - `, "xyzzy,undefined,undefined,xyzzy,true,false,false") - - test(` - var abc = {}; - - function _get0() { - return 10; - } - - function _set(value) { - abc.def = value; - } - - Object.defineProperty(abc, "ghi", { - get: _get0, - set: _set, - configurable: true - }); - - function _get1() { - return 20; - } - - Object.defineProperty(abc, "ghi", { - get: _get0 - }); - - var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi"); - [ typeof descriptor.set ]; - `, "function") - - test(`raise: - var abc = []; - Object.defineProperty(abc, "length", { - get: function () { - return 2; - } - }); - `, "TypeError") - - test(` - var abc = {}; - - var getter = function() { - return 1; - } - - Object.defineProperty(abc, "def", { - get: getter, - configurable: false - }); - - var jkl = undefined; - try { - Object.defineProperty(abc, "def", { - get: undefined - }); - } - catch (err) { - jkl = err; - } - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ jkl instanceof TypeError, ghi.get === getter, ghi.configurable, ghi.enumerable ]; - `, "true,true,false,false") - - test(` - var abc = {}; - - var getter = function() { - return 1; - }; - - Object.defineProperty(abc, "def", { - get: getter - }); - - Object.defineProperty(abc, "def", { - set: undefined - }); - - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ ghi.get === getter, ghi.set === undefined, ghi.configurable, ghi.enumerable ]; - `, "true,true,false,false") - - test(` - var abc = {}; - - var getter = function() { - return 1; - }; - - Object.defineProperty(abc, "def", { - get: getter - }); - - var jkl = undefined; - try { - Object.defineProperty(abc, "def", { - set: function() {} - }); - } - catch (err) { - jkl = err; - } - - var ghi = Object.getOwnPropertyDescriptor(abc, "def"); - [ jkl instanceof TypeError, ghi.get === getter, ghi.set, ghi.configurable, ghi.enumerable ]; - `, "true,true,,false,false") - - test(` - var abc = {}; - var def = "xyzzy"; - - Object.defineProperty(abc, "ghi", { - get: undefined, - set: function(value) { - def = value; - }, - enumerable: true, - configurable: true - }); - - var hasOwn = abc.hasOwnProperty("ghi"); - var descriptor = Object.getOwnPropertyDescriptor(abc, "ghi"); - - [ hasOwn, typeof descriptor.get ]; - `, "true,undefined") - - test(` - var abc = "xyzzy"; - Object.defineProperty(Array.prototype, "abc", { - get: function () { - return abc; - }, - set: function (value) { - abc = value; - }, - enumerable: true, - configurable: true - }); - var def = []; - def.abc = 3.14159; - [ def.hasOwnProperty("abc"), def.abc, abc ]; - `, "false,3.14159,3.14159") - }) -} - -func TestProperty(t *testing.T) { - tt(t, func() { - property := _property{} - property.writeOn() - is(property.writeSet(), true) - - property.writeClear() - is(property.writeSet(), false) - - property.writeOff() - is(property.writeSet(), true) - - property.writeClear() - is(property.writeSet(), false) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/otto.go b/vendor/github.com/robertkrimen/otto/otto.go index 7d90658515a..b5b528d53b5 100644 --- a/vendor/github.com/robertkrimen/otto/otto.go +++ b/vendor/github.com/robertkrimen/otto/otto.go @@ -132,6 +132,7 @@ The following are some limitations with otto: * "use strict" will parse, but does nothing. * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. + * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. Regular Expression Incompatibility diff --git a/vendor/github.com/robertkrimen/otto/otto/Makefile b/vendor/github.com/robertkrimen/otto/otto/Makefile deleted file mode 100644 index bac5cd4a55d..00000000000 --- a/vendor/github.com/robertkrimen/otto/otto/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -.PHONY: build - -build: - go build -a - -gxc build-darwin-386 -a diff --git a/vendor/github.com/robertkrimen/otto/otto/main.go b/vendor/github.com/robertkrimen/otto/otto/main.go deleted file mode 100644 index f379e42a92b..00000000000 --- a/vendor/github.com/robertkrimen/otto/otto/main.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "os" - - "github.com/robertkrimen/otto" - "github.com/robertkrimen/otto/underscore" -) - -var flag_underscore *bool = flag.Bool("underscore", true, "Load underscore into the runtime environment") - -func readSource(filename string) ([]byte, error) { - if filename == "" || filename == "-" { - return ioutil.ReadAll(os.Stdin) - } - return ioutil.ReadFile(filename) -} - -func main() { - flag.Parse() - - if !*flag_underscore { - underscore.Disable() - } - - err := func() error { - src, err := readSource(flag.Arg(0)) - if err != nil { - return err - } - - vm := otto.New() - _, err = vm.Run(src) - return err - }() - if err != nil { - switch err := err.(type) { - case *otto.Error: - fmt.Print(err.String()) - default: - fmt.Println(err) - } - os.Exit(64) - } -} diff --git a/vendor/github.com/robertkrimen/otto/otto_error_test.go b/vendor/github.com/robertkrimen/otto/otto_error_test.go deleted file mode 100644 index 5ce358819a1..00000000000 --- a/vendor/github.com/robertkrimen/otto/otto_error_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestOttoError(t *testing.T) { - tt(t, func() { - vm := New() - - _, err := vm.Run(`throw "Xyzzy"`) - is(err, "Xyzzy") - - _, err = vm.Run(`throw new TypeError()`) - is(err, "TypeError") - - _, err = vm.Run(`throw new TypeError("Nothing happens.")`) - is(err, "TypeError: Nothing happens.") - - _, err = ToValue([]byte{}) - is(err, "TypeError: invalid value (slice): missing runtime: [] ([]uint8)") - - _, err = vm.Run(` - (function(){ - return abcdef.length - })() - `) - is(err, "ReferenceError: 'abcdef' is not defined") - - _, err = vm.Run(` - function start() { - } - - start() - - xyzzy() - `) - is(err, "ReferenceError: 'xyzzy' is not defined") - - _, err = vm.Run(` - // Just a comment - - xyzzy - `) - is(err, "ReferenceError: 'xyzzy' is not defined") - - }) -} diff --git a/vendor/github.com/robertkrimen/otto/otto_test.go b/vendor/github.com/robertkrimen/otto/otto_test.go deleted file mode 100644 index ad70a75768c..00000000000 --- a/vendor/github.com/robertkrimen/otto/otto_test.go +++ /dev/null @@ -1,1749 +0,0 @@ -package otto - -import ( - "bytes" - "io" - "testing" - - "github.com/robertkrimen/otto/parser" -) - -func TestOtto(t *testing.T) { - tt(t, func() { - test, _ := test() - - test("xyzzy = 2", 2) - - test("xyzzy + 2", 4) - - test("xyzzy += 16", 18) - - test("xyzzy", 18) - - test(` - (function(){ - return 1 - })() - `, 1) - - test(` - (function(){ - return 1 - }).call(this) - `, 1) - - test(` - (function(){ - var result - (function(){ - result = -1 - })() - return result - })() - `, -1) - - test(` - var abc = 1 - abc || (abc = -1) - abc - `, 1) - - test(` - var abc = (function(){ 1 === 1 })(); - abc; - `, "undefined") - }) -} - -func TestFunction__(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - function abc() { - return 1; - }; - abc(); - `, 1) - }) -} - -func TestIf(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = undefined; - def = undefined; - if (true) abc = 1 - else abc = 2; - if (false) { - def = 3; - } - else def = 4; - - [ abc, def ]; - `, "1,4") - - test(` - if (1) { - abc = 1; - } - else { - abc = 0; - } - abc; - `, 1) - - test(` - if (0) { - abc = 1; - } - else { - abc = 0; - } - abc; - `, 0) - - test(` - abc = 0; - if (0) { - abc = 1; - } - abc; - `, 0) - - test(` - abc = 0; - if (abc) { - abc = 1; - } - abc; - `, 0) - }) -} - -func TestSequence(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - 1, 2, 3; - `, 3) - }) -} - -func TestCall(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - Math.pow(3, 2); - `, 9) - }) -} - -func TestRunFunctionWithSetArguments(t *testing.T) { - tt(t, func() { - vm := New() - vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`) - record := map[string]interface{}{"foo": "bar", "answer": 42} - // Set performs a conversion that allows the map to be addressed as a Javascript object - vm.Set("argument", record) - _, err := vm.Run("sillyFunction(argument)") - - is(err, nil) - is(record["answer"].(float64), -42) - is(record["silly"].(bool), true) - }) -} - -func TestRunFunctionWithArgumentsPassedToCall(t *testing.T) { - tt(t, func() { - vm := New() - vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`) - record := map[string]interface{}{"foo": "bar", "answer": 42} - _, err := vm.Call("sillyFunction", nil, record) - - is(err, nil) - is(record["answer"].(float64), -42) - is(record["silly"].(bool), true) - }) -} - -func TestMember(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = [ 0, 1, 2 ]; - def = { - "abc": 0, - "def": 1, - "ghi": 2, - }; - [ abc[2], def.abc, abc[1], def.def ]; - `, "2,0,1,1") - }) -} - -func Test_this(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - typeof this; - `, "object") - }) -} - -func TestWhile(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - limit = 4 - abc = 0 - while (limit) { - abc = abc + 1 - limit = limit - 1 - } - abc; - `, 4) - }) -} - -func TestSwitch_break(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = true; - var ghi = "Xyzzy"; - while (abc) { - switch ('def') { - case 'def': - break; - } - ghi = "Nothing happens."; - abc = false; - } - ghi; - `, "Nothing happens.") - - test(` - var abc = true; - var ghi = "Xyzzy"; - WHILE: - while (abc) { - switch ('def') { - case 'def': - break WHILE; - } - ghi = "Nothing happens." - abc = false - } - ghi; - `, "Xyzzy") - - test(` - var ghi = "Xyzzy"; - FOR: - for (;;) { - switch ('def') { - case 'def': - break FOR; - ghi = ""; - } - ghi = "Nothing happens."; - } - ghi; - `, "Xyzzy") - - test(` - var ghi = "Xyzzy"; - FOR: - for (var jkl in {}) { - switch ('def') { - case 'def': - break FOR; - ghi = "Something happens."; - } - ghi = "Nothing happens."; - } - ghi; - `, "Xyzzy") - - test(` - var ghi = "Xyzzy"; - function jkl() { - switch ('def') { - case 'def': - break; - ghi = ""; - } - ghi = "Nothing happens."; - } - while (abc) { - jkl(); - abc = false; - ghi = "Something happens."; - } - ghi; - `, "Something happens.") - }) -} - -func TestTryFinally(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc; - try { - abc = 1; - } - finally { - abc = 2; - } - abc; - `, 2) - - test(` - var abc = false, def = 0; - do { - def += 1; - if (def > 100) { - break; - } - try { - continue; - } - finally { - abc = true; - } - } - while(!abc && def < 10) - def; - `, 1) - - test(` - var abc = false, def = 0, ghi = 0; - do { - def += 1; - if (def > 100) { - break; - } - try { - throw 0; - } - catch (jkl) { - continue; - } - finally { - abc = true; - ghi = 11; - } - ghi -= 1; - } - while(!abc && def < 10) - ghi; - `, 11) - - test(` - var abc = 0, def = 0; - do { - try { - abc += 1; - throw "ghi"; - } - finally { - def = 1; - continue; - } - def -= 1; - } - while (abc < 2) - [ abc, def ]; - `, "2,1") - }) -} - -func TestTryCatch(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 1; - try { - throw 4; - abc = -1; - } - catch (xyzzy) { - abc += xyzzy + 1; - } - abc; - `, 6) - - test(` - abc = 1; - var def; - try { - try { - throw 4; - abc = -1; - } - catch (xyzzy) { - abc += xyzzy + 1; - throw 64; - } - } - catch (xyzzy) { - def = xyzzy; - abc = -2; - } - [ def, abc ]; - `, "64,-2") - }) -} - -func TestWith(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var def; - with({ abc: 9 }) { - def = abc; - } - def; - `, 9) - - test(` - var def; - with({ abc: function(){ - return 11; - } }) { - def = abc(); - } - def; - `, 11) - }) -} - -func TestSwitch(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 0; - switch (0) { - default: - abc += 1; - case 1: - abc += 2; - case 2: - abc += 4; - case 3: - abc += 8; - } - abc; - `, 15) - - test(` - abc = 0; - switch (3) { - default: - abc += 1; - case 1: - abc += 2; - case 2: - abc += 4; - case 3: - abc += 8; - } - abc; - `, 8) - - test(` - abc = 0; - switch (60) { - case 1: - abc += 2; - case 2: - abc += 4; - case 3: - abc += 8; - } - abc; - `, 0) - }) -} - -func TestForIn(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc; - for (property in { a: 1 }) { - abc = property; - } - abc; - `, "a") - - test(` - var ghi; - for (property in new String("xyzzy")) { - ghi = property; - } - ghi; - `, "4") - }) -} - -func TestFor(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 7; - for (i = 0; i < 3; i += 1) { - abc += 1; - } - abc; - `, 10) - - test(` - abc = 7; - for (i = 0; i < 3; i += 1) { - abc += 1; - if (i == 1) { - break; - } - } - abc; - `, 9) - - test(` - abc = 7; - for (i = 0; i < 3; i += 1) { - if (i == 2) { - continue; - } - abc += 1; - } - abc; - `, 9) - - test(` - abc = 0; - for (;;) { - abc += 1; - if (abc == 3) - break; - } - abc; - `, 3) - - test(` - for (abc = 0; ;) { - abc += 1; - if (abc == 3) - break; - } - abc; - `, 3) - - test(` - for (abc = 0; ; abc += 1) { - abc += 1; - if (abc == 3) - break; - } - abc; - `, 3) - }) -} - -func TestLabelled(t *testing.T) { - tt(t, func() { - test, _ := test() - - // TODO Add emergency break - - test(` - xyzzy: for (var abc = 0; abc <= 0; abc++) { - for (var def = 0; def <= 1; def++) { - if (def === 0) { - continue xyzzy; - } else { - } - } - } - `) - - test(` - abc = 0 - def: - while (true) { - while (true) { - abc = abc + 1 - if (abc > 11) { - break def; - } - } - } - abc; - `, 12) - - test(` - abc = 0 - def: - do { - do { - abc = abc + 1 - if (abc > 11) { - break def; - } - } while (true) - } while (true) - abc; - `, 12) - }) -} - -func TestConditional(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ true ? false : true, true ? 1 : 0, false ? 3.14159 : "abc" ]; - `, "false,1,abc") - }) -} - -func TestArrayLiteral(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ 1, , 3.14159 ]; - `, "1,,3.14159") - }) -} - -func TestAssignment(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 1; - abc; - `, 1) - - test(` - abc += 2; - abc; - `, 3) - }) -} - -func TestBinaryOperation(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`0 == 1`, false) - test(`1 == "1"`, true) - test(`0 === 1`, false) - test(`1 === "1"`, false) - test(`"1" === "1"`, true) - }) -} - -func Test_typeof(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`typeof abc`, "undefined") - test(`typeof abc === 'undefined'`, true) - test(`typeof {}`, "object") - test(`typeof null`, "object") - }) -} - -func Test_PrimitiveValueObjectValue(t *testing.T) { - tt(t, func() { - test, _ := test() - - Number11 := test(`new Number(11)`) - is(Number11.float64(), 11) - }) -} - -func Test_eval(t *testing.T) { - tt(t, func() { - test, _ := test() - - // FIXME terst, Is this correct? - test(` - var abc = 1; - `, "undefined") - - test(` - eval("abc += 1"); - `, 2) - - test(` - (function(){ - var abc = 11; - eval("abc += 1"); - return abc; - })(); - `, 12) - test(`abc`, 2) - - test(` - (function(){ - try { - eval("var prop = \\u2029;"); - return false; - } catch (abc) { - return [ abc instanceof SyntaxError, abc.toString() ]; - } - })(); - `, "true,SyntaxError: Unexpected token ILLEGAL") - - test(` - function abc(){ - this.THIS = eval("this"); - } - var def = new abc(); - def === def.THIS; - `, true) - }) -} - -func Test_evalDirectIndirect(t *testing.T) { - tt(t, func() { - test, _ := test() - - // (function () {return this;}()).abc = "global"; - test(` - var abc = "global"; - (function(){ - try { - var _eval = eval; - var abc = "function"; - return [ - _eval("\'global\' === abc"), // eval (Indirect) - eval("\'function\' === abc"), // eval (Direct) - ]; - } finally { - delete this.abc; - } - })(); - `, "true,true") - }) -} - -func TestError_URIError(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`new URIError() instanceof URIError`, true) - - test(` - var abc - try { - decodeURI("http://example.com/ _^#%") - } - catch (def) { - abc = def instanceof URIError - } - abc - `, true) - }) -} - -func TestTo(t *testing.T) { - tt(t, func() { - test, _ := test() - - { - value, _ := test(`"11"`).ToFloat() - is(value, float64(11)) - } - - { - value, _ := test(`"11"`).ToInteger() - is(value, int64(11)) - - value, _ = test(`1.1`).ToInteger() - is(value, int64(1)) - } - }) -} - -func TestShouldError(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`raise: - xyzzy - throw new TypeError("Nothing happens.") - `, "ReferenceError: 'xyzzy' is not defined") - }) -} - -func TestAPI(t *testing.T) { - tt(t, func() { - test, vm := test() - - test(` - String.prototype.xyzzy = function(){ - return this.length + 11 + (arguments[0] || 0) - } - abc = new String("xyzzy") - def = "Nothing happens." - abc.xyzzy() - `, 16) - abc, _ := vm.Get("abc") - def, _ := vm.Get("def") - object := abc.Object() - result, _ := object.Call("xyzzy") - is(result, 16) - result, _ = object.Call("xyzzy", 1) - is(result, 17) - value, _ := object.Get("xyzzy") - result, _ = value.Call(def) - is(result, 27) - result, _ = value.Call(def, 3) - is(result, 30) - object = value.Object() // Object xyzzy - result, _ = object.Value().Call(def, 3) - is(result, 30) - - test(` - abc = { - 'abc': 1, - 'def': false, - 3.14159: NaN, - }; - abc['abc']; - `, 1) - abc, err := vm.Get("abc") - is(err, nil) - object = abc.Object() // Object abc - value, err = object.Get("abc") - is(err, nil) - is(value, 1) - is(object.Keys(), []string{"abc", "def", "3.14159"}) - - test(` - abc = [ 0, 1, 2, 3.14159, "abc", , ]; - abc.def = true; - `) - abc, err = vm.Get("abc") - is(err, nil) - object = abc.Object() // Object abc - is(object.Keys(), []string{"0", "1", "2", "3", "4", "def"}) - }) -} - -func TestObjectKeys(t *testing.T) { - tt(t, func() { - vm := New() - vm.Eval(`var x = Object.create(null); x.a = 1`) - vm.Eval(`var y = Object.create(x); y.b = 2`) - - o1, _ := vm.Object("x") - is(o1.Keys(), []string{"a"}) - is(o1.KeysByParent(), [][]string{{"a"}}) - - o2, _ := vm.Object("y") - is(o2.Keys(), []string{"b"}) - is(o2.KeysByParent(), [][]string{{"b"}, {"a"}}) - }) -} - -func TestUnicode(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`var abc = eval("\"a\uFFFFa\"");`, "undefined") - - test(`abc.length`, 3) - - test(`abc != "aa"`, true) - - test("abc[1] === \"\uFFFF\"", true) - }) -} - -func TestDotMember(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = { - ghi: 11, - } - abc.def = "Xyzzy" - abc.null = "Nothing happens." - `) - test(`abc.def`, "Xyzzy") - test(`abc.null`, "Nothing happens.") - test(`abc.ghi`, 11) - - test(` - abc = { - null: 11, - } - `) - test(`abc.def`, "undefined") - test(`abc.null`, 11) - test(`abc.ghi`, "undefined") - }) -} - -func Test_stringToFloat(t *testing.T) { - tt(t, func() { - - is(parseNumber("10e10000"), _Infinity) - is(parseNumber("10e10_."), _NaN) - }) -} - -func Test_delete(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - delete 42; - `, true) - - test(` - var abc = delete $_undefined_$; - abc = abc && delete ($_undefined_$); - abc; - `, true) - - // delete should not trigger get() - test(` - var abc = { - get def() { - throw "Test_delete: delete should not trigger get()" - } - }; - delete abc.def - `, true) - }) -} - -func TestObject_defineOwnProperty(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var object = {}; - - var descriptor = new Boolean(false); - descriptor.configurable = true; - - Object.defineProperties(object, { - property: descriptor - }); - - var abc = object.hasOwnProperty("property"); - delete object.property; - var def = object.hasOwnProperty("property"); - - [ abc, def ]; - `, "true,false") - - test(` - var object = [0, 1, 2]; - Object.defineProperty(object, "0", { - value: 42, - writable: false, - enumerable: false, - configurable: false - }); - var abc = Object.getOwnPropertyDescriptor(object, "0"); - [ abc.value, abc.writable, abc.enumerable, abc.configurable ]; - `, "42,false,false,false") - - test(` - var abc = { "xyzzy": 42 }; - var def = Object.defineProperties(abc, ""); - abc === def; - `, true) - }) -} - -func Test_assignmentEvaluationOrder(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 0; - ((abc = 1) & abc); - `, 1) - - test(` - var abc = 0; - (abc & (abc = 1)); - `, 0) - }) -} - -func TestOttoCall(t *testing.T) { - tt(t, func() { - vm := New() - - _, err := vm.Run(` - var abc = { - ghi: 1, - def: function(def){ - var ghi = 0; - if (this.ghi) { - ghi = this.ghi; - } - return "def: " + (def + 3.14159 + ghi); - } - }; - function structFunc(s) { - return s.Val; - } - `) - is(err, nil) - - value, err := vm.Call(`abc.def`, nil, 2) - is(err, nil) - is(value, "def: 6.14159") - - value, err = vm.Call(`abc.def`, "", 2) - is(err, nil) - is(value, "def: 5.14159") - - // Do not attempt to do a ToValue on a this of nil - value, err = vm.Call(`jkl.def`, nil, 1, 2, 3) - is(err, "!=", nil) - is(value, "undefined") - - value, err = vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") - is(err, nil) - is(value, "1,2,3,,4,5,6,7,abc") - - s := struct{ Val int }{Val: 10} - value, err = vm.Call("structFunc", nil, s) - is(err, nil) - is(value, 10) - }) -} - -func TestOttoCall_new(t *testing.T) { - tt(t, func() { - test, vm := test() - - vm.Set("abc", func(call FunctionCall) Value { - value, err := call.Otto.Call(`new Object`, nil, "Nothing happens.") - is(err, nil) - return value - }) - test(` - def = abc(); - [ def, def instanceof String ]; - `, "Nothing happens.,true") - }) -} - -func TestOttoCall_newWithBrackets(t *testing.T) { - tt(t, func() { - test, vm := test() - - _, err := vm.Run(`var a = {default: function B(x) { this.x = x; } }`) - is(err, nil) - - test(`(new a['default'](1)).x`, 1) - }) -} - -func TestOttoCall_throw(t *testing.T) { - // FIXME? (Been broken for a while) - // Looks like this has been broken for a while... what - // behavior do we want here? - - if true { - return - } - - tt(t, func() { - test, vm := test() - - vm.Set("abc", func(call FunctionCall) Value { - if false { - call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") - } - call.Otto.Call(`throw Error`, nil, "abcdef") - return Value{} - }) - // TODO try { abc(); } catch (err) { error = err } - // Possible unrelated error case: - // If error is not declared beforehand, is later referencing it a ReferenceError? - // Should the catch { } declare error in the outer scope? - test(` - var error; - try { - abc(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def ]; - `, "true,abcdef,") - - vm.Set("def", func(call FunctionCall) Value { - call.Otto.Call(`throw new Object`, nil, 3.14159) - return UndefinedValue() - }) - test(` - try { - def(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def, typeof error, error, error instanceof Number ]; - `, "false,,,object,3.14159,true") - }) -} - -func TestOttoCopy(t *testing.T) { - tt(t, func() { - vm0 := New() - vm0.Run(` - var abc = function() { - return "Xyzzy"; - }; - - function def() { - return abc() + (0 + {}); - } - `) - - value, err := vm0.Run(` - def(); - `) - is(err, nil) - is(value, "Xyzzy0[object Object]") - - vm1 := vm0.Copy() - value, err = vm1.Run(` - def(); - `) - is(err, nil) - is(value, "Xyzzy0[object Object]") - - vm1.Run(` - abc = function() { - return 3.14159; - }; - `) - value, err = vm1.Run(` - def(); - `) - is(err, nil) - is(value, "3.141590[object Object]") - - value, err = vm0.Run(` - def(); - `) - is(err, nil) - is(value, "Xyzzy0[object Object]") - - { - vm0 := New() - vm0.Run(` - var global = (function () {return this;}()) - var abc = 0; - var vm = "vm0"; - - var def = (function(){ - var jkl = 0; - var abc = function() { - global.abc += 1; - jkl += 1; - return 1; - }; - - return function() { - return [ vm, global.abc, jkl, abc() ]; - }; - })(); - `) - - value, err := vm0.Run(` - def(); - `) - is(err, nil) - is(value, "vm0,0,0,1") - - vm1 := vm0.Copy() - vm1.Set("vm", "vm1") - value, err = vm1.Run(` - def(); - `) - is(err, nil) - is(value, "vm1,1,1,1") - - value, err = vm0.Run(` - def(); - `) - is(err, nil) - is(value, "vm0,1,1,1") - - value, err = vm1.Run(` - def(); - `) - is(err, nil) - is(value, "vm1,2,2,1") - } - }) -} - -func TestOttoCall_clone(t *testing.T) { - tt(t, func() { - vm := New().clone() - rt := vm.runtime - - { - // FIXME terst, Check how this comparison is done - is(rt.global.Array.prototype, rt.global.FunctionPrototype) - is(rt.global.ArrayPrototype, "!=", nil) - is(rt.global.Array.runtime, rt) - is(rt.global.Array.prototype.runtime, rt) - is(rt.global.Array.get("prototype")._object().runtime, rt) - } - - { - value, err := vm.Run(`[ 1, 2, 3 ].toString()`) - is(err, nil) - is(value, "1,2,3") - } - - { - value, err := vm.Run(`[ 1, 2, 3 ]`) - is(err, nil) - is(value, "1,2,3") - object := value._object() - is(object, "!=", nil) - is(object.prototype, rt.global.ArrayPrototype) - - value, err = vm.Run(`Array.prototype`) - is(err, nil) - object = value._object() - is(object.runtime, rt) - is(object, "!=", nil) - is(object, rt.global.ArrayPrototype) - } - - { - otto1 := New() - _, err := otto1.Run(` - var abc = 1; - var def = 2; - `) - is(err, nil) - - otto2 := otto1.clone() - value, err := otto2.Run(`abc += 1; abc;`) - is(err, nil) - is(value, 2) - - value, err = otto1.Run(`abc += 4; abc;`) - is(err, nil) - is(value, 5) - } - - { - vm1 := New() - _, err := vm1.Run(` - var abc = 1; - var def = function(value) { - abc += value; - return abc; - } - `) - is(err, nil) - - vm2 := vm1.clone() - value, err := vm2.Run(`def(1)`) - is(err, nil) - is(value, 2) - - value, err = vm1.Run(`def(4)`) - is(err, nil) - is(value, 5) - } - - { - vm1 := New() - _, err := vm1.Run(` - var abc = { - ghi: 1, - jkl: function(value) { - this.ghi += value; - return this.ghi; - } - }; - var def = { - abc: abc - }; - `) - is(err, nil) - - otto2 := vm1.clone() - value, err := otto2.Run(`def.abc.jkl(1)`) - is(err, nil) - is(value, 2) - - value, err = vm1.Run(`def.abc.jkl(4)`) - is(err, nil) - is(value, 5) - } - - { - vm1 := New() - _, err := vm1.Run(` - var abc = function() { return "abc"; }; - var def = function() { return "def"; }; - `) - is(err, nil) - - vm2 := vm1.clone() - value, err := vm2.Run(` - [ abc.toString(), def.toString() ]; - `) - is(value, `function() { return "abc"; },function() { return "def"; }`) - - _, err = vm2.Run(` - var def = function() { return "ghi"; }; - `) - is(err, nil) - - value, err = vm1.Run(` - [ abc.toString(), def.toString() ]; - `) - is(value, `function() { return "abc"; },function() { return "def"; }`) - - value, err = vm2.Run(` - [ abc.toString(), def.toString() ]; - `) - is(value, `function() { return "abc"; },function() { return "ghi"; }`) - } - - }) -} - -func TestOttoRun(t *testing.T) { - tt(t, func() { - vm := New() - - program, err := parser.ParseFile(nil, "", "", 0) - is(err, nil) - value, err := vm.Run(program) - is(err, nil) - is(value, UndefinedValue()) - - program, err = parser.ParseFile(nil, "", "2 + 2", 0) - is(err, nil) - value, err = vm.Run(program) - is(err, nil) - is(value, 4) - value, err = vm.Run(program) - is(err, nil) - is(value, 4) - - program, err = parser.ParseFile(nil, "", "var abc; if (!abc) abc = 0; abc += 2; abc;", 0) - value, err = vm.Run(program) - is(err, nil) - is(value, 2) - value, err = vm.Run(program) - is(err, nil) - is(value, 4) - value, err = vm.Run(program) - is(err, nil) - is(value, 6) - - { - src := []byte("var abc; if (!abc) abc = 0; abc += 2; abc;") - value, err = vm.Run(src) - is(err, nil) - is(value, 8) - - value, err = vm.Run(bytes.NewBuffer(src)) - is(err, nil) - is(value, 10) - - value, err = vm.Run(io.Reader(bytes.NewBuffer(src))) - is(err, nil) - is(value, 12) - } - - { - script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) - is(err, nil) - - value, err = vm.Run(script) - is(err, nil) - is(value, 14) - - value, err = vm.Run(script) - is(err, nil) - is(value, 16) - - is(script.String(), "// \nvar abc; if (!abc) abc = 0; abc += 2; abc;") - } - }) -} - -// This generates functions to be used by the test below. The arguments are -// `src`, which is something that otto can execute, and `expected`, which is -// what the result of executing `src` should be. -func makeTestOttoEvalFunction(src, expected interface{}) func(c FunctionCall) Value { - return func(c FunctionCall) Value { - v, err := c.Otto.Eval(src) - is(err, nil) - if err != nil { - panic(err) - } - - i, err := v.Export() - is(err, nil) - if err != nil { - panic(err) - } - - is(i, expected) - - return v - } -} - -func TestOttoEval(t *testing.T) { - tt(t, func() { - vm := New() - - vm.Set("x1", makeTestOttoEvalFunction(`a`, 1)) - vm.Set("y1", makeTestOttoEvalFunction(`b`, "hello")) - vm.Set("z1", makeTestOttoEvalFunction(`c`, true)) - vm.Set("w", makeTestOttoEvalFunction(`a = 2; b = 'what'; c = false; null`, nil)) - vm.Set("x2", makeTestOttoEvalFunction(`a`, 2)) - vm.Set("y2", makeTestOttoEvalFunction(`b`, "what")) - vm.Set("z2", makeTestOttoEvalFunction(`c`, false)) - - // note that these variables are defined in the scope of function `t`, - // so would not usually be available to the functions called below. - // - // this is _not_ the recommended use case for `Eval` - instead it's - // intended to be used in `debugger` handlers. this code here is the - // equivalent of reading behind the current stack frame in C... - // technically valid, but completely insane. - // - // makes for a good test case though. - _, err := vm.Run(`(function t() { - var a = 1; - var b = 'hello'; - var c = true; - - x1(); - y1(); - z1(); - w(); - x2(); - y2(); - z2(); - }())`) - - is(err, nil) - }) - - // this test makes sure that `Eval` doesn't explode if the VM doesn't have - // a scope other than global defined. - tt(t, func() { - vm := New() - - _, err := vm.Eval("null") - is(err, nil) - - vm.Set("a", 1) - vm.Set("b", 2) - - v, err := vm.Eval("a + b") - is(err, nil) - r, err := v.Export() - is(err, nil) - is(r, 3) - }) -} - -func TestOttoContext(t *testing.T) { - // These are all the builtin global scope symbols - builtins := []string{ - "escape", - "URIError", - "RegExp", - "ReferenceError", - "parseFloat", - "parseInt", - "SyntaxError", - "decodeURIComponent", - "encodeURIComponent", - "Infinity", - "JSON", - "isNaN", - "unescape", - "decodeURI", - "Object", - "Function", - "RangeError", - "Error", - "get_context", - "eval", - "Number", - "Math", - "NaN", - "Date", - "Boolean", - "console", - "encodeURI", - "EvalError", - "Array", - "TypeError", - "String", - "isFinite", - "undefined", - } - - tt(t, func() { - vm := New() - - vm.Set("get_context", func(c FunctionCall) Value { - ctx := c.Otto.Context() - is(ctx.Callee, "f1") - is(ctx.Filename, "") - is(ctx.Line, 8) - is(ctx.Column, 5) - is(ctx.Stacktrace, []string{ - "f1 (:8:5)", - "f2 (:15:5)", - "f3 (:19:5)", - "t (:22:4)", - }) - is(len(ctx.Symbols), 9+len(builtins)) - is(ctx.Symbols["a"], 1) - is(ctx.Symbols["b"], "hello") - is(ctx.Symbols["c"], true) - is(ctx.Symbols["j"], 2) - is(ctx.Symbols["f1"].IsFunction(), true) - is(ctx.Symbols["f2"].IsFunction(), true) - is(ctx.Symbols["f3"].IsFunction(), true) - is(ctx.Symbols["t"].IsFunction(), true) - callee, _ := ctx.Symbols["arguments"].Object().Get("callee") - is(callee.IsDefined(), true) - - return Value{} - }) - - _, err := vm.Run(`(function t() { - var a = 1; - var b = 'hello'; - var c = true; - - function f1() { - var j = 2; - get_context(); - (function() { - var d = 4; - })() - } - - function f2() { - f1(); - } - - function f3() { - f2(); - } - - f3(); - - a = 2; - b = 'goodbye'; - c = false; - }())`) - - is(err, nil) - }) - - // this test makes sure that `Context` works on global scope by default, if - // there is not a current scope. - tt(t, func() { - vm := New() - - vm.Set("get_context", func(c FunctionCall) Value { - ctx := c.Otto.Context() - is(ctx.Callee, "") - is(ctx.Filename, "") - is(ctx.Line, 3) - is(ctx.Column, 4) - is(ctx.Stacktrace, []string{":3:4"}) - is(len(ctx.Symbols), 2+len(builtins)) - is(ctx.Symbols["a"], 1) - is(ctx.Symbols["b"], UndefinedValue()) - - return Value{} - }) - - _, err := vm.Run(` - var a = 1; - get_context() - var b = 2; - `) - is(err, nil) - }) - - // this test makes sure variables are shadowed correctly. - tt(t, func() { - vm := New() - - vm.Set("check_context", func(c FunctionCall) Value { - n, err := c.Argument(0).ToInteger() - is(err, nil) - - ctx := c.Otto.Context() - is(ctx.Symbols["a"], n) - - return Value{} - }) - - _, err := vm.Run(` - var a = 1; - check_context(1); - (function() { - var a = 2; - check_context(2); - }()); - (function(a) { - check_context(3); - }(3)); - (function(a) { - check_context(4); - }).call(null, 4); - check_context(1); - `) - is(err, nil) - }) -} - -func Test_objectLength(t *testing.T) { - tt(t, func() { - _, vm := test() - - value := vm.Set("abc", []string{"jkl", "mno"}) - is(objectLength(value._object()), 2) - - value, _ = vm.Run(`[1, 2, 3]`) - is(objectLength(value._object()), 3) - - value, _ = vm.Run(`new String("abcdefghi")`) - is(objectLength(value._object()), 9) - - value, _ = vm.Run(`"abcdefghi"`) - is(objectLength(value._object()), 0) - }) -} - -func Test_stackLimit(t *testing.T) { - // JavaScript stack depth before entering `a` is 5; becomes 6 after - // entering. setting the maximum stack depth to 5 should result in an - // error ocurring at that 5 -> 6 boundary. - code := ` - function a() {} - function b() { a(); } - function c() { b(); } - function d() { c(); } - function e() { d(); } - e(); - ` - - // has no error - tt(t, func() { - _, vm := test() - - _, err := vm.Run(code) - - is(err == nil, true) - }) - - // has error - tt(t, func() { - _, vm := test() - - vm.vm.SetStackDepthLimit(2) - - _, err := vm.Run(code) - - is(err == nil, false) - }) - - // has error - tt(t, func() { - _, vm := test() - - vm.vm.SetStackDepthLimit(5) - - _, err := vm.Run(code) - - is(err == nil, false) - }) - - // has no error - tt(t, func() { - _, vm := test() - - vm.vm.SetStackDepthLimit(6) - - _, err := vm.Run(code) - - is(err == nil, true) - }) - - // has no error - tt(t, func() { - _, vm := test() - - vm.vm.SetStackDepthLimit(1) - vm.vm.SetStackDepthLimit(0) - - _, err := vm.Run(code) - - is(err == nil, true) - }) -} - -func BenchmarkNew(b *testing.B) { - for i := 0; i < b.N; i++ { - New() - } -} - -func BenchmarkClone(b *testing.B) { - vm := New() - b.ResetTimer() - for i := 0; i < b.N; i++ { - vm.clone() - } -} diff --git a/vendor/github.com/robertkrimen/otto/panic_test.go b/vendor/github.com/robertkrimen/otto/panic_test.go deleted file mode 100644 index 06f0a64fc1c..00000000000 --- a/vendor/github.com/robertkrimen/otto/panic_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package otto - -import ( - "testing" -) - -func Test_panic(t *testing.T) { - tt(t, func() { - test, _ := test() - - // Test that property.value is set to something if writable is set - // to something - test(` - var abc = []; - Object.defineProperty(abc, "0", { writable: false }); - Object.defineProperty(abc, "0", { writable: false }); - "0" in abc; - `, true) - - test(`raise: - var abc = []; - Object.defineProperty(abc, "0", { writable: false }); - Object.defineProperty(abc, "0", { value: false, writable: false }); - `, "TypeError") - - // Test that a regular expression can contain \c0410 (CYRILLIC CAPITAL LETTER A) - // without panicking - test(` - var abc = 0x0410; - var def = String.fromCharCode(abc); - new RegExp("\\c" + def).exec(def); - `, "null") - - // Test transforming a transformable regular expression without a panic - test(` - new RegExp("\\u0000"); - new RegExp("\\undefined").test("undefined"); - `, true) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/parser/comments_test.go b/vendor/github.com/robertkrimen/otto/parser/comments_test.go deleted file mode 100644 index 72d08bb0d17..00000000000 --- a/vendor/github.com/robertkrimen/otto/parser/comments_test.go +++ /dev/null @@ -1,1450 +0,0 @@ -package parser - -import ( - "fmt" - "github.com/robertkrimen/otto/ast" - "reflect" - "testing" -) - -func checkComments(actual []*ast.Comment, expected []string, position ast.CommentPosition) error { - var comments []*ast.Comment - for _, c := range actual { - if c.Position == position { - comments = append(comments, c) - } - } - - if len(comments) != len(expected) { - return fmt.Errorf("the number of comments is not correct. %v != %v", len(comments), len(expected)) - } - - for i, v := range comments { - if v.Text != expected[i] { - return fmt.Errorf("comments do not match. \"%v\" != \"%v\"\n", v.Text, expected[i]) - } - if v.Position != position { - return fmt.Errorf("the comment is not %v, was %v\n", position, v.Position) - } - } - - return nil -} - -func displayStatements(statements []ast.Statement) { - fmt.Printf("Printing statements (%v)\n", len(statements)) - for k, v := range statements { - fmt.Printf("Type of line %v: %v\n", k, reflect.TypeOf(v)) - } -} - -func displayComments(m ast.CommentMap) { - fmt.Printf("Displaying comments:\n") - for n, comments := range m { - fmt.Printf("%v %v:\n", reflect.TypeOf(n), n) - for i, comment := range comments { - fmt.Printf(" [%v] %v @ %v\n", i, comment.Text, comment.Position) - } - } -} - -func TestParser_comments(t *testing.T) { - tt(t, func() { - test := func(source string, chk interface{}) (*_parser, *ast.Program) { - parser, program, err := testParseWithMode(source, StoreComments) - is(firstErr(err), chk) - - // Check unresolved comments - //is(len(parser.comments), 0) - return parser, program - } - - var err error - var parser *_parser - var program *ast.Program - - parser, program = test("q=2;// Hej\nv = 0", nil) - is(len(program.Body), 2) - err = checkComments((parser.comments.CommentMap)[program.Body[1]], []string{" Hej"}, ast.LEADING) - is(err, nil) - - // Assignment - parser, program = test("i = /*test=*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right], []string{"test="}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Conditional, before consequent - parser, program = test("i ? /*test?*/ 2 : 3", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression).Consequent], []string{"test?"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Conditional, after consequent - parser, program = test("i ? 2 /*test?*/ : 3", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression).Consequent], []string{"test?"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Conditional, before alternate - parser, program = test("i ? 2 : /*test:*/ 3", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression).Alternate], []string{"test:"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Logical OR - parser, program = test("i || /*test||*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test||"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Logical AND - parser, program = test("i && /*test&&*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test&&"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Bitwise OR - parser, program = test("i | /*test|*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test|"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Exclusive OR - parser, program = test("i ^ /*test^*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test^"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Bitwise AND - parser, program = test("i & /*test&*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test&"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Equality - parser, program = test("i == /*test==*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test=="}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Relational, < - parser, program = test("i < /*test<*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test<"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Relational, instanceof - parser, program = test("i instanceof /*testinstanceof*/ thing", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"testinstanceof"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Shift left - parser, program = test("i << /*test<<*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test<<"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // + - parser, program = test("i + /*test+*/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test+"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // * - parser, program = test("i * /*test**/ 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"test*"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Unary prefix, ++ - parser, program = test("++/*test++*/i", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression).Operand], []string{"test++"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Unary prefix, delete - parser, program = test("delete /*testdelete*/ i", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression).Operand], []string{"testdelete"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Unary postfix, ++ - parser, program = test("i/*test++*/++", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression).Operand], []string{"test++"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // + pt 2 - parser, program = test("i /*test+*/ + 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Left], []string{"test+"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Multiple comments for a single node - parser, program = test("i /*test+*/ /*test+2*/ + 2", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Left], []string{"test+", "test+2"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 2) - - // Multiple comments for multiple nodes - parser, program = test("i /*test1*/ + 2 /*test2*/ + a /*test3*/ * x /*test4*/", nil) - is(len(program.Body), 1) - is(parser.comments.CommentMap.Size(), 4) - - // Leading comment - parser, program = test("/*leadingtest*/i + 2", nil) - is(len(program.Body), 1) - - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement)], []string{"leadingtest"}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Left], []string{}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Leading comment, with semicolon - parser, program = test("/*leadingtest;*/;i + 2", nil) - is(len(program.Body), 2) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"leadingtest;"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays - parser, program = test("[1, 2 /*test2*/, 3]", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{"test2"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Function calls - parser, program = test("fun(a,b) //test", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.CallExpression)], []string{"test"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Function calls, pt 2 - parser, program = test("fun(a/*test1*/,b)", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.CallExpression).ArgumentList[0]], []string{"test1"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Function calls, pt 3 - parser, program = test("fun(/*test1*/a,b)", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.CallExpression).ArgumentList[0]], []string{"test1"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 2 - parser, program = test(`["abc".substr(0,1)/*testa*/, - "abc.substr(0,2)"];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[0]], []string{"testa"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 3 - parser, program = test(`[a, //test - b];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{"test"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 4 - parser, program = test(`[a, //test - b, c];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{"test"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 5 - parser, program = test(` -[ - "a1", // "a" - "a2", // "ab" -]; - `, nil) - is(parser.comments.CommentMap.Size(), 2) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{" \"a\""}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral)], []string{" \"ab\""}, ast.FINAL), nil) - - // Arrays pt 6 - parser, program = test(`[a, /*test*/ b, c];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{"test"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 7 - Empty node - parser, program = test(`[a,,/*test2*/,];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[2]], []string{"test2"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 8 - Trailing node - parser, program = test(`[a,,,/*test2*/];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral)], []string{"test2"}, ast.FINAL), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Arrays pt 9 - Leading node - parser, program = test(`[/*test2*/a,,,];`, nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[0]], []string{"test2"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal - parser, program = test("obj = {a: 1, b: 2 /*test2*/, c: 3}", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[1].Value], []string{"test2"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal, pt 2 - parser, program = test("obj = {/*test2*/a: 1, b: 2, c: 3}", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{"test2"}, ast.KEY), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal, pt 3 - parser, program = test("obj = {x/*test2*/: 1, y: 2, z: 3}", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{"test2"}, ast.COLON), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal, pt 4 - parser, program = test("obj = {x: /*test2*/1, y: 2, z: 3}", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{"test2"}, ast.LEADING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal, pt 5 - parser, program = test("obj = {x: 1/*test2*/, y: 2, z: 3}", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{"test2"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal, pt 6 - parser, program = test("obj = {x: 1, y: 2, z: 3/*test2*/}", nil) - is(len(program.Body), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[2].Value], []string{"test2"}, ast.TRAILING), nil) - is(parser.comments.CommentMap.Size(), 1) - - // Object literal, pt 7 - trailing comment - parser, program = test("obj = {x: 1, y: 2, z: 3,/*test2*/}", nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral)], []string{"test2"}, ast.FINAL), nil) - - // Line breaks - parser, program = test(` -t1 = "BLA DE VLA" -/*Test*/ -t2 = "Nothing happens." - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"Test"}, ast.LEADING), nil) - - // Line breaks pt 2 - parser, program = test(` -t1 = "BLA DE VLA" /*Test*/ -t2 = "Nothing happens." - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.StringLiteral)], []string{"Test"}, ast.TRAILING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[1].(*ast.ExpressionStatement)], []string{}, ast.LEADING), nil) - - // Line breaks pt 3 - parser, program = test(` -t1 = "BLA DE VLA" /*Test*/ /*Test2*/ -t2 = "Nothing happens." - `, nil) - is(parser.comments.CommentMap.Size(), 2) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.StringLiteral)], []string{"Test", "Test2"}, ast.TRAILING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[1].(*ast.ExpressionStatement)], []string{}, ast.LEADING), nil) - - // Line breaks pt 4 - parser, program = test(` -t1 = "BLA DE VLA" /*Test*/ -/*Test2*/ -t2 = "Nothing happens." - `, nil) - is(parser.comments.CommentMap.Size(), 2) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.StringLiteral)], []string{"Test"}, ast.TRAILING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"Test2"}, ast.LEADING), nil) - - // Line breaks pt 5 - parser, program = test(` -t1 = "BLA DE VLA"; -/*Test*/ -t2 = "Nothing happens." - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"Test"}, ast.LEADING), nil) - - // Line breaks pt 6 - parser, program = test(` -t1 = "BLA DE VLA"; /*Test*/ -/*Test2*/ -t2 = "Nothing happens." - `, nil) - is(parser.comments.CommentMap.Size(), 2) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"Test", "Test2"}, ast.LEADING), nil) - - // Misc - parser, program = test(` -var x = Object.create({y: { -}, -// a -}); - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Misc 2 - parser, program = test(` -var x = Object.create({y: { -}, -// a -// b -a: 2}); - `, nil) - is(parser.comments.CommentMap.Size(), 2) - - // Statement blocks - parser, program = test(` -(function() { - // Baseline setup -}) - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body], []string{" Baseline setup"}, ast.FINAL), nil) - - // Switches - parser, program = test(` -switch (switcha) { - // switch comment - case "switchb": - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0]], []string{" switch comment"}, ast.LEADING), nil) - - // Switches pt 2 - parser, program = test(` -switch (switcha) { - case /*switch comment*/ "switchb": - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Test], []string{"switch comment"}, ast.LEADING), nil) - - // Switches pt 3 - parser, program = test(` -switch (switcha) { - case "switchb" /*switch comment*/: - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Test], []string{"switch comment"}, ast.TRAILING), nil) - - // Switches pt 4 - parser, program = test(` -switch (switcha) { - case "switchb": /*switch comment*/ - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{"switch comment"}, ast.LEADING), nil) - - // Switches pt 5 - default - parser, program = test(` -switch (switcha) { - default: /*switch comment*/ - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{"switch comment"}, ast.LEADING), nil) - - // Switches pt 6 - parser, program = test(` -switch (switcha) { - case "switchb": - /*switch comment*/a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{"switch comment"}, ast.LEADING), nil) - - // Switches pt 7 - parser, program = test(` -switch (switcha) { - case "switchb": /*switch comment*/ { - a - } -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{"switch comment"}, ast.LEADING), nil) - - // Switches pt 8 - parser, program = test(` -switch (switcha) { - case "switchb": { - a - }/*switch comment*/ -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{"switch comment"}, ast.TRAILING), nil) - - // Switches pt 9 - parser, program = test(` -switch (switcha) { - case "switchb": /*switch comment*/ { - a - } -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{"switch comment"}, ast.LEADING), nil) - - // Switches pt 10 - parser, program = test(` -switch (switcha) { - case "switchb": { - /*switch comment*/a - } -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0].(*ast.BlockStatement).List[0]], []string{"switch comment"}, ast.LEADING), nil) - - // For loops - parser, program = test(` -for(/*comment*/i = 0 ; i < 1 ; i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Initializer.(*ast.SequenceExpression).Sequence[0].(*ast.AssignExpression).Left], []string{"comment"}, ast.LEADING), nil) - - // For loops pt 2 - parser, program = test(` -for(i/*comment*/ = 0 ; i < 1 ; i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Initializer.(*ast.SequenceExpression).Sequence[0].(*ast.AssignExpression).Left], []string{"comment"}, ast.TRAILING), nil) - - // For loops pt 3 - parser, program = test(` -for(i = 0 ; /*comment*/i < 1 ; i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Test.(*ast.BinaryExpression).Left], []string{"comment"}, ast.LEADING), nil) - - // For loops pt 4 - parser, program = test(` -for(i = 0 ;i /*comment*/ < 1 ; i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Test.(*ast.BinaryExpression).Left], []string{"comment"}, ast.TRAILING), nil) - - // For loops pt 5 - parser, program = test(` -for(i = 0 ;i < 1 /*comment*/ ; i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Test.(*ast.BinaryExpression).Right], []string{"comment"}, ast.TRAILING), nil) - - // For loops pt 6 - parser, program = test(` -for(i = 0 ;i < 1 ; /*comment*/ i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression).Operand], []string{"comment"}, ast.LEADING), nil) - - // For loops pt 7 - parser, program = test(` -for(i = 0 ;i < 1 ; i++) /*comment*/ { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Body], []string{"comment"}, ast.LEADING), nil) - - // For loops pt 8 - parser, program = test(` -for(i = 0 ;i < 1 ; i++) { - a -}/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // For loops pt 9 - parser, program = test(` -for(i = 0 ;i < 1 ; /*comment*/i++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression).Operand], []string{"comment"}, ast.LEADING), nil) - - // For loops pt 10 - parser, program = test(` -for(i = 0 ;i < 1 ; i/*comment*/++) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression).Operand.(*ast.Identifier)], []string{"comment"}, ast.TRAILING), nil) - - // For loops pt 11 - parser, program = test(` -for(i = 0 ;i < 1 ; i++/*comment*/) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression)], []string{"comment"}, ast.TRAILING), nil) - - // ForIn - parser, program = test(` -for(/*comment*/var i = 0 in obj) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Into], []string{"comment"}, ast.LEADING), nil) - - // ForIn pt 2 - parser, program = test(` -for(var i = 0 /*comment*/in obj) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Into.(*ast.VariableExpression).Initializer], []string{"comment"}, ast.TRAILING), nil) - - // ForIn pt 3 - parser, program = test(` -for(var i = 0 in /*comment*/ obj) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Source], []string{"comment"}, ast.LEADING), nil) - - // ForIn pt 4 - parser, program = test(` -for(var i = 0 in obj/*comment*/) { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Source], []string{"comment"}, ast.TRAILING), nil) - - // ForIn pt 5 - parser, program = test(` -for(var i = 0 in obj) /*comment*/ { - a -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Body], []string{"comment"}, ast.LEADING), nil) - - // ForIn pt 6 - parser, program = test(` -for(var i = 0 in obj) { - a -}/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // ForIn pt 7 - parser, program = test(` -for(var i = 0 in obj) { - a -} -// comment - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program], []string{" comment"}, ast.TRAILING), nil) - - // ForIn pt 8 - parser, program = test(` -for(var i = 0 in obj) { - a -} -// comment -c - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{" comment"}, ast.LEADING), nil) - - // Block - parser, program = test(` - /*comment*/{ - a - } - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.BlockStatement)], []string{"comment"}, ast.LEADING), nil) - - // Block pt 2 - parser, program = test(` - { - a - }/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.BlockStatement)], []string{"comment"}, ast.TRAILING), nil) - - // If then else - parser, program = test(` -/*comment*/ -if(a) { - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement)], []string{"comment"}, ast.LEADING), nil) - - // If then else pt 2 - parser, program = test(` -if/*comment*/(a) { - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement)], []string{"comment"}, ast.IF), nil) - - // If then else pt 3 - parser, program = test(` -if(/*comment*/a) { - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Test], []string{"comment"}, ast.LEADING), nil) - - // If then else pt 4 - parser, program = test(` -if(a/*comment*/) { - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Test], []string{"comment"}, ast.TRAILING), nil) - - // If then else pt 4 - parser, program = test(` -if(a)/*comment*/ { - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Consequent], []string{"comment"}, ast.LEADING), nil) - - // If then else pt 5 - parser, program = test(` -if(a) { - b -} /*comment*/else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Consequent], []string{"comment"}, ast.TRAILING), nil) - - // If then else pt 6 - parser, program = test(` -if(a) { - b -} else/*comment*/ { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Alternate], []string{"comment"}, ast.LEADING), nil) - - // If then else pt 7 - parser, program = test(` -if(a) { - b -} else { - c -}/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Alternate], []string{"comment"}, ast.TRAILING), nil) - - // If then else pt 8 - parser, program = test(` -if -/*comment*/ -(a) { - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // If then else pt 9 - parser, program = test(` -if -(a) - /*comment*/{ - b -} else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // If then else pt 10 - parser, program = test(` -if(a){ - b -} -/*comment*/ -else { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Do while - parser, program = test(` -/*comment*/do { - a -} while(b) - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{"comment"}, ast.LEADING), nil) - - // Do while pt 2 - parser, program = test(` -do /*comment*/ { - a -} while(b) - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{"comment"}, ast.DO), nil) - - // Do while pt 3 - parser, program = test(` -do { - a -} /*comment*/ while(b) - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // Do while pt 4 - parser, program = test(` -do { - a -} while/*comment*/(b) - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{"comment"}, ast.WHILE), nil) - - // Do while pt 5 - parser, program = test(` -do { - a -} while(b)/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{"comment"}, ast.TRAILING), nil) - - // While - parser, program = test(` -/*comment*/while(a) { - b -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement)], []string{"comment"}, ast.LEADING), nil) - - // While pt 2 - parser, program = test(` -while/*comment*/(a) { - b -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement)], []string{"comment"}, ast.WHILE), nil) - - // While pt 3 - parser, program = test(` -while(/*comment*/a) { - b -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Test], []string{"comment"}, ast.LEADING), nil) - - // While pt 4 - parser, program = test(` -while(a/*comment*/) { - b -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Test], []string{"comment"}, ast.TRAILING), nil) - - // While pt 5 - parser, program = test(` -while(a) /*comment*/ { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body], []string{"comment"}, ast.LEADING), nil) - - // While pt 6 - parser, program = test(` -while(a) { - c -}/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // While pt 7 - parser, program = test(` -while(a) { - c/*comment*/ -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.ExpressionStatement).Expression.(*ast.Identifier)], []string{"comment"}, ast.TRAILING), nil) - - // While pt 7 - parser, program = test(` -while(a) { - /*comment*/ -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement)], []string{"comment"}, ast.FINAL), nil) - - // While pt 8 - parser, program = test(` -while -/*comment*/(a) { - -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // While pt 9 - parser, program = test(` -while -(a) - /*comment*/{ - -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Break - parser, program = test(` -while(a) { - break/*comment*/; -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.BranchStatement)], []string{"comment"}, ast.TRAILING), nil) - - // Break pt 2 - parser, program = test(` -while(a) { - next/*comment*/: - break next; -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement).Label], []string{"comment"}, ast.TRAILING), nil) - - // Break pt 3 - parser, program = test(` -while(a) { - next:/*comment*/ - break next; -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement)], []string{"comment"}, ast.LEADING), nil) - - // Break pt 4 - parser, program = test(` -while(a) { - next: - break /*comment*/next; -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement).Statement.(*ast.BranchStatement).Label], []string{"comment"}, ast.LEADING), nil) - - // Break pt 5 - parser, program = test(` -while(a) { - next: - break next/*comment*/; -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement).Statement.(*ast.BranchStatement).Label], []string{"comment"}, ast.TRAILING), nil) - - // Debugger - parser, program = test(` -debugger // comment - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.DebuggerStatement)], []string{" comment"}, ast.TRAILING), nil) - - // Debugger pt 2 - parser, program = test(` -debugger; // comment - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program], []string{" comment"}, ast.TRAILING), nil) - - // Debugger pt 3 - parser, program = test(` -debugger; -// comment - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program], []string{" comment"}, ast.TRAILING), nil) - - // With - parser, program = test(` -/*comment*/with(a) { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WithStatement)], []string{"comment"}, ast.LEADING), nil) - - // With pt 2 - parser, program = test(` -with/*comment*/(a) { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WithStatement)], []string{"comment"}, ast.WITH), nil) - - // With pt 3 - parser, program = test(` -with(/*comment*/a) { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Object], []string{"comment"}, ast.LEADING), nil) - - // With pt 4 - parser, program = test(` -with(a/*comment*/) { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Object], []string{"comment"}, ast.TRAILING), nil) - - // With pt 5 - parser, program = test(` -with(a) /*comment*/ { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Body], []string{"comment"}, ast.LEADING), nil) - - // With pt 6 - parser, program = test(` -with(a) { -}/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // With pt 7 - parser, program = test(` -with -/*comment*/(a) { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // With pt 8 - parser, program = test(` -with -(a) - /*comment*/{ -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Var - parser, program = test(` -/*comment*/var a - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.VariableStatement)], []string{"comment"}, ast.LEADING), nil) - - // Var pt 2 - parser, program = test(` -var/*comment*/ a - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[0]], []string{"comment"}, ast.LEADING), nil) - - // Var pt 3 - parser, program = test(` -var a/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[0]], []string{"comment"}, ast.TRAILING), nil) - - // Var pt 4 - parser, program = test(` -var a/*comment*/, b - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[0].(*ast.VariableExpression)], []string{"comment"}, ast.TRAILING), nil) - - // Var pt 5 - parser, program = test(` -var a, /*comment*/b - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[1].(*ast.VariableExpression)], []string{"comment"}, ast.LEADING), nil) - - // Var pt 6 - parser, program = test(` -var a, b/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[1]], []string{"comment"}, ast.TRAILING), nil) - - // Var pt 7 - parser, program = test(` -var a, b; -/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program], []string{"comment"}, ast.TRAILING), nil) - - // Return - parser, program = test(` - function f() { -/*comment*/return o -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Try catch - parser, program = test(` -/*comment*/try { - a -} catch(b) { - c -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement)], []string{"comment"}, ast.LEADING), nil) - - // Try catch pt 2 - parser, program = test(` -try/*comment*/ { - a -} catch(b) { - c -} finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Body], []string{"comment"}, ast.LEADING), nil) - - // Try catch pt 3 - parser, program = test(` -try { - a -}/*comment*/ catch(b) { - c -} finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // Try catch pt 4 - parser, program = test(` -try { - a -} catch(/*comment*/b) { - c -} finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Parameter], []string{"comment"}, ast.LEADING), nil) - - // Try catch pt 5 - parser, program = test(` -try { - a -} catch(b/*comment*/) { - c -} finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Parameter], []string{"comment"}, ast.TRAILING), nil) - - // Try catch pt 6 - parser, program = test(` -try { - a -} catch(b) /*comment*/{ - c -} finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Body], []string{"comment"}, ast.LEADING), nil) - - // Try catch pt 7 - parser, program = test(` -try { - a -} catch(b){ - c -} /*comment*/ finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Body], []string{"comment"}, ast.TRAILING), nil) - - // Try catch pt 8 - parser, program = test(` -try { - a -} catch(b){ - c -} finally /*comment*/ { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Finally], []string{"comment"}, ast.LEADING), nil) - - // Try catch pt 9 - parser, program = test(` -try { - a -} catch(b){ - c -} finally { -}/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Finally], []string{"comment"}, ast.TRAILING), nil) - - // Try catch pt 11 - parser, program = test(` -try { - a -} -/*comment*/ - catch(b){ - c -} finally { - d -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Body], []string{"comment"}, ast.TRAILING), nil) - - // Throw - parser, program = test(` -throw a/*comment*/ - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ThrowStatement).Argument], []string{"comment"}, ast.TRAILING), nil) - - // Throw pt 2 - parser, program = test(` -/*comment*/throw a - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ThrowStatement)], []string{"comment"}, ast.LEADING), nil) - - // Throw pt 3 - parser, program = test(` -throw /*comment*/a - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ThrowStatement).Argument], []string{"comment"}, ast.LEADING), nil) - - // Try catch pt 10 - parser, program = test(` -try { - a -} catch(b){ - c -} - /*comment*/finally { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Body], []string{"comment"}, ast.TRAILING), nil) - - // Try catch pt 11 - parser, program = test(` -try { - a -} catch(b){ - c -} - finally - /*comment*/ - { - d -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Finally], []string{"comment"}, ast.LEADING), nil) - - // Switch / comment - parser, program = test(` -var volvo = 1 -//comment -switch(abra) { -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Switch / comment - parser, program = test(` -f("string",{ - key: "val" - //comment -}); - `, nil) - is(parser.comments.CommentMap.Size(), 1) - - // Switch / comment - parser, program = test(` -function f() { - /*comment*/if(true){a++} -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - n := program.Body[0].(*ast.FunctionStatement).Function.Body.(*ast.BlockStatement).List[0] - is(checkComments((parser.comments.CommentMap)[n], []string{"comment"}, ast.LEADING), nil) - - // Function in function - parser, program = test(` -function f() { - /*comment*/function f2() { - } -} - `, nil) - is(parser.comments.CommentMap.Size(), 1) - n = program.Body[0].(*ast.FunctionStatement).Function.Body.(*ast.BlockStatement).List[0] - is(checkComments((parser.comments.CommentMap)[n], []string{"comment"}, ast.LEADING), nil) - - parser, program = test(` -a + /*comment1*/ -/*comment2*/ -b/*comment3*/; -/*comment4*/c - `, nil) - is(parser.comments.CommentMap.Size(), 4) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"comment1", "comment2"}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"comment3"}, ast.TRAILING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"comment4"}, ast.LEADING), nil) - - parser, program = test(` -a + /*comment1*/ -/*comment2*/ -b/*comment3*/ -/*comment4*/c - `, nil) - is(parser.comments.CommentMap.Size(), 4) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"comment1", "comment2"}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{"comment3"}, ast.TRAILING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[1]], []string{"comment4"}, ast.LEADING), nil) - - // New - parser, program = test(` -a = /*comment1*/new /*comment2*/ obj/*comment3*/() - `, nil) - is(parser.comments.CommentMap.Size(), 3) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right], []string{"comment1"}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.NewExpression).Callee], []string{"comment2"}, ast.LEADING), nil) - is(checkComments((parser.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.NewExpression).Callee], []string{"comment3"}, ast.TRAILING), nil) - - }) -} - -func TestParser_comments2(t *testing.T) { - tt(t, func() { - test := func(source string, chk interface{}) (*_parser, *ast.Program) { - parser, program, err := testParseWithMode(source, StoreComments) - is(firstErr(err), chk) - - // Check unresolved comments - is(len(parser.comments.Comments), 0) - return parser, program - } - - parser, program := test(` -a = /*comment1*/new /*comment2*/ obj/*comment3*/() -`, nil) - n := program.Body[0] - fmt.Printf("FOUND NODE: %v, number of comments: %v\n", reflect.TypeOf(n), len(parser.comments.CommentMap[n])) - displayComments(parser.comments.CommentMap) - - }) -} diff --git a/vendor/github.com/robertkrimen/otto/parser/lexer_test.go b/vendor/github.com/robertkrimen/otto/parser/lexer_test.go deleted file mode 100644 index 99fcbac7832..00000000000 --- a/vendor/github.com/robertkrimen/otto/parser/lexer_test.go +++ /dev/null @@ -1,386 +0,0 @@ -package parser - -import ( - "../terst" - "testing" - - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -var tt = terst.Terst -var is = terst.Is - -func TestLexer(t *testing.T) { - tt(t, func() { - setup := func(src string) *_parser { - parser := _newParser("", src, 1, nil) - return parser - } - - test := func(src string, test ...interface{}) { - parser := setup(src) - for len(test) > 0 { - tkn, literal, idx := parser.scan() - if len(test) > 0 { - is(tkn, test[0].(token.Token)) - test = test[1:] - } - if len(test) > 0 { - is(literal, test[0].(string)) - test = test[1:] - } - if len(test) > 0 { - // FIXME terst, Fix this so that cast to file.Idx is not necessary? - is(idx, file.Idx(test[0].(int))) - test = test[1:] - } - } - } - - test("", - token.EOF, "", 1, - ) - - test("1", - token.NUMBER, "1", 1, - token.EOF, "", 2, - ) - - test(".0", - token.NUMBER, ".0", 1, - token.EOF, "", 3, - ) - - test("abc", - token.IDENTIFIER, "abc", 1, - token.EOF, "", 4, - ) - - test("abc(1)", - token.IDENTIFIER, "abc", 1, - token.LEFT_PARENTHESIS, "", 4, - token.NUMBER, "1", 5, - token.RIGHT_PARENTHESIS, "", 6, - token.EOF, "", 7, - ) - - test(".", - token.PERIOD, "", 1, - token.EOF, "", 2, - ) - - test("===.", - token.STRICT_EQUAL, "", 1, - token.PERIOD, "", 4, - token.EOF, "", 5, - ) - - test(">>>=.0", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - token.NUMBER, ".0", 5, - token.EOF, "", 7, - ) - - test(">>>=0.0.", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - token.NUMBER, "0.0", 5, - token.PERIOD, "", 8, - token.EOF, "", 9, - ) - - test("\"abc\"", - token.STRING, "\"abc\"", 1, - token.EOF, "", 6, - ) - - test("abc = //", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.EOF, "", 9, - ) - - test("abc = /*test*/", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.EOF, "", 15, - ) - - test("abc = 1 / 2", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NUMBER, "1", 7, - token.SLASH, "", 9, - token.NUMBER, "2", 11, - token.EOF, "", 12, - ) - - test("xyzzy = 'Nothing happens.'", - token.IDENTIFIER, "xyzzy", 1, - token.ASSIGN, "", 7, - token.STRING, "'Nothing happens.'", 9, - token.EOF, "", 27, - ) - - test("abc = !false", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NOT, "", 7, - token.BOOLEAN, "false", 8, - token.EOF, "", 13, - ) - - test("abc = !!true", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NOT, "", 7, - token.NOT, "", 8, - token.BOOLEAN, "true", 9, - token.EOF, "", 13, - ) - - test("abc *= 1", - token.IDENTIFIER, "abc", 1, - token.MULTIPLY_ASSIGN, "", 5, - token.NUMBER, "1", 8, - token.EOF, "", 9, - ) - - test("if 1 else", - token.IF, "if", 1, - token.NUMBER, "1", 4, - token.ELSE, "else", 6, - token.EOF, "", 10, - ) - - test("null", - token.NULL, "null", 1, - token.EOF, "", 5, - ) - - test(`"\u007a\x79\u000a\x78"`, - token.STRING, "\"\\u007a\\x79\\u000a\\x78\"", 1, - token.EOF, "", 23, - ) - - test(`"[First line \ -Second line \ - Third line\ -. ]" - `, - token.STRING, "\"[First line \\\nSecond line \\\n Third line\\\n. ]\"", 1, - token.EOF, "", 53, - ) - - test("/", - token.SLASH, "", 1, - token.EOF, "", 2, - ) - - test("var abc = \"abc\uFFFFabc\"", - token.VAR, "var", 1, - token.IDENTIFIER, "abc", 5, - token.ASSIGN, "", 9, - token.STRING, "\"abc\uFFFFabc\"", 11, - token.EOF, "", 22, - ) - - test(`'\t' === '\r'`, - token.STRING, "'\\t'", 1, - token.STRICT_EQUAL, "", 6, - token.STRING, "'\\r'", 10, - token.EOF, "", 14, - ) - - test(`var \u0024 = 1`, - token.VAR, "var", 1, - token.IDENTIFIER, "$", 5, - token.ASSIGN, "", 12, - token.NUMBER, "1", 14, - token.EOF, "", 15, - ) - - test("10e10000", - token.NUMBER, "10e10000", 1, - token.EOF, "", 9, - ) - - test(`var if var class`, - token.VAR, "var", 1, - token.IF, "if", 5, - token.VAR, "var", 8, - token.KEYWORD, "class", 12, - token.EOF, "", 17, - ) - - test(`-0`, - token.MINUS, "", 1, - token.NUMBER, "0", 2, - token.EOF, "", 3, - ) - - test(`.01`, - token.NUMBER, ".01", 1, - token.EOF, "", 4, - ) - - test(`.01e+2`, - token.NUMBER, ".01e+2", 1, - token.EOF, "", 7, - ) - - test(";", - token.SEMICOLON, "", 1, - token.EOF, "", 2, - ) - - test(";;", - token.SEMICOLON, "", 1, - token.SEMICOLON, "", 2, - token.EOF, "", 3, - ) - - test("//", - token.EOF, "", 3, - ) - - test(";;//test", - token.SEMICOLON, "", 1, - token.SEMICOLON, "", 2, - token.EOF, "", 9, - ) - - test("1", - token.NUMBER, "1", 1, - ) - - test("12 123", - token.NUMBER, "12", 1, - token.NUMBER, "123", 4, - ) - - test("1.2 12.3", - token.NUMBER, "1.2", 1, - token.NUMBER, "12.3", 5, - ) - - test("/ /=", - token.SLASH, "", 1, - token.QUOTIENT_ASSIGN, "", 3, - ) - - test(`"abc"`, - token.STRING, `"abc"`, 1, - ) - - test(`'abc'`, - token.STRING, `'abc'`, 1, - ) - - test("++", - token.INCREMENT, "", 1, - ) - - test(">", - token.GREATER, "", 1, - ) - - test(">=", - token.GREATER_OR_EQUAL, "", 1, - ) - - test(">>", - token.SHIFT_RIGHT, "", 1, - ) - - test(">>=", - token.SHIFT_RIGHT_ASSIGN, "", 1, - ) - - test(">>>", - token.UNSIGNED_SHIFT_RIGHT, "", 1, - ) - - test(">>>=", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - ) - - test("1 \"abc\"", - token.NUMBER, "1", 1, - token.STRING, "\"abc\"", 3, - ) - - test(",", - token.COMMA, "", 1, - ) - - test("1, \"abc\"", - token.NUMBER, "1", 1, - token.COMMA, "", 2, - token.STRING, "\"abc\"", 4, - ) - - test("new abc(1, 3.14159);", - token.NEW, "new", 1, - token.IDENTIFIER, "abc", 5, - token.LEFT_PARENTHESIS, "", 8, - token.NUMBER, "1", 9, - token.COMMA, "", 10, - token.NUMBER, "3.14159", 12, - token.RIGHT_PARENTHESIS, "", 19, - token.SEMICOLON, "", 20, - ) - - test("1 == \"1\"", - token.NUMBER, "1", 1, - token.EQUAL, "", 3, - token.STRING, "\"1\"", 6, - ) - - test("1\n[]\n", - token.NUMBER, "1", 1, - token.LEFT_BRACKET, "", 3, - token.RIGHT_BRACKET, "", 4, - ) - - test("1\ufeff[]\ufeff", - token.NUMBER, "1", 1, - token.LEFT_BRACKET, "", 5, - token.RIGHT_BRACKET, "", 6, - ) - - // ILLEGAL - - test(`3ea`, - token.ILLEGAL, "3e", 1, - token.IDENTIFIER, "a", 3, - token.EOF, "", 4, - ) - - test(`3in`, - token.ILLEGAL, "3", 1, - token.IN, "in", 2, - token.EOF, "", 4, - ) - - test("\"Hello\nWorld\"", - token.ILLEGAL, "", 1, - token.IDENTIFIER, "World", 8, - token.ILLEGAL, "", 13, - token.EOF, "", 14, - ) - - test("\u203f = 10", - token.ILLEGAL, "", 1, - token.ASSIGN, "", 5, - token.NUMBER, "10", 7, - token.EOF, "", 9, - ) - - test(`"\x0G"`, - token.STRING, "\"\\x0G\"", 1, - token.EOF, "", 7, - ) - - }) -} diff --git a/vendor/github.com/robertkrimen/otto/parser/marshal_test.go b/vendor/github.com/robertkrimen/otto/parser/marshal_test.go deleted file mode 100644 index f54cd2d4fbc..00000000000 --- a/vendor/github.com/robertkrimen/otto/parser/marshal_test.go +++ /dev/null @@ -1,930 +0,0 @@ -package parser - -import ( - "bytes" - "encoding/json" - "fmt" - "os" - "reflect" - "strings" - "testing" - - "github.com/robertkrimen/otto/ast" -) - -func marshal(name string, children ...interface{}) interface{} { - if len(children) == 1 { - if name == "" { - return testMarshalNode(children[0]) - } - return map[string]interface{}{ - name: children[0], - } - } - map_ := map[string]interface{}{} - length := len(children) / 2 - for i := 0; i < length; i++ { - name := children[i*2].(string) - value := children[i*2+1] - map_[name] = value - } - if name == "" { - return map_ - } - return map[string]interface{}{ - name: map_, - } -} - -func testMarshalNode(node interface{}) interface{} { - switch node := node.(type) { - - // Expression - - case *ast.ArrayLiteral: - return marshal("Array", testMarshalNode(node.Value)) - - case *ast.AssignExpression: - return marshal("Assign", - "Left", testMarshalNode(node.Left), - "Right", testMarshalNode(node.Right), - ) - - case *ast.BinaryExpression: - return marshal("BinaryExpression", - "Operator", node.Operator.String(), - "Left", testMarshalNode(node.Left), - "Right", testMarshalNode(node.Right), - ) - - case *ast.BooleanLiteral: - return marshal("Literal", node.Value) - - case *ast.CallExpression: - return marshal("Call", - "Callee", testMarshalNode(node.Callee), - "ArgumentList", testMarshalNode(node.ArgumentList), - ) - - case *ast.ConditionalExpression: - return marshal("Conditional", - "Test", testMarshalNode(node.Test), - "Consequent", testMarshalNode(node.Consequent), - "Alternate", testMarshalNode(node.Alternate), - ) - - case *ast.DotExpression: - return marshal("Dot", - "Left", testMarshalNode(node.Left), - "Member", node.Identifier.Name, - ) - - case *ast.NewExpression: - return marshal("New", - "Callee", testMarshalNode(node.Callee), - "ArgumentList", testMarshalNode(node.ArgumentList), - ) - - case *ast.NullLiteral: - return marshal("Literal", nil) - - case *ast.NumberLiteral: - return marshal("Literal", node.Value) - - case *ast.ObjectLiteral: - return marshal("Object", testMarshalNode(node.Value)) - - case *ast.RegExpLiteral: - return marshal("Literal", node.Literal) - - case *ast.StringLiteral: - return marshal("Literal", node.Literal) - - case *ast.VariableExpression: - return []interface{}{node.Name, testMarshalNode(node.Initializer)} - - // Statement - - case *ast.Program: - return testMarshalNode(node.Body) - - case *ast.BlockStatement: - return marshal("BlockStatement", testMarshalNode(node.List)) - - case *ast.EmptyStatement: - return "EmptyStatement" - - case *ast.ExpressionStatement: - return testMarshalNode(node.Expression) - - case *ast.ForInStatement: - return marshal("ForIn", - "Into", marshal("", node.Into), - "Source", marshal("", node.Source), - "Body", marshal("", node.Body), - ) - - case *ast.FunctionLiteral: - return marshal("Function", testMarshalNode(node.Body)) - - case *ast.Identifier: - return marshal("Identifier", node.Name) - - case *ast.IfStatement: - if_ := marshal("", - "Test", testMarshalNode(node.Test), - "Consequent", testMarshalNode(node.Consequent), - ).(map[string]interface{}) - if node.Alternate != nil { - if_["Alternate"] = testMarshalNode(node.Alternate) - } - return marshal("If", if_) - - case *ast.LabelledStatement: - return marshal("Label", - "Name", node.Label.Name, - "Statement", testMarshalNode(node.Statement), - ) - case ast.Property: - return marshal("", - "Key", node.Key, - "Value", testMarshalNode(node.Value), - ) - - case *ast.ReturnStatement: - return marshal("Return", testMarshalNode(node.Argument)) - - case *ast.SequenceExpression: - return marshal("Sequence", testMarshalNode(node.Sequence)) - - case *ast.ThrowStatement: - return marshal("Throw", testMarshalNode(node.Argument)) - - case *ast.VariableStatement: - return marshal("Var", testMarshalNode(node.List)) - - } - - { - value := reflect.ValueOf(node) - if value.Kind() == reflect.Slice { - tmp0 := []interface{}{} - for index := 0; index < value.Len(); index++ { - tmp0 = append(tmp0, testMarshalNode(value.Index(index).Interface())) - } - return tmp0 - } - } - - if node != nil { - fmt.Fprintf(os.Stderr, "testMarshalNode(%T)\n", node) - } - - return nil -} - -func testMarshal(node interface{}) string { - value, err := json.Marshal(testMarshalNode(node)) - if err != nil { - panic(err) - } - return string(value) -} - -func TestParserAST(t *testing.T) { - tt(t, func() { - - test := func(inputOutput string) { - match := matchBeforeAfterSeparator.FindStringIndex(inputOutput) - input := strings.TrimSpace(inputOutput[0:match[0]]) - wantOutput := strings.TrimSpace(inputOutput[match[1]:]) - _, program, err := testParse(input) - is(err, nil) - haveOutput := testMarshal(program) - tmp0, tmp1 := bytes.Buffer{}, bytes.Buffer{} - json.Indent(&tmp0, []byte(haveOutput), "\t\t", " ") - json.Indent(&tmp1, []byte(wantOutput), "\t\t", " ") - is("\n\t\t"+tmp0.String(), "\n\t\t"+tmp1.String()) - } - - test(` - --- -[] - `) - - test(` - ; - --- -[ - "EmptyStatement" -] - `) - - test(` - ;;; - --- -[ - "EmptyStatement", - "EmptyStatement", - "EmptyStatement" -] - `) - - test(` - 1; true; abc; "abc"; null; - --- -[ - { - "Literal": 1 - }, - { - "Literal": true - }, - { - "Identifier": "abc" - }, - { - "Literal": "\"abc\"" - }, - { - "Literal": null - } -] - `) - - test(` - { 1; null; 3.14159; ; } - --- -[ - { - "BlockStatement": [ - { - "Literal": 1 - }, - { - "Literal": null - }, - { - "Literal": 3.14159 - }, - "EmptyStatement" - ] - } -] - `) - - test(` - new abc(); - --- -[ - { - "New": { - "ArgumentList": [], - "Callee": { - "Identifier": "abc" - } - } - } -] - `) - - test(` - new abc(1, 3.14159) - --- -[ - { - "New": { - "ArgumentList": [ - { - "Literal": 1 - }, - { - "Literal": 3.14159 - } - ], - "Callee": { - "Identifier": "abc" - } - } - } -] - `) - - test(` - true ? false : true - --- -[ - { - "Conditional": { - "Alternate": { - "Literal": true - }, - "Consequent": { - "Literal": false - }, - "Test": { - "Literal": true - } - } - } -] - `) - - test(` - true || false - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": true - }, - "Operator": "||", - "Right": { - "Literal": false - } - } - } -] - `) - - test(` - 0 + { abc: true } - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": 0 - }, - "Operator": "+", - "Right": { - "Object": [ - { - "Key": "abc", - "Value": { - "Literal": true - } - } - ] - } - } - } -] - `) - - test(` - 1 == "1" - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": 1 - }, - "Operator": "==", - "Right": { - "Literal": "\"1\"" - } - } - } -] - `) - - test(` - abc(1) - --- -[ - { - "Call": { - "ArgumentList": [ - { - "Literal": 1 - } - ], - "Callee": { - "Identifier": "abc" - } - } - } -] - `) - - test(` - Math.pow(3, 2) - --- -[ - { - "Call": { - "ArgumentList": [ - { - "Literal": 3 - }, - { - "Literal": 2 - } - ], - "Callee": { - "Dot": { - "Left": { - "Identifier": "Math" - }, - "Member": "pow" - } - } - } - } -] - `) - - test(` - 1, 2, 3 - --- -[ - { - "Sequence": [ - { - "Literal": 1 - }, - { - "Literal": 2 - }, - { - "Literal": 3 - } - ] - } -] - `) - - test(` - / abc / gim; - --- -[ - { - "Literal": "/ abc / gim" - } -] - `) - - test(` - if (0) - 1; - --- -[ - { - "If": { - "Consequent": { - "Literal": 1 - }, - "Test": { - "Literal": 0 - } - } - } -] - `) - - test(` - 0+function(){ - return; - } - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": 0 - }, - "Operator": "+", - "Right": { - "Function": { - "BlockStatement": [ - { - "Return": null - } - ] - } - } - } - } -] - `) - - test(` - xyzzy // Ignore it - // Ignore this - // And this - /* And all.. - - - - ... of this! - */ - "Nothing happens." - // And finally this - --- -[ - { - "Identifier": "xyzzy" - }, - { - "Literal": "\"Nothing happens.\"" - } -] - `) - - test(` - ((x & (x = 1)) !== 0) - --- -[ - { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": { - "Identifier": "x" - }, - "Operator": "\u0026", - "Right": { - "Assign": { - "Left": { - "Identifier": "x" - }, - "Right": { - "Literal": 1 - } - } - } - } - }, - "Operator": "!==", - "Right": { - "Literal": 0 - } - } - } -] - `) - - test(` - { abc: 'def' } - --- -[ - { - "BlockStatement": [ - { - "Label": { - "Name": "abc", - "Statement": { - "Literal": "'def'" - } - } - } - ] - } -] - `) - - test(` - // This is not an object, this is a string literal with a label! - ({ abc: 'def' }) - --- -[ - { - "Object": [ - { - "Key": "abc", - "Value": { - "Literal": "'def'" - } - } - ] - } -] - `) - - test(` - [,] - --- -[ - { - "Array": [ - null - ] - } -] - `) - - test(` - [,,] - --- -[ - { - "Array": [ - null, - null - ] - } -] - `) - - test(` - ({ get abc() {} }) - --- -[ - { - "Object": [ - { - "Key": "abc", - "Value": { - "Function": { - "BlockStatement": [] - } - } - } - ] - } -] - `) - - test(` - /abc/.source - --- -[ - { - "Dot": { - "Left": { - "Literal": "/abc/" - }, - "Member": "source" - } - } -] - `) - - test(` - xyzzy - - throw new TypeError("Nothing happens.") - --- -[ - { - "Identifier": "xyzzy" - }, - { - "Throw": { - "New": { - "ArgumentList": [ - { - "Literal": "\"Nothing happens.\"" - } - ], - "Callee": { - "Identifier": "TypeError" - } - } - } - } -] - `) - - // When run, this will call a type error to be thrown - // This is essentially the same as: - // - // var abc = 1(function(){})() - // - test(` - var abc = 1 - (function(){ - })() - --- -[ - { - "Var": [ - [ - "abc", - { - "Call": { - "ArgumentList": [], - "Callee": { - "Call": { - "ArgumentList": [ - { - "Function": { - "BlockStatement": [] - } - } - ], - "Callee": { - "Literal": 1 - } - } - } - } - } - ] - ] - } -] - `) - - test(` - "use strict" - --- -[ - { - "Literal": "\"use strict\"" - } -] - `) - - test(` - "use strict" - abc = 1 + 2 + 11 - --- -[ - { - "Literal": "\"use strict\"" - }, - { - "Assign": { - "Left": { - "Identifier": "abc" - }, - "Right": { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": { - "Literal": 1 - }, - "Operator": "+", - "Right": { - "Literal": 2 - } - } - }, - "Operator": "+", - "Right": { - "Literal": 11 - } - } - } - } - } -] - `) - - test(` - abc = function() { 'use strict' } - --- -[ - { - "Assign": { - "Left": { - "Identifier": "abc" - }, - "Right": { - "Function": { - "BlockStatement": [ - { - "Literal": "'use strict'" - } - ] - } - } - } - } -] - `) - - test(` - for (var abc in def) { - } - --- -[ - { - "ForIn": { - "Body": { - "BlockStatement": [] - }, - "Into": [ - "abc", - null - ], - "Source": { - "Identifier": "def" - } - } - } -] - `) - - test(` - abc = { - '"': "'", - "'": '"', - } - --- -[ - { - "Assign": { - "Left": { - "Identifier": "abc" - }, - "Right": { - "Object": [ - { - "Key": "\"", - "Value": { - "Literal": "\"'\"" - } - }, - { - "Key": "'", - "Value": { - "Literal": "'\"'" - } - } - ] - } - } - } -] - `) - - return - - test(` - if (!abc && abc.jkl(def) && abc[0] === +abc[0] && abc.length < ghi) { - } - --- -[ - { - "If": { - "Consequent": { - "BlockStatement": [] - }, - "Test": { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": null, - "Operator": "\u0026\u0026", - "Right": { - "Call": { - "ArgumentList": [ - { - "Identifier": "def" - } - ], - "Callee": { - "Dot": { - "Left": { - "Identifier": "abc" - }, - "Member": "jkl" - } - } - } - } - } - }, - "Operator": "\u0026\u0026", - "Right": { - "BinaryExpression": { - "Left": null, - "Operator": "===", - "Right": null - } - } - } - }, - "Operator": "\u0026\u0026", - "Right": { - "BinaryExpression": { - "Left": { - "Dot": { - "Left": { - "Identifier": "abc" - }, - "Member": "length" - } - }, - "Operator": "\u003c", - "Right": { - "Identifier": "ghi" - } - } - } - } - } - } - } -] - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/parser/parser_test.go b/vendor/github.com/robertkrimen/otto/parser/parser_test.go deleted file mode 100644 index 49c96f8a507..00000000000 --- a/vendor/github.com/robertkrimen/otto/parser/parser_test.go +++ /dev/null @@ -1,1023 +0,0 @@ -package parser - -import ( - "errors" - "regexp" - "strings" - "testing" - - "github.com/robertkrimen/otto/ast" - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/underscore" -) - -func firstErr(err error) error { - switch err := err.(type) { - case ErrorList: - return err[0] - } - return err -} - -var matchBeforeAfterSeparator = regexp.MustCompile(`(?m)^[ \t]*---$`) - -func testParse(src string) (parser *_parser, program *ast.Program, err error) { - return testParseWithMode(src, 0) -} - -func testParseWithMode(src string, mode Mode) (parser *_parser, program *ast.Program, err error) { - defer func() { - if tmp := recover(); tmp != nil { - switch tmp := tmp.(type) { - case string: - if strings.HasPrefix(tmp, "SyntaxError:") { - parser = nil - program = nil - err = errors.New(tmp) - return - } - } - panic(tmp) - } - }() - parser = _newParser("", src, 1, nil) - parser.mode = mode - program, err = parser.parse() - return -} - -func TestParseFile(t *testing.T) { - tt(t, func() { - _, err := ParseFile(nil, "", `/abc/`, 0) - is(err, nil) - - _, err = ParseFile(nil, "", `/(?!def)abc/`, IgnoreRegExpErrors) - is(err, nil) - - _, err = ParseFile(nil, "", `/(?!def)abc/`, 0) - is(err, "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) ") - - _, err = ParseFile(nil, "", `/(?!def)abc/; return`, IgnoreRegExpErrors) - is(err, "(anonymous): Line 1:15 Illegal return statement") - - _, err = ParseFile(nil, "/make-sure-file-path-is-returned-not-anonymous", `a..`, 0) - is(err, "/make-sure-file-path-is-returned-not-anonymous: Line 1:3 Unexpected token .") - }) -} - -func TestParseFunction(t *testing.T) { - tt(t, func() { - test := func(prm, bdy string, expect interface{}) *ast.FunctionLiteral { - function, err := ParseFunction(prm, bdy) - is(firstErr(err), expect) - return function - } - - test("a, b,c,d", "", nil) - - test("a, b;,c,d", "", "(anonymous): Line 1:15 Unexpected token ;") - - test("this", "", "(anonymous): Line 1:11 Unexpected token this") - - test("a, b, c, null", "", "(anonymous): Line 1:20 Unexpected token null") - - test("a, b,c,d", "return;", nil) - - test("a, b,c,d", "break;", "(anonymous): Line 2:1 Illegal break statement") - - test("a, b,c,d", "{}", nil) - }) -} - -func TestParserErr(t *testing.T) { - tt(t, func() { - test := func(input string, expect interface{}) (*ast.Program, *_parser) { - parser := _newParser("", input, 1, nil) - program, err := parser.parse() - is(firstErr(err), expect) - return program, parser - } - - program, parser := test("", nil) - - program, parser = test(` - var abc; - break; do { - } while(true); - `, "(anonymous): Line 3:9 Illegal break statement") - { - stmt := program.Body[1].(*ast.BadStatement) - is(parser.position(stmt.From).Column, 9) - is(parser.position(stmt.To).Column, 16) - is(parser.slice(stmt.From, stmt.To), "break; ") - } - - test("{", "(anonymous): Line 1:2 Unexpected end of input") - - test("}", "(anonymous): Line 1:1 Unexpected token }") - - test("3ea", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3in", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3in []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3e", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3e+", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3e-", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3x0", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("0x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("09", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("018", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("01.0", "(anonymous): Line 1:3 Unexpected number") - - test("01a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("0x3in[]", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\"Hello\nWorld\"", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\u203f = 10", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("/\n", "(anonymous): Line 1:1 Invalid regular expression: missing /") - - test("var x = /(s/g", "(anonymous): Line 1:9 Invalid regular expression: Unterminated group") - - test("0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("func() = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("(1 + 1) = 2", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - - test("1++", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - - test("1--", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - - test("--1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("for((1 + 1) in abc) def();", "(anonymous): Line 1:1 Invalid left-hand side in for-in") - - test("[", "(anonymous): Line 1:2 Unexpected end of input") - - test("[,", "(anonymous): Line 1:3 Unexpected end of input") - - test("1 + {", "(anonymous): Line 1:6 Unexpected end of input") - - test("1 + { abc:abc", "(anonymous): Line 1:14 Unexpected end of input") - - test("1 + { abc:abc,", "(anonymous): Line 1:15 Unexpected end of input") - - test("var abc = /\n/", "(anonymous): Line 1:11 Invalid regular expression: missing /") - - test("var abc = \"\n", "(anonymous): Line 1:11 Unexpected token ILLEGAL") - - test("var if = 0", "(anonymous): Line 1:5 Unexpected token if") - - test("abc + 0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("+abc = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("1 + (", "(anonymous): Line 1:6 Unexpected end of input") - - test("\n\n\n{", "(anonymous): Line 4:2 Unexpected end of input") - - test("\n/* Some multiline\ncomment */\n)", "(anonymous): Line 4:1 Unexpected token )") - - // TODO - //{ set 1 } - //{ get 2 } - //({ set: s(if) { } }) - //({ set s(.) { } }) - //({ set: s() { } }) - //({ set: s(a, b) { } }) - //({ get: g(d) { } }) - //({ get i() { }, i: 42 }) - //({ i: 42, get i() { } }) - //({ set i(x) { }, i: 42 }) - //({ i: 42, set i(x) { } }) - //({ get i() { }, get i() { } }) - //({ set i(x) { }, set i(x) { } }) - - test("function abc(if) {}", "(anonymous): Line 1:14 Unexpected token if") - - test("function abc(true) {}", "(anonymous): Line 1:14 Unexpected token true") - - test("function abc(false) {}", "(anonymous): Line 1:14 Unexpected token false") - - test("function abc(null) {}", "(anonymous): Line 1:14 Unexpected token null") - - test("function null() {}", "(anonymous): Line 1:10 Unexpected token null") - - test("function true() {}", "(anonymous): Line 1:10 Unexpected token true") - - test("function false() {}", "(anonymous): Line 1:10 Unexpected token false") - - test("function if() {}", "(anonymous): Line 1:10 Unexpected token if") - - test("a b;", "(anonymous): Line 1:3 Unexpected identifier") - - test("if.a", "(anonymous): Line 1:3 Unexpected token .") - - test("a if", "(anonymous): Line 1:3 Unexpected token if") - - test("a class", "(anonymous): Line 1:3 Unexpected reserved word") - - test("break\n", "(anonymous): Line 1:1 Illegal break statement") - - test("break 1;", "(anonymous): Line 1:7 Unexpected number") - - test("for (;;) { break 1; }", "(anonymous): Line 1:18 Unexpected number") - - test("continue\n", "(anonymous): Line 1:1 Illegal continue statement") - - test("continue 1;", "(anonymous): Line 1:10 Unexpected number") - - test("for (;;) { continue 1; }", "(anonymous): Line 1:21 Unexpected number") - - test("throw", "(anonymous): Line 1:1 Unexpected end of input") - - test("throw;", "(anonymous): Line 1:6 Unexpected token ;") - - test("throw \n", "(anonymous): Line 1:1 Unexpected end of input") - - test("for (var abc, def in {});", "(anonymous): Line 1:19 Unexpected token in") - - test("for ((abc in {});;);", nil) - - test("for ((abc in {}));", "(anonymous): Line 1:17 Unexpected token )") - - test("for (+abc in {});", "(anonymous): Line 1:1 Invalid left-hand side in for-in") - - test("if (false)", "(anonymous): Line 1:11 Unexpected end of input") - - test("if (false) abc(); else", "(anonymous): Line 1:23 Unexpected end of input") - - test("do", "(anonymous): Line 1:3 Unexpected end of input") - - test("while (false)", "(anonymous): Line 1:14 Unexpected end of input") - - test("for (;;)", "(anonymous): Line 1:9 Unexpected end of input") - - test("with (abc)", "(anonymous): Line 1:11 Unexpected end of input") - - test("try {}", "(anonymous): Line 1:1 Missing catch or finally after try") - - test("try {} catch {}", "(anonymous): Line 1:14 Unexpected token {") - - test("try {} catch () {}", "(anonymous): Line 1:15 Unexpected token )") - - test("\u203f = 1", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - // TODO - // const x = 12, y; - // const x, y = 12; - // const x; - // if(true) let a = 1; - // if(true) const a = 1; - - test(`new abc()."def"`, "(anonymous): Line 1:11 Unexpected string") - - test("/*", "(anonymous): Line 1:3 Unexpected end of input") - - test("/**", "(anonymous): Line 1:4 Unexpected end of input") - - test("/*\n\n\n", "(anonymous): Line 4:1 Unexpected end of input") - - test("/*\n\n\n*", "(anonymous): Line 4:2 Unexpected end of input") - - test("/*abc", "(anonymous): Line 1:6 Unexpected end of input") - - test("/*abc *", "(anonymous): Line 1:9 Unexpected end of input") - - test("\n]", "(anonymous): Line 2:1 Unexpected token ]") - - test("\r\n]", "(anonymous): Line 2:1 Unexpected token ]") - - test("\n\r]", "(anonymous): Line 3:1 Unexpected token ]") - - test("//\r\n]", "(anonymous): Line 2:1 Unexpected token ]") - - test("//\n\r]", "(anonymous): Line 3:1 Unexpected token ]") - - test("/abc\\\n/", "(anonymous): Line 1:1 Invalid regular expression: missing /") - - test("//\r \n]", "(anonymous): Line 3:1 Unexpected token ]") - - test("/*\r\n*/]", "(anonymous): Line 2:3 Unexpected token ]") - - test("/*\r \n*/]", "(anonymous): Line 3:3 Unexpected token ]") - - test("\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\abc", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u0000", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u200c = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u200D = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test(`"\`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test(`"\u`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("return", "(anonymous): Line 1:1 Illegal return statement") - - test("continue", "(anonymous): Line 1:1 Illegal continue statement") - - test("break", "(anonymous): Line 1:1 Illegal break statement") - - test("switch (abc) { default: continue; }", "(anonymous): Line 1:25 Illegal continue statement") - - test("do { abc } *", "(anonymous): Line 1:12 Unexpected token *") - - test("while (true) { break abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") - - test("while (true) { continue abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") - - test("abc: while (true) { (function(){ break abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") - - test("abc: while (true) { (function(){ abc: break abc; }); }", nil) - - test("abc: while (true) { (function(){ continue abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") - - test(`abc: if (0) break abc; else {}`, nil) - - test(`abc: if (0) { break abc; } else {}`, nil) - - test(`abc: if (0) { break abc } else {}`, nil) - - test("abc: while (true) { abc: while (true) {} }", "(anonymous): Line 1:21 Label 'abc' already exists") - - if false { - // TODO When strict mode is implemented - test("(function () { 'use strict'; delete abc; }())", "") - } - - test("_: _: while (true) {]", "(anonymous): Line 1:4 Label '_' already exists") - - test("_:\n_:\nwhile (true) {]", "(anonymous): Line 2:1 Label '_' already exists") - - test("_:\n _:\nwhile (true) {]", "(anonymous): Line 2:4 Label '_' already exists") - - test("/Xyzzy(?!Nothing happens)/", - "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) ") - - test("function(){}", "(anonymous): Line 1:9 Unexpected token (") - - test("\n/*/", "(anonymous): Line 2:4 Unexpected end of input") - - test("/*/.source", "(anonymous): Line 1:11 Unexpected end of input") - - test("/\\1/.source", "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid \\1 ") - - test("var class", "(anonymous): Line 1:5 Unexpected reserved word") - - test("var if", "(anonymous): Line 1:5 Unexpected token if") - - test("object Object", "(anonymous): Line 1:8 Unexpected identifier") - - test("[object Object]", "(anonymous): Line 1:9 Unexpected identifier") - - test("\\u0xyz", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test(`for (var abc, def in {}) {}`, "(anonymous): Line 1:19 Unexpected token in") - - test(`for (abc, def in {}) {}`, "(anonymous): Line 1:1 Invalid left-hand side in for-in") - - test(`for (var abc=def, ghi=("abc" in {}); true;) {}`, nil) - - { - // Semicolon insertion - - test("this\nif (1);", nil) - - test("while (1) { break\nif (1); }", nil) - - test("throw\nif (1);", "(anonymous): Line 1:1 Illegal newline after throw") - - test("(function(){ return\nif (1); })", nil) - - test("while (1) { continue\nif (1); }", nil) - - test("debugger\nif (1);", nil) - } - - { // Reserved words - - test("class", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.class = 1", nil) - test("var class;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("const", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.const = 1", nil) - test("var const;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("enum", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.enum = 1", nil) - test("var enum;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("export", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.export = 1", nil) - test("var export;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("extends", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.extends = 1", nil) - test("var extends;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("import", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.import = 1", nil) - test("var import;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("super", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.super = 1", nil) - test("var super;", "(anonymous): Line 1:5 Unexpected reserved word") - } - - { // Reserved words (strict) - - test(`implements`, nil) - test(`abc.implements = 1`, nil) - test(`var implements;`, nil) - - test(`interface`, nil) - test(`abc.interface = 1`, nil) - test(`var interface;`, nil) - - test(`let`, nil) - test(`abc.let = 1`, nil) - test(`var let;`, nil) - - test(`package`, nil) - test(`abc.package = 1`, nil) - test(`var package;`, nil) - - test(`private`, nil) - test(`abc.private = 1`, nil) - test(`var private;`, nil) - - test(`protected`, nil) - test(`abc.protected = 1`, nil) - test(`var protected;`, nil) - - test(`public`, nil) - test(`abc.public = 1`, nil) - test(`var public;`, nil) - - test(`static`, nil) - test(`abc.static = 1`, nil) - test(`var static;`, nil) - - test(`yield`, nil) - test(`abc.yield = 1`, nil) - test(`var yield;`, nil) - } - }) -} - -func TestParser(t *testing.T) { - tt(t, func() { - test := func(source string, chk interface{}) *ast.Program { - _, program, err := testParse(source) - is(firstErr(err), chk) - return program - } - - test(` - abc - -- - [] - `, "(anonymous): Line 3:13 Invalid left-hand side in assignment") - - test(` - abc-- - [] - `, nil) - - test("1\n[]\n", "(anonymous): Line 2:2 Unexpected token ]") - - test(` - function abc() { - } - abc() - `, nil) - - program := test("", nil) - - test("//", nil) - - test("/* */", nil) - - test("/** **/", nil) - - test("/*****/", nil) - - test("/*", "(anonymous): Line 1:3 Unexpected end of input") - - test("#", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("/**/#", "(anonymous): Line 1:5 Unexpected token ILLEGAL") - - test("new +", "(anonymous): Line 1:5 Unexpected token +") - - program = test(";", nil) - is(len(program.Body), 1) - is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1)) - - program = test(";;", nil) - is(len(program.Body), 2) - is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1)) - is(program.Body[1].(*ast.EmptyStatement).Semicolon, file.Idx(2)) - - program = test("1.2", nil) - is(len(program.Body), 1) - is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") - - program = test("/* */1.2", nil) - is(len(program.Body), 1) - is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") - - program = test("\n", nil) - is(len(program.Body), 0) - - test(` - if (0) { - abc = 0 - } - else abc = 0 - `, nil) - - test("if (0) abc = 0 else abc = 0", "(anonymous): Line 1:16 Unexpected token else") - - test(` - if (0) { - abc = 0 - } else abc = 0 - `, nil) - - test(` - if (0) { - abc = 1 - } else { - } - `, nil) - - test(` - do { - } while (true) - `, nil) - - test(` - try { - } finally { - } - `, nil) - - test(` - try { - } catch (abc) { - } finally { - } - `, nil) - - test(` - try { - } - catch (abc) { - } - finally { - } - `, nil) - - test(`try {} catch (abc) {} finally {}`, nil) - - test(` - do { - do { - } while (0) - } while (0) - `, nil) - - test(` - (function(){ - try { - if ( - 1 - ) { - return 1 - } - return 0 - } finally { - } - })() - `, nil) - - test("abc = ''\ndef", nil) - - test("abc = 1\ndef", nil) - - test("abc = Math\ndef", nil) - - test(`"\'"`, nil) - - test(` - abc = function(){ - } - abc = 0 - `, nil) - - test("abc.null = 0", nil) - - test("0x41", nil) - - test(`"\d"`, nil) - - test(`(function(){return this})`, nil) - - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); - abc = [101]; - abc.hasOwnProperty("0") && abc[0] === 101; - `, nil) - - test(`new abc()`, nil) - test(`new {}`, nil) - - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - } - else { - break - } - result = result + 1 - } - `, nil) - - test(` - while (0) { - if (0) { - continue - } - } - `, nil) - - test("var \u0061\u0062\u0063 = 0", nil) - - // 7_3_1 - test("var test7_3_1\nabc = 66;", nil) - test("var test7_3_1\u2028abc = 66;", nil) - - // 7_3_3 - test("//\u2028 =;", "(anonymous): Line 2:2 Unexpected token =") - - // 7_3_10 - test("var abc = \u2029;", "(anonymous): Line 2:1 Unexpected token ;") - test("var abc = \\u2029;", "(anonymous): Line 1:11 Unexpected token ILLEGAL") - test("var \\u0061\\u0062\\u0063 = 0;", nil) - - test("'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("'\nstr\ning\n'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - // S7.6_A4.3_T1 - test(`var $\u0030 = 0;`, nil) - - // S7.6.1.1_A1.1 - test(`switch = 1`, "(anonymous): Line 1:8 Unexpected token =") - - // S7.8.3_A2.1_T1 - test(`.0 === 0.0`, nil) - - // 7.8.5-1 - test("var regExp = /\\\rn/;", "(anonymous): Line 1:14 Invalid regular expression: missing /") - - // S7.8.5_A1.1_T2 - test("var regExp = /=/;", nil) - - // S7.8.5_A1.2_T1 - test("/*/", "(anonymous): Line 1:4 Unexpected end of input") - - // Sbp_7.9_A9_T3 - test(` - do { - ; - } while (false) true - `, nil) - - // S7.9_A10_T10 - test(` - {a:1 - } 3 - `, nil) - - test(` - abc - ++def - `, nil) - - // S7.9_A5.2_T1 - test(` - for(false;false - ) { - break; - } - `, "(anonymous): Line 3:13 Unexpected token )") - - // S7.9_A9_T8 - test(` - do {}; - while (false) - `, "(anonymous): Line 2:18 Unexpected token ;") - - // S8.4_A5 - test(` - "x\0y" - `, nil) - - // S9.3.1_A6_T1 - test(` - 10e10000 - `, nil) - - // 10.4.2-1-5 - test(` - "abc\ - def" - `, nil) - - test("'\\\n'", nil) - - test("'\\\r\n'", nil) - - //// 11.13.1-1-1 - test("42 = 42;", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - // S11.13.2_A4.2_T1.3 - test(` - abc /= "1" - `, nil) - - // 12.1-1 - test(` - try{};catch(){} - `, "(anonymous): Line 2:13 Missing catch or finally after try") - - // 12.1-3 - test(` - try{};finally{} - `, "(anonymous): Line 2:13 Missing catch or finally after try") - - // S12.6.3_A11.1_T3 - test(` - while (true) { - break abc; - } - `, "(anonymous): Line 3:17 Undefined label 'abc'") - - // S15.3_A2_T1 - test(`var x / = 1;`, "(anonymous): Line 1:7 Unexpected token /") - - test(` - function abc() { - if (0) - return; - else { - } - } - `, nil) - - test("//\u2028 var =;", "(anonymous): Line 2:6 Unexpected token =") - - test(` - throw - {} - `, "(anonymous): Line 2:13 Illegal newline after throw") - - // S7.6.1.1_A1.11 - test(` - function = 1 - `, "(anonymous): Line 2:22 Unexpected token =") - - // S7.8.3_A1.2_T1 - test(`0e1`, nil) - - test("abc = 1; abc\n++", "(anonymous): Line 2:3 Unexpected end of input") - - // --- - - test("({ get abc() {} })", nil) - - test(`for (abc.def in {}) {}`, nil) - - test(`while (true) { break }`, nil) - - test(`while (true) { continue }`, nil) - - test(`abc=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,def=/^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/`, nil) - - test(`(function() { try {} catch (err) {} finally {} return })`, nil) - - test(`0xde0b6b3a7640080.toFixed(0)`, nil) - - test(`/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/`, nil) - - test(`/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]/`, nil) - - test("var abc = 1;\ufeff", nil) - - test("\ufeff/* var abc = 1; */", nil) - - test(`if (-0x8000000000000000<=abc&&abc<=0x8000000000000000) {}`, nil) - - test(`(function(){debugger;return this;})`, nil) - - test(` - - `, nil) - - test(` - var abc = "" - debugger - `, nil) - - test(` - var abc = /\[\]$/ - debugger - `, nil) - - test(` - var abc = 1 / - 2 - debugger - `, nil) - }) -} - -func Test_parseStringLiteral(t *testing.T) { - tt(t, func() { - test := func(have, want string) { - have, err := parseStringLiteral(have) - is(err, nil) - is(have, want) - } - - test("", "") - - test("1(\\\\d+)", "1(\\d+)") - - test("\\u2029", "\u2029") - - test("abc\\uFFFFabc", "abc\uFFFFabc") - - test("[First line \\\nSecond line \\\n Third line\\\n. ]", - "[First line Second line Third line. ]") - - test("\\u007a\\x79\\u000a\\x78", "zy\nx") - - // S7.8.4_A4.2_T3 - test("\\a", "a") - test("\u0410", "\u0410") - - // S7.8.4_A5.1_T1 - test("\\0", "\u0000") - - // S8.4_A5 - test("\u0000", "\u0000") - - // 15.5.4.20 - test("'abc'\\\n'def'", "'abc''def'") - - // 15.5.4.20-4-1 - test("'abc'\\\r\n'def'", "'abc''def'") - - // Octal - test("\\0", "\000") - test("\\00", "\000") - test("\\000", "\000") - test("\\09", "\0009") - test("\\009", "\0009") - test("\\0009", "\0009") - test("\\1", "\001") - test("\\01", "\001") - test("\\001", "\001") - test("\\0011", "\0011") - test("\\1abc", "\001abc") - - test("\\\u4e16", "\u4e16") - - // err - test = func(have, want string) { - have, err := parseStringLiteral(have) - is(err.Error(), want) - is(have, "") - } - - test(`\u`, `invalid escape: \u: len("") != 4`) - test(`\u0`, `invalid escape: \u: len("0") != 4`) - test(`\u00`, `invalid escape: \u: len("00") != 4`) - test(`\u000`, `invalid escape: \u: len("000") != 4`) - - test(`\x`, `invalid escape: \x: len("") != 2`) - test(`\x0`, `invalid escape: \x: len("0") != 2`) - test(`\x0`, `invalid escape: \x: len("0") != 2`) - }) -} - -func Test_parseNumberLiteral(t *testing.T) { - tt(t, func() { - test := func(input string, expect interface{}) { - result, err := parseNumberLiteral(input) - is(err, nil) - is(result, expect) - } - - test("0", 0) - - test("0x8000000000000000", float64(9.223372036854776e+18)) - }) -} - -func TestPosition(t *testing.T) { - tt(t, func() { - parser := _newParser("", "// Lorem ipsum", 1, nil) - - // Out of range, idx0 (error condition) - is(parser.slice(0, 1), "") - is(parser.slice(0, 10), "") - - // Out of range, idx1 (error condition) - is(parser.slice(1, 128), "") - - is(parser.str[0:0], "") - is(parser.slice(1, 1), "") - - is(parser.str[0:1], "/") - is(parser.slice(1, 2), "/") - - is(parser.str[0:14], "// Lorem ipsum") - is(parser.slice(1, 15), "// Lorem ipsum") - - parser = _newParser("", "(function(){ return 0; })", 1, nil) - program, err := parser.parse() - is(err, nil) - - var node ast.Node - node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) - is(node.Idx0(), file.Idx(2)) - is(node.Idx1(), file.Idx(25)) - is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - is(parser.slice(node.Idx0(), node.Idx1()+1), "function(){ return 0; })") - is(parser.slice(node.Idx0(), node.Idx1()+2), "") - is(node.(*ast.FunctionLiteral).Source, "function(){ return 0; }") - - node = program - is(node.Idx0(), file.Idx(2)) - is(node.Idx1(), file.Idx(25)) - is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - - parser = _newParser("", "(function(){ return abc; })", 1, nil) - program, err = parser.parse() - is(err, nil) - node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) - is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }") - }) -} - -func BenchmarkParser(b *testing.B) { - src := underscore.Source() - b.ResetTimer() - - for i := 0; i < b.N; i++ { - parser := _newParser("", src, 1, nil) - parser.parse() - } -} diff --git a/vendor/github.com/robertkrimen/otto/parser/regexp_test.go b/vendor/github.com/robertkrimen/otto/parser/regexp_test.go deleted file mode 100644 index 3222db1a7b3..00000000000 --- a/vendor/github.com/robertkrimen/otto/parser/regexp_test.go +++ /dev/null @@ -1,149 +0,0 @@ -package parser - -import ( - "regexp" - "testing" -) - -func TestRegExp(t *testing.T) { - tt(t, func() { - { - // err - test := func(input string, expect interface{}) { - _, err := TransformRegExp(input) - is(err, expect) - } - - test("[", "Unterminated character class") - - test("(", "Unterminated group") - - test("(?=)", "re2: Invalid (?=) ") - - test("(?=)", "re2: Invalid (?=) ") - - test("(?!)", "re2: Invalid (?!) ") - - // An error anyway - test("(?=", "re2: Invalid (?=) ") - - test("\\1", "re2: Invalid \\1 ") - - test("\\90", "re2: Invalid \\90 ") - - test("\\9123456789", "re2: Invalid \\9123456789 ") - - test("\\(?=)", "Unmatched ')'") - - test(")", "Unmatched ')'") - } - - { - // err - test := func(input, expect string, expectErr interface{}) { - output, err := TransformRegExp(input) - is(output, expect) - is(err, expectErr) - } - - test("(?!)", "(?!)", "re2: Invalid (?!) ") - - test(")", "", "Unmatched ')'") - - test("(?!))", "", "re2: Invalid (?!) ") - - test("\\0", "\\0", nil) - - test("\\1", "\\1", "re2: Invalid \\1 ") - - test("\\9123456789", "\\9123456789", "re2: Invalid \\9123456789 ") - } - - { - // err - test := func(input string, expect string) { - result, err := TransformRegExp(input) - is(err, nil) - if is(result, expect) { - _, err := regexp.Compile(result) - if !is(err, nil) { - t.Log(result) - } - } - } - - test("", "") - - test("abc", "abc") - - test(`\abc`, `abc`) - - test(`\a\b\c`, `a\bc`) - - test(`\x`, `x`) - - test(`\c`, `c`) - - test(`\cA`, `\x01`) - - test(`\cz`, `\x1a`) - - test(`\ca`, `\x01`) - - test(`\cj`, `\x0a`) - - test(`\ck`, `\x0b`) - - test(`\+`, `\+`) - - test(`[\b]`, `[\x08]`) - - test(`\u0z01\x\undefined`, `u0z01xundefined`) - - test(`\\|'|\r|\n|\t|\u2028|\u2029`, `\\|'|\r|\n|\t|\x{2028}|\x{2029}`) - - test("]", "]") - - test("}", "}") - - test("%", "%") - - test("(%)", "(%)") - - test("(?:[%\\s])", "(?:[%\\s])") - - test("[[]", "[[]") - - test("\\101", "\\x41") - - test("\\51", "\\x29") - - test("\\051", "\\x29") - - test("\\175", "\\x7d") - - test("\\04", "\\x04") - - test(`<%([\s\S]+?)%>`, `<%([\s\S]+?)%>`) - - test(`(.)^`, "(.)^") - - test(`<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`, `<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`) - - test(`\$`, `\$`) - - test(`[G-b]`, `[G-b]`) - - test(`[G-b\0]`, `[G-b\0]`) - } - }) -} - -func TestTransformRegExp(t *testing.T) { - tt(t, func() { - pattern, err := TransformRegExp(`\s+abc\s+`) - is(err, nil) - is(pattern, `\s+abc\s+`) - is(regexp.MustCompile(pattern).MatchString("\t abc def"), true) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/parser_test.go b/vendor/github.com/robertkrimen/otto/parser_test.go deleted file mode 100644 index 7db43d239d7..00000000000 --- a/vendor/github.com/robertkrimen/otto/parser_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestPersistence(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - function abc() { return 1; } - abc.toString(); - `, "function abc() { return 1; }") - - test(` - function def() { return 3.14159; } - [ abc.toString(), def.toString() ]; - `, "function abc() { return 1; },function def() { return 3.14159; }") - - test(` - eval("function ghi() { return 'ghi' }"); - [ abc.toString(), def.toString(), ghi.toString() ]; - `, "function abc() { return 1; },function def() { return 3.14159; },function ghi() { return 'ghi' }") - - test(` - [ abc.toString(), def.toString(), ghi.toString() ]; - `, "function abc() { return 1; },function def() { return 3.14159; },function ghi() { return 'ghi' }") - - test(`/* - - - - - - - - - - */`, UndefinedValue()) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/reflect_test.go b/vendor/github.com/robertkrimen/otto/reflect_test.go deleted file mode 100644 index 23966b849ac..00000000000 --- a/vendor/github.com/robertkrimen/otto/reflect_test.go +++ /dev/null @@ -1,744 +0,0 @@ -package otto - -import ( - "fmt" - "math" - "reflect" - "testing" -) - -type _abcStruct struct { - Abc bool - Def int - Ghi string - Jkl interface{} - Mno _mnoStruct - Pqr map[string]int8 -} - -func (abc _abcStruct) String() string { - return abc.Ghi -} - -func (abc *_abcStruct) FuncPointer() string { - return "abc" -} - -func (abc _abcStruct) Func() { - return -} - -func (abc _abcStruct) FuncReturn1() string { - return "abc" -} - -func (abc _abcStruct) FuncReturn2() (string, error) { - return "def", nil -} - -func (abc _abcStruct) Func1Return1(a string) string { - return a -} - -func (abc _abcStruct) Func2Return1(x, y string) string { - return x + y -} - -func (abc _abcStruct) FuncEllipsis(xyz ...string) int { - return len(xyz) -} - -func (abc _abcStruct) FuncReturnStruct() _mnoStruct { - return _mnoStruct{} -} - -func (abs _abcStruct) Func1Int(i int) int { - return i + 1 -} - -func (abs _abcStruct) Func1Int8(i int8) int8 { - return i + 1 -} - -func (abs _abcStruct) Func1Int16(i int16) int16 { - return i + 1 -} - -func (abs _abcStruct) Func1Int32(i int32) int32 { - return i + 1 -} - -func (abs _abcStruct) Func1Int64(i int64) int64 { - return i + 1 -} - -func (abs _abcStruct) Func1Uint(i uint) uint { - return i + 1 -} - -func (abs _abcStruct) Func1Uint8(i uint8) uint8 { - return i + 1 -} - -func (abs _abcStruct) Func1Uint16(i uint16) uint16 { - return i + 1 -} - -func (abs _abcStruct) Func1Uint32(i uint32) uint32 { - return i + 1 -} - -func (abs _abcStruct) Func1Uint64(i uint64) uint64 { - return i + 1 -} - -func (abs _abcStruct) Func2Int(i, j int) int { - return i + j -} - -func (abs _abcStruct) Func2StringInt(s string, i int) string { - return fmt.Sprintf("%v:%v", s, i) -} - -func (abs _abcStruct) Func1IntVariadic(a ...int) int { - t := 0 - for _, i := range a { - t += i - } - return t -} - -func (abs _abcStruct) Func2IntVariadic(s string, a ...int) string { - t := 0 - for _, i := range a { - t += i - } - return fmt.Sprintf("%v:%v", s, t) -} - -func (abs _abcStruct) Func2IntArrayVariadic(s string, a ...[]int) string { - t := 0 - for _, i := range a { - for _, j := range i { - t += j - } - } - return fmt.Sprintf("%v:%v", s, t) -} - -type _mnoStruct struct { - Ghi string -} - -func (mno _mnoStruct) Func() string { - return "mno" -} - -func TestReflect(t *testing.T) { - if true { - return - } - tt(t, func() { - // Testing dbgf - // These should panic - toValue("Xyzzy").toReflectValue(reflect.Ptr) - stringToReflectValue("Xyzzy", reflect.Ptr) - }) -} - -func Test_reflectStruct(t *testing.T) { - tt(t, func() { - test, vm := test() - - // _abcStruct - { - abc := &_abcStruct{} - vm.Set("abc", abc) - - test(` - [ abc.Abc, abc.Ghi ]; - `, "false,") - - abc.Abc = true - abc.Ghi = "Nothing happens." - - test(` - [ abc.Abc, abc.Ghi ]; - `, "true,Nothing happens.") - - *abc = _abcStruct{} - - test(` - [ abc.Abc, abc.Ghi ]; - `, "false,") - - abc.Abc = true - abc.Ghi = "Xyzzy" - vm.Set("abc", abc) - - test(` - [ abc.Abc, abc.Ghi ]; - `, "true,Xyzzy") - - is(abc.Abc, true) - test(` - abc.Abc = false; - abc.Def = 451; - abc.Ghi = "Nothing happens."; - abc.abc = "Something happens."; - [ abc.Def, abc.abc ]; - `, "451,Something happens.") - is(abc.Abc, false) - is(abc.Def, 451) - is(abc.Ghi, "Nothing happens.") - - test(` - delete abc.Def; - delete abc.abc; - [ abc.Def, abc.abc ]; - `, "451,") - is(abc.Def, 451) - - test(` - abc.FuncPointer(); - `, "abc") - - test(` - abc.Func(); - `, "undefined") - - test(` - abc.FuncReturn1(); - `, "abc") - - test(` - abc.Func1Return1("abc"); - `, "abc") - - test(` - abc.Func2Return1("abc", "def"); - `, "abcdef") - - test(` - abc.FuncEllipsis("abc", "def", "ghi"); - `, 3) - - test(` - ret = abc.FuncReturn2(); - if (ret && ret.length && ret.length == 2 && ret[0] == "def" && ret[1] === undefined) { - true; - } else { - false; - } - `, true) - - test(` - abc.FuncReturnStruct(); - `, "[object Object]") - - test(` - abc.FuncReturnStruct().Func(); - `, "mno") - - test(` - abc.Func1Int(1); - `, 2) - - test(` - abc.Func1Int(0x01 & 0x01); - `, 2) - - test(`raise: - abc.Func1Int(1.1); - `, "RangeError: converting float64 to int would cause loss of precision") - - test(` - var v = 1; - abc.Func1Int(v + 1); - `, 3) - - test(` - abc.Func2Int(1, 2); - `, 3) - - test(` - abc.Func1Int8(1); - `, 2) - - test(` - abc.Func1Int16(1); - `, 2) - - test(` - abc.Func1Int32(1); - `, 2) - - test(` - abc.Func1Int64(1); - `, 2) - - test(` - abc.Func1Uint(1); - `, 2) - - test(` - abc.Func1Uint8(1); - `, 2) - - test(` - abc.Func1Uint16(1); - `, 2) - - test(` - abc.Func1Uint32(1); - `, 2) - - test(` - abc.Func1Uint64(1); - `, 2) - - test(` - abc.Func2StringInt("test", 1); - `, "test:1") - - test(` - abc.Func1IntVariadic(1, 2); - `, 3) - - test(` - abc.Func2IntVariadic("test", 1, 2); - `, "test:3") - - test(` - abc.Func2IntVariadic("test", [1, 2]); - `, "test:3") - - test(` - abc.Func2IntArrayVariadic("test", [1, 2]); - `, "test:3") - - test(` - abc.Func2IntArrayVariadic("test", [1, 2], [3, 4]); - `, "test:10") - - test(` - abc.Func2IntArrayVariadic("test", [[1, 2], [3, 4]]); - `, "test:10") - } - }) -} - -func Test_reflectMap(t *testing.T) { - tt(t, func() { - test, vm := test() - - // map[string]string - { - abc := map[string]string{ - "Xyzzy": "Nothing happens.", - "def": "1", - } - vm.Set("abc", abc) - - test(` - abc.xyz = "pqr"; - [ abc.Xyzzy, abc.def, abc.ghi ]; - `, "Nothing happens.,1,") - - is(abc["xyz"], "pqr") - } - - // map[string]float64 - { - abc := map[string]float64{ - "Xyzzy": math.Pi, - "def": 1, - } - vm.Set("abc", abc) - - test(` - abc.xyz = "pqr"; - abc.jkl = 10; - [ abc.Xyzzy, abc.def, abc.ghi ]; - `, "3.141592653589793,1,") - - is(abc["xyz"], math.NaN()) - is(abc["jkl"], float64(10)) - } - - // map[string]int32 - { - abc := map[string]int32{ - "Xyzzy": 3, - "def": 1, - } - vm.Set("abc", abc) - - test(` - abc.xyz = "pqr"; - abc.jkl = 10; - [ abc.Xyzzy, abc.def, abc.ghi ]; - `, "3,1,") - - is(abc["xyz"], 0) - is(abc["jkl"], int32(10)) - - test(` - delete abc["Xyzzy"]; - `) - - _, exists := abc["Xyzzy"] - is(exists, false) - is(abc["Xyzzy"], 0) - } - - // map[int32]string - { - abc := map[int32]string{ - 0: "abc", - 1: "def", - } - vm.Set("abc", abc) - - test(` - abc[2] = "pqr"; - //abc.jkl = 10; - abc[3] = 10; - [ abc[0], abc[1], abc[2], abc[3] ] - `, "abc,def,pqr,10") - - is(abc[2], "pqr") - is(abc[3], "10") - - test(` - delete abc[2]; - `) - - _, exists := abc[2] - is(exists, false) - } - - }) -} - -func Test_reflectMapIterateKeys(t *testing.T) { - tt(t, func() { - test, vm := test() - - // map[string]interface{} - { - abc := map[string]interface{}{ - "Xyzzy": "Nothing happens.", - "def": 1, - } - vm.Set("abc", abc) - test(` - var keys = []; - for (var key in abc) { - keys.push(key); - } - keys.sort(); - keys; - `, "Xyzzy,def") - } - - // map[uint]interface{} - { - abc := map[uint]interface{}{ - 456: "Nothing happens.", - 123: 1, - } - vm.Set("abc", abc) - test(` - var keys = []; - for (var key in abc) { - keys.push(key); - } - keys.sort(); - keys; - `, "123,456") - } - - // map[byte]interface{} - { - abc := map[byte]interface{}{ - 10: "Nothing happens.", - 20: 1, - } - vm.Set("abc", abc) - test(` - for (var key in abc) { - abc[key] = "123"; - } - `) - is(abc[10], "123") - is(abc[20], "123") - } - - }) -} - -func Test_reflectSlice(t *testing.T) { - tt(t, func() { - test, vm := test() - - // []bool - { - abc := []bool{ - false, - true, - true, - false, - } - vm.Set("abc", abc) - - test(` - abc; - `, "false,true,true,false") - - test(` - abc[0] = true; - abc[abc.length-1] = true; - delete abc[2]; - abc; - `, "true,true,false,true") - - is(abc, []bool{true, true, false, true}) - is(abc[len(abc)-1], true) - } - - // []int32 - { - abc := make([]int32, 4) - vm.Set("abc", abc) - - test(` - abc; - `, "0,0,0,0") - - test(`raise: - abc[0] = "42"; - abc[1] = 4.2; - abc[2] = 3.14; - abc; - `, "RangeError: 4.2 to reflect.Kind: int32") - - is(abc, []int32{42, 0, 0, 0}) - - test(` - delete abc[1]; - delete abc[2]; - `) - is(abc[1], 0) - is(abc[2], 0) - } - }) -} - -func Test_reflectArray(t *testing.T) { - tt(t, func() { - test, vm := test() - - // []bool - { - abc := [4]bool{ - false, - true, - true, - false, - } - vm.Set("abc", abc) - - test(` - abc; - `, "false,true,true,false") - // Unaddressable array - - test(` - abc[0] = true; - abc[abc.length-1] = true; - abc; - `, "false,true,true,false") - // Again, unaddressable array - - is(abc, [4]bool{false, true, true, false}) - is(abc[len(abc)-1], false) - // ... - } - // []int32 - { - abc := make([]int32, 4) - vm.Set("abc", abc) - - test(` - abc; - `, "0,0,0,0") - - test(`raise: - abc[0] = "42"; - abc[1] = 4.2; - abc[2] = 3.14; - abc; - `, "RangeError: 4.2 to reflect.Kind: int32") - - is(abc, []int32{42, 0, 0, 0}) - } - - // []bool - { - abc := [4]bool{ - false, - true, - true, - false, - } - vm.Set("abc", &abc) - - test(` - abc; - `, "false,true,true,false") - - test(` - abc[0] = true; - abc[abc.length-1] = true; - delete abc[2]; - abc; - `, "true,true,false,true") - - is(abc, [4]bool{true, true, false, true}) - is(abc[len(abc)-1], true) - } - - // no common type - { - test(` - abc = [1, 2.2, "str"]; - abc; - `, "1,2.2,str") - val, err := vm.Get("abc") - is(err, nil) - abc, err := val.Export() - is(err, nil) - is(abc, []interface{}{int64(1), 2.2, "str"}) - } - - // common type int - { - test(` - abc = [1, 2, 3]; - abc; - `, "1,2,3") - val, err := vm.Get("abc") - is(err, nil) - abc, err := val.Export() - is(err, nil) - is(abc, []int64{1, 2, 3}) - } - - // common type string - { - - test(` - abc = ["str1", "str2", "str3"]; - abc; - `, "str1,str2,str3") - - val, err := vm.Get("abc") - is(err, nil) - abc, err := val.Export() - is(err, nil) - is(abc, []string{"str1", "str2", "str3"}) - } - }) -} - -func Test_reflectArray_concat(t *testing.T) { - tt(t, func() { - test, vm := test() - - vm.Set("ghi", []string{"jkl", "mno"}) - vm.Set("pqr", []interface{}{"jkl", 42, 3.14159, true}) - test(` - var def = { - "abc": ["abc"], - "xyz": ["xyz"] - }; - xyz = pqr.concat(ghi, def.abc, def, def.xyz); - [ xyz, xyz.length ]; - `, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz,9") - }) -} - -func Test_reflectMapInterface(t *testing.T) { - tt(t, func() { - test, vm := test() - - { - abc := map[string]interface{}{ - "Xyzzy": "Nothing happens.", - "def": "1", - "jkl": "jkl", - } - vm.Set("abc", abc) - vm.Set("mno", &_abcStruct{}) - - test(` - abc.xyz = "pqr"; - abc.ghi = {}; - abc.jkl = 3.14159; - abc.mno = mno; - mno.Abc = true; - mno.Ghi = "Something happens."; - [ abc.Xyzzy, abc.def, abc.ghi, abc.mno ]; - `, "Nothing happens.,1,[object Object],[object Object]") - - is(abc["xyz"], "pqr") - is(abc["ghi"], "[object Object]") - is(abc["jkl"], float64(3.14159)) - mno, valid := abc["mno"].(*_abcStruct) - is(valid, true) - is(mno.Abc, true) - is(mno.Ghi, "Something happens.") - } - }) -} - -func TestPassthrough(t *testing.T) { - tt(t, func() { - test, vm := test() - - { - abc := &_abcStruct{ - Mno: _mnoStruct{ - Ghi: "", - }, - } - vm.Set("abc", abc) - - test(` - abc.Mno.Ghi; - `, "") - - vm.Set("pqr", map[string]int8{ - "xyzzy": 0, - "Nothing happens.": 1, - }) - - test(` - abc.Ghi = "abc"; - abc.Pqr = pqr; - abc.Pqr["Nothing happens."]; - `, 1) - - mno := _mnoStruct{ - Ghi: "", - } - vm.Set("mno", mno) - - test(` - abc.Mno = mno; - abc.Mno.Ghi; - `, "") - } - }) -} diff --git a/vendor/github.com/robertkrimen/otto/regexp_test.go b/vendor/github.com/robertkrimen/otto/regexp_test.go deleted file mode 100644 index 8e65ee46a42..00000000000 --- a/vendor/github.com/robertkrimen/otto/regexp_test.go +++ /dev/null @@ -1,290 +0,0 @@ -package otto - -import ( - "fmt" - "testing" -) - -func TestRegExp(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ - /abc/.toString(), - /abc/gim.toString(), - ""+/abc/gi.toString(), - new RegExp("1(\\d+)").toString(), - ]; - `, "/abc/,/abc/gim,/abc/gi,/1(\\d+)/") - - test(` - [ - new RegExp("abc").exec("123abc456"), - null === new RegExp("xyzzy").exec("123abc456"), - new RegExp("1(\\d+)").exec("123abc456"), - new RegExp("xyzzy").test("123abc456"), - new RegExp("1(\\d+)").test("123abc456"), - new RegExp("abc").exec("123abc456"), - ]; - `, "abc,true,123,23,false,true,abc") - - test(`new RegExp("abc").toString()`, "/abc/") - test(`new RegExp("abc", "g").toString()`, "/abc/g") - test(`new RegExp("abc", "mig").toString()`, "/abc/gim") - - result := test(`/(a)?/.exec('b')`, ",") - is(result._object().get("0"), "") - is(result._object().get("1"), "undefined") - is(result._object().get("length"), 2) - - result = test(`/(a)?(b)?/.exec('b')`, "b,,b") - is(result._object().get("0"), "b") - is(result._object().get("1"), "undefined") - is(result._object().get("2"), "b") - is(result._object().get("length"), 3) - - test(`/\u0041/.source`, "\\u0041") - test(`/\a/.source`, "\\a") - test(`/\;/.source`, "\\;") - - test(`/a\a/.source`, "a\\a") - test(`/,\;/.source`, ",\\;") - test(`/ \ /.source`, " \\ ") - - // Start sanity check... - test("eval(\"/abc/\").source", "abc") - test("eval(\"/\u0023/\").source", "#") - test("eval(\"/\u0058/\").source", "X") - test("eval(\"/\\\u0023/\").source == \"\\\u0023\"", true) - test("'0x' + '0058'", "0x0058") - test("'\\\\' + '0x' + '0058'", "\\0x0058") - // ...stop sanity check - - test(`abc = '\\' + String.fromCharCode('0x' + '0058'); eval('/' + abc + '/').source`, "\\X") - test(`abc = '\\' + String.fromCharCode('0x0058'); eval('/' + abc + '/').source == "\\\u0058"`, true) - test(`abc = '\\' + String.fromCharCode('0x0023'); eval('/' + abc + '/').source == "\\\u0023"`, true) - test(`abc = '\\' + String.fromCharCode('0x0078'); eval('/' + abc + '/').source == "\\\u0078"`, true) - - test(` - var abc = Object.getOwnPropertyDescriptor(RegExp, "prototype"); - [ [ typeof RegExp.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") - }) -} - -func TestRegExp_global(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = /(?:ab|cd)\d?/g; - var found = []; - do { - match = abc.exec("ab cd2 ab34 cd"); - if (match !== null) { - found.push(match[0]); - } else { - break; - } - } while (true); - found; - `, "ab,cd2,ab3,cd") - }) -} - -func TestRegExp_exec(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = /./g; - def = '123456'; - ghi = 0; - while (ghi < 100 && abc.exec(def) !== null) { - ghi += 1; - } - [ ghi, def.length, ghi == def.length ]; - `, "6,6,true") - - test(` - abc = /[abc](\d)?/g; - def = 'a0 b c1 d3'; - ghi = 0; - lastIndex = 0; - while (ghi < 100 && abc.exec(def) !== null) { - lastIndex = abc.lastIndex; - ghi += 1; - - } - [ ghi, lastIndex ]; - `, "3,7") - - test(` - var abc = /[abc](\d)?/.exec("a0 b c1 d3"); - [ abc.length, abc.input, abc.index, abc ]; - `, "2,a0 b c1 d3,0,a0,0") - - test(`raise: - var exec = RegExp.prototype.exec; - exec("Xyzzy"); - `, "TypeError: Calling RegExp.exec on a non-RegExp object") - - test(` - var abc = /\w{3}\d?/.exec("CE\uFFFFL\uFFDDbox127"); - [ abc.input.length, abc.length, abc.input, abc.index, abc ]; - `, "11,1,CE\uFFFFL\uFFDDbox127,5,box1") - - test(`RegExp.prototype.exec.length`, 1) - test(`RegExp.prototype.exec.prototype`, "undefined") - }) -} - -func TestRegExp_test(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`RegExp.prototype.test.length`, 1) - test(`RegExp.prototype.test.prototype`, "undefined") - }) -} - -func TestRegExp_toString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`RegExp.prototype.toString.length`, 0) - test(`RegExp.prototype.toString.prototype`, "undefined") - }) -} - -func TestRegExp_zaacbbbcac(t *testing.T) { - if true { - return - } - - tt(t, func() { - test, _ := test() - - // FIXME? TODO /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac") - test(` - var abc = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); - [ abc.length, abc.index, abc ]; - `, "6,0,zaacbbbcac,z,ac,a,,c") - }) -} - -func TestRegExpCopying(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = /xyzzy/i; - def = RegExp(abc); - abc.indicator = 1; - [ abc.indicator, def.indicator ]; - `, "1,1") - - test(`raise: - RegExp(new RegExp("\\d"), "1"); - `, "TypeError: Cannot supply flags when constructing one RegExp from another") - }) -} - -func TestRegExp_multiline(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = /s$/m.exec("pairs\nmakes\tdouble"); - [ abc.length, abc.index, abc ]; - `, "1,4,s") - }) -} - -func TestRegExp_source(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ /xyzzy/i.source, /./i.source ]; - `, "xyzzy,.") - - test(` - var abc = /./i; - var def = new RegExp(abc); - [ abc.source, def.source, abc.source === def.source ]; - `, ".,.,true") - - test(` - var abc = /./i; - var def = abc.hasOwnProperty("source"); - var ghi = abc.source; - abc.source = "xyzzy"; - [ def, abc.source ]; - `, "true,.") - }) -} - -func TestRegExp_newRegExp(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - Math.toString(); - var abc = new RegExp(Math,eval("\"g\"")); - [ abc, abc.global ]; - `, "/[object Math]/g,true") - }) -} - -func TestRegExp_flags(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = /./i; - var def = new RegExp(abc); - [ abc.multiline == def.multiline, abc.global == def.global, abc.ignoreCase == def.ignoreCase ]; - `, "true,true,true") - }) -} - -func TestRegExp_controlCharacter(t *testing.T) { - tt(t, func() { - test, _ := test() - - for code := 0x41; code < 0x5a; code++ { - string_ := string(code - 64) - test(fmt.Sprintf(` - var code = 0x%x; - var string = String.fromCharCode(code %% 32); - var result = (new RegExp("\\c" + String.fromCharCode(code))).exec(string); - [ code, string, result ]; - `, code), fmt.Sprintf("%d,%s,%s", code, string_, string_)) - } - }) -} - -func TestRegExp_notNotEmptyCharacterClass(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = /[\s\S]a/m.exec("a\naba"); - [ abc.length, abc.input, abc ]; - `, "1,a\naba,\na") - }) -} - -func TestRegExp_compile(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = /[\s\S]a/; - abc.compile('^\w+'); - `, "undefined") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/repl/autocompleter.go b/vendor/github.com/robertkrimen/otto/repl/autocompleter.go deleted file mode 100644 index 3256678dacd..00000000000 --- a/vendor/github.com/robertkrimen/otto/repl/autocompleter.go +++ /dev/null @@ -1,57 +0,0 @@ -package repl - -import ( - "regexp" - "strings" - - "github.com/robertkrimen/otto" -) - -type autoCompleter struct { - vm *otto.Otto -} - -var lastExpressionRegex = regexp.MustCompile(`[a-zA-Z0-9]([a-zA-Z0-9\.]*[a-zA-Z0-9])?\.?$`) - -func (a *autoCompleter) Do(line []rune, pos int) ([][]rune, int) { - lastExpression := lastExpressionRegex.FindString(string(line)) - - bits := strings.Split(lastExpression, ".") - - first := bits[:len(bits)-1] - last := bits[len(bits)-1] - - var l []string - - if len(first) == 0 { - c := a.vm.Context() - - l = make([]string, len(c.Symbols)) - - i := 0 - for k := range c.Symbols { - l[i] = k - i++ - } - } else { - r, err := a.vm.Eval(strings.Join(bits[:len(bits)-1], ".")) - if err != nil { - return nil, 0 - } - - if o := r.Object(); o != nil { - for _, v := range o.KeysByParent() { - l = append(l, v...) - } - } - } - - var r [][]rune - for _, s := range l { - if strings.HasPrefix(s, last) { - r = append(r, []rune(strings.TrimPrefix(s, last))) - } - } - - return r, len(last) -} diff --git a/vendor/github.com/robertkrimen/otto/repl/repl.go b/vendor/github.com/robertkrimen/otto/repl/repl.go deleted file mode 100644 index 268d913f110..00000000000 --- a/vendor/github.com/robertkrimen/otto/repl/repl.go +++ /dev/null @@ -1,149 +0,0 @@ -// Package repl implements a REPL (read-eval-print loop) for otto. -package repl - -import ( - "fmt" - "io" - "strings" - "sync/atomic" - - "github.com/robertkrimen/otto" - "gopkg.in/readline.v1" -) - -var counter uint32 - -// DebuggerHandler implements otto's debugger handler signature, providing a -// simple drop-in debugger implementation. -func DebuggerHandler(vm *otto.Otto) { - i := atomic.AddUint32(&counter, 1) - - // purposefully ignoring the error here - we can't do anything useful with - // it except panicking, and that'd be pretty rude. it'd be easy enough for a - // consumer to define an equivalent function that _does_ panic if desired. - _ = RunWithPrompt(vm, fmt.Sprintf("DEBUGGER[%d]> ", i)) -} - -// Run creates a REPL with the default prompt and no prelude. -func Run(vm *otto.Otto) error { - return RunWithOptions(vm, Options{}) -} - -// RunWithPrompt runs a REPL with the given prompt and no prelude. -func RunWithPrompt(vm *otto.Otto, prompt string) error { - return RunWithOptions(vm, Options{ - Prompt: prompt, - }) -} - -// RunWithPrelude runs a REPL with the default prompt and the given prelude. -func RunWithPrelude(vm *otto.Otto, prelude string) error { - return RunWithOptions(vm, Options{ - Prelude: prelude, - }) -} - -// RunWithPromptAndPrelude runs a REPL with the given prompt and prelude. -func RunWithPromptAndPrelude(vm *otto.Otto, prompt, prelude string) error { - return RunWithOptions(vm, Options{ - Prompt: prompt, - Prelude: prelude, - }) -} - -// Options contains parameters for configuring a REPL session. -type Options struct { - // Prompt controls what's shown at the beginning of the line. If not - // specified, this defaults to "> " - Prompt string - // Prelude is some text that's printed before control is given to the user. - // By default this is empty. If specified, this will be printed with a - // newline following it. - Prelude string - // Autocomplete controls whether this REPL session has autocompletion - // enabled. The way autocomplete is implemented can incur a performance - // penalty, so it's turned off by default. - Autocomplete bool -} - -// RunWithOptions runs a REPL with the given options. -func RunWithOptions(vm *otto.Otto, options Options) error { - prompt := options.Prompt - if prompt == "" { - prompt = "> " - } - - c := &readline.Config{ - Prompt: prompt, - } - - if options.Autocomplete { - c.AutoComplete = &autoCompleter{vm} - } - - rl, err := readline.NewEx(c) - if err != nil { - return err - } - - prelude := options.Prelude - if prelude != "" { - if _, err := io.Copy(rl.Stderr(), strings.NewReader(prelude+"\n")); err != nil { - return err - } - - rl.Refresh() - } - - var d []string - - for { - l, err := rl.Readline() - if err != nil { - if err == readline.ErrInterrupt { - if d != nil { - d = nil - - rl.SetPrompt(prompt) - rl.Refresh() - - continue - } - - break - } - - return err - } - - if l == "" { - continue - } - - d = append(d, l) - - s, err := vm.Compile("repl", strings.Join(d, "\n")) - if err != nil { - rl.SetPrompt(strings.Repeat(" ", len(prompt))) - } else { - rl.SetPrompt(prompt) - - d = nil - - v, err := vm.Eval(s) - if err != nil { - if oerr, ok := err.(*otto.Error); ok { - io.Copy(rl.Stdout(), strings.NewReader(oerr.String())) - } else { - io.Copy(rl.Stdout(), strings.NewReader(err.Error())) - } - } else { - rl.Stdout().Write([]byte(v.String() + "\n")) - } - } - - rl.Refresh() - } - - return rl.Close() -} diff --git a/vendor/github.com/robertkrimen/otto/runtime.go b/vendor/github.com/robertkrimen/otto/runtime.go index 6ebb1f982b7..5762bd0c31b 100644 --- a/vendor/github.com/robertkrimen/otto/runtime.go +++ b/vendor/github.com/robertkrimen/otto/runtime.go @@ -352,20 +352,52 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) reflect.Valu tt := t.Elem() - for i := int64(0); i < l; i++ { - p, ok := o.property[strconv.FormatInt(i, 10)] - if !ok { - continue - } + if o.class == "Array" { + for i := int64(0); i < l; i++ { + p, ok := o.property[strconv.FormatInt(i, 10)] + if !ok { + continue + } + + e, ok := p.value.(Value) + if !ok { + continue + } - e, ok := p.value.(Value) - if !ok { - continue + ev := self.convertCallParameter(e, tt) + + s.Index(int(i)).Set(ev) + } + } else if o.class == "GoArray" { + + var gslice bool + switch o.value.(type) { + case *_goSliceObject: + gslice = true + case *_goArrayObject: + gslice = false } - ev := self.convertCallParameter(e, tt) + for i := int64(0); i < l; i++ { + var p *_property + if gslice { + p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10)) + } else { + p = goArrayGetOwnProperty(o, strconv.FormatInt(i, 10)) + } + if p == nil { + continue + } + + e, ok := p.value.(Value) + if !ok { + continue + } + + ev := self.convertCallParameter(e, tt) - s.Index(int(i)).Set(ev) + s.Index(int(i)).Set(ev) + } } return s diff --git a/vendor/github.com/robertkrimen/otto/runtime_test.go b/vendor/github.com/robertkrimen/otto/runtime_test.go deleted file mode 100644 index eeb117383d0..00000000000 --- a/vendor/github.com/robertkrimen/otto/runtime_test.go +++ /dev/null @@ -1,834 +0,0 @@ -package otto - -import ( - "math" - "testing" -) - -// FIXME terst, Review tests - -func TestOperator(t *testing.T) { - tt(t, func() { - test, vm := test() - - test("xyzzy = 1") - test("xyzzy", 1) - - if true { - vm.Set("twoPlusTwo", func(FunctionCall) Value { - return toValue(5) - }) - test("twoPlusTwo( 1 )", 5) - - test("1 + twoPlusTwo( 1 )", 6) - - test("-1 + twoPlusTwo( 1 )", 4) - } - - test("result = 4") - test("result", 4) - - test("result += 1") - test("result", 5) - - test("result *= 2") - test("result", 10) - - test("result /= 2") - test("result", 5) - - test("result = 112.51 % 3.1") - test("result", 0.9100000000000019) - - test("result = 'Xyzzy'") - test("result", "Xyzzy") - - test("result = 'Xyz' + 'zy'") - test("result", "Xyzzy") - - test("result = \"Xyzzy\"") - test("result", "Xyzzy") - - test("result = 1; result = result") - test("result", 1) - - test(` - var result64 - = - 64 - , result10 = - 10 - `) - test("result64", 64) - test("result10", 10) - - test(` - result = 1; - result += 1; - `) - test("result", 2) - }) -} - -func TestFunction_(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - result = 2 - xyzzy = function() { - result += 1 - } - xyzzy() - result; - `, 3) - - test(` - xyzzy = function() { - return 1 - } - result = xyzzy() - `, 1) - - test(` - xyzzy = function() {} - result = xyzzy() - `, "undefined") - - test(` - xyzzy = function() { - return 64 - return 1 - } - result = xyzzy() - `, 64) - - test(` - result = 4 - xyzzy = function() { - result = 2 - } - xyzzy(); - result; - `, 2) - - test(` - result = 4 - xyzzy = function() { - var result - result = 2 - } - xyzzy(); - result; - `, 4) - - test(` - xyzzy = function() { - var result = 4 - return result - } - result = xyzzy() - `, 4) - - test(` - xyzzy = function() { - function test() { - var result = 1 - return result - } - return test() + 1 - } - result = xyzzy() + 1 - `, 3) - - test(` - xyzzy = function() { - function test() { - var result = 1 - return result - } - _xyzzy = 2 - var result = _xyzzy + test() + 1 - return result - } - result = xyzzy() + 1; - [ result, _xyzzy ]; - `, "5,2") - - test(` - xyzzy = function(apple) { - return 1 - } - result = xyzzy(1) - `, 1) - - test(` - xyzzy = function(apple) { - return apple + 1 - } - result = xyzzy(2) - `, 3) - - test(` - { - result = 1 - result += 1; - } - `, 2) - - test(` - var global = 1 - outer = function() { - var global = 2 - var inner = function(){ - return global - } - return inner() - } - result = outer() - `, 2) - - test(` - var apple = 1 - var banana = function() { - return apple - } - var cherry = function() { - var apple = 2 - return banana() - } - result = cherry() - `, 1) - - test(` - function xyz() { - }; - delete xyz; - `, false) - - test(` - var abc = function __factorial(def){ - if (def === 1) { - return def; - } else { - return __factorial(def-1)*def; - } - }; - abc(3); - `, 6) - }) -} - -func TestDoWhile(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - limit = 4; - result = 0; - do { - result = result + 1; - limit = limit - 1; - } while (limit); - result; - `, 4) - - test(` - result = eval("do {abc=1; break; abc=2;} while (0);"); - [ result, abc ]; - `, "1,1") - }) -} - -func TestContinueBreak(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - } - else { - break - } - result = result + 1 - } - [ result, limit ]; - `, "3,0") - - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - continue - } - else { - break - } - result = result + 1 - } - result; - `, 0) - - test(` - limit = 4 - result = 0 - do { - limit = limit - 1 - if (limit) { - continue - } - else { - break - } - result = result + 1 - } while (limit) - result; - `, 0) - }) -} - -func TestTryCatchError(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc - try { - 1() - } - catch (def) { - abc = def - } - abc; - `, "TypeError: 1 is not a function") - - }) -} - -func TestPositiveNegativeZero(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`1/0`, _Infinity) - test(`1/-0`, -_Infinity) - test(` - abc = -0 - 1/abc - `, -_Infinity) - }) -} - -func TestComparison(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - undefined = 1; undefined; - `, "undefined") - - test("undefined == undefined", true) - - test("undefined != undefined", false) - - test("null == null", true) - - test("null != null", false) - - test("0 == 1", false) - - is(negativeZero(), -0) - is(positiveZero(), 0) - is(math.Signbit(negativeZero()), true) - is(positiveZero() == negativeZero(), true) - - test("1 == 1", true) - - test("'Hello, World.' == 'Goodbye, World.'", false) - - test("'Hello, World.' == true", false) - - test("'Hello, World.' == false", false) - - test("'Hello, World.' == 1", false) - - test("1 == 'Hello, World.'", false) - - is(parseNumber("-1"), -1) - - test("0+Object", "0function Object() { [native code] }") - }) -} - -func TestComparisonRelational(t *testing.T) { - tt(t, func() { - test, _ := test() - - test("0 < 0", false) - - test("0 > 0", false) - - test("0 <= 0", true) - - test("0 >= 0", true) - - test("' 0' >= 0", true) - - test("'_ 0' >= 0", false) - }) -} - -func TestArguments(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - xyzzy = function() { - return arguments[0] - } - result = xyzzy("xyzzy"); - `, "xyzzy") - - test(` - xyzzy = function() { - arguments[0] = "abcdef" - return arguments[0] - } - result = xyzzy("xyzzy"); - `, "abcdef") - - test(` - xyzzy = function(apple) { - apple = "abcdef" - return arguments[0] - } - result = xyzzy("xyzzy"); - `, "abcdef") - - test(` - (function(){ - return arguments - })() - `, "[object Arguments]") - - test(` - (function(){ - return arguments.length - })() - `, 0) - - test(` - (function(){ - return arguments.length - })(1, 2, 4, 8, 10) - `, 5) - }) -} - -func TestObjectLiteral(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - ({}); - `, "[object Object]") - - test(` - var abc = { - xyzzy: "Nothing happens.", - get 1e2() { - return 3.14159; - }, - get null() { - return true; - }, - get "[\n]"() { - return "<>"; - } - }; - [ abc["1e2"], abc.null, abc["[\n]"] ]; - `, "3.14159,true,<>") - - test(` - var abc = { - xyzzy: "Nothing happens.", - set 1e2() { - this[3.14159] = 100; - return Math.random(); - }, - set null(def) { - this.def = def; - return Math.random(); - }, - }; - [ abc["1e2"] = Infinity, abc[3.14159], abc.null = "xyz", abc.def ]; - `, "Infinity,100,xyz,xyz") - }) -} - -func TestUnaryPrefix(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var result = 0; - [++result, result]; - `, "1,1") - - test(` - result = 0; - [--result, result]; - `, "-1,-1") - - test(` - var object = { valueOf: function() { return 1; } }; - result = ++object; - [ result, typeof result ]; - `, "2,number") - - test(` - var object = { valueOf: function() { return 1; } }; - result = --object; - [ result, typeof result ]; - `, "0,number") - }) -} - -func TestUnaryPostfix(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var result = 0; - result++; - [ result++, result ]; - `, "1,2") - - test(` - result = 0; - result--; - [ result--, result ]; - `, "-1,-2") - - test(` - var object = { valueOf: function() { return 1; } }; - result = object++; - [ result, typeof result ]; - `, "1,number") - - test(` - var object = { valueOf: function() { return 1; } }; - result = object-- - [ result, typeof result ]; - `, "1,number") - }) -} - -func TestBinaryLogicalOperation(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = true - def = false - ghi = false - jkl = false - result = abc && def || ghi && jkl - `, false) - - test(` - abc = true - def = true - ghi = false - jkl = false - result = abc && def || ghi && jkl - `, true) - - }) -} - -func TestBinaryBitwiseOperation(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = 1 & 2; - def = 1 & 3; - ghi = 1 | 3; - jkl = 1 ^ 2; - mno = 1 ^ 3; - [ abc, def, ghi, jkl, mno ]; - `, "0,1,3,3,2") - }) -} - -func TestBinaryShiftOperation(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - high = (1 << 30) - 1 + (1 << 30) - low = -high - 1 - abc = 23 << 1 - def = -105 >> 1 - ghi = 23 << 2 - jkl = 1 >>> 31 - mno = 1 << 64 - pqr = 1 >> 2 - stu = -2 >> 4 - vwx = low >> 1 - yz = low >>> 1 - `) - test("abc", 46) - test("def", -53) - test("ghi", 92) - test("jkl", 0) - test("mno", 1) - test("pqr", 0) - test("stu", -1) - test("vwx", -1073741824) - test("yz", 1073741824) - }) -} - -func TestParenthesizing(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = 1 + 2 * 3 - def = (1 + 2) * 3 - ghi = !(false || true) - jkl = !false || true - `) - test("abc", 7) - test("def", 9) - test("ghi", false) - test("jkl", true) - }) -} - -func Test_instanceof(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = {} instanceof Object; - `, true) - - test(` - abc = "abc" instanceof Object; - `, false) - - test(`raise: - abc = {} instanceof "abc"; - `, "TypeError: Expecting a function in instanceof check, but got: abc") - - test(`raise: - "xyzzy" instanceof Math; - `, "TypeError") - }) -} - -func TestIn(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = "prototype" in Object; - def = "xyzzy" in Object; - [ abc, def ]; - `, "true,false") - }) -} - -func Test_new(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = new Boolean; - def = new Boolean(1); - [ abc, def ]; - `, "false,true") - }) -} - -func TestNewFunction(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - new Function("return 11")() - `, 11) - - test(` - abc = 10 - new Function("abc += 1")() - abc - `, 11) - - test(` - new Function("a", "b", "c", "return b + 2")(10, 11, 12) - `, 13) - - test(`raise: - new 1 - `, "TypeError: 1 is not a function") - - // TODO Better error reporting: new this - test(`raise: - new this - `, "TypeError: [object environment] is not a function") - - test(`raise: - new {} - `, "TypeError: [object Object] is not a function") - }) -} - -func TestNewPrototype(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = { 'xyzzy': 'Nothing happens.' } - function Xyzzy(){} - Xyzzy.prototype = abc; - (new Xyzzy()).xyzzy - `, "Nothing happens.") - }) -} - -func TestBlock(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc=0; - var ghi; - def: { - do { - abc++; - if (!(abc < 10)) { - break def; - ghi = "ghi"; - } - } while (true); - } - [ abc,ghi ]; - `, "10,") - }) -} - -func Test_toString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [undefined+""] - `, "undefined") - }) -} - -func TestEvaluationOrder(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - var abc = 0; - abc < (abc = 1) === true; - `, true) - }) -} - -func TestClone(t *testing.T) { - tt(t, func() { - vm1 := New() - vm1.Run(` - var abc = 1; - `) - - vm2 := vm1.clone() - vm1.Run(` - abc += 2; - `) - vm2.Run(` - abc += 4; - `) - - is(vm1.getValue("abc"), 3) - is(vm2.getValue("abc"), 5) - }) -} - -func Test_debugger(t *testing.T) { - tt(t, func() { - called := false - - vm := New() - vm.SetDebuggerHandler(func(o *Otto) { - is(o, vm) - called = true - }) - - _, err := vm.Run(`debugger`) - is(err, nil) - is(called, true) - }) - - tt(t, func() { - called := false - - vm := New() - vm.SetDebuggerHandler(func(o *Otto) { - is(o, vm) - called = true - }) - - _, err := vm.Run(`null`) - is(err, nil) - is(called, false) - }) - - tt(t, func() { - vm := New() - - _, err := vm.Run(`debugger`) - is(err, nil) - }) -} - -func Test_random(t *testing.T) { - tt(t, func() { - vm := New() - vm.SetRandomSource(func() float64 { return 1 }) - - r, err := vm.Run(`Math.random()`) - is(err, nil) - f, err := r.ToFloat() - is(err, nil) - is(f, 1) - }) - - tt(t, func() { - vm := New() - - r1, err := vm.Run(`Math.random()`) - is(err, nil) - f1, err := r1.ToFloat() - is(err, nil) - - r2, err := vm.Run(`Math.random()`) - is(err, nil) - f2, err := r2.ToFloat() - is(err, nil) - - is(f1 == f2, false) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/script_test.go b/vendor/github.com/robertkrimen/otto/script_test.go deleted file mode 100644 index 9099237410c..00000000000 --- a/vendor/github.com/robertkrimen/otto/script_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestScript(t *testing.T) { - tt(t, func() { - vm := New() - - script, err := vm.Compile("xyzzy", `var abc; if (!abc) abc = 0; abc += 2; abc;`) - is(err, nil) - - str := script.String() - is(str, "// xyzzy\nvar abc; if (!abc) abc = 0; abc += 2; abc;") - - value, err := vm.Run(script) - is(err, nil) - is(value, 2) - - if true { - return - } - - tmp, err := script.marshalBinary() - is(err, nil) - is(len(tmp), 1228) - - { - script := &Script{} - err = script.unmarshalBinary(tmp) - is(err, nil) - - is(script.String(), str) - - value, err = vm.Run(script) - is(err, nil) - is(value, 4) - - tmp, err = script.marshalBinary() - is(err, nil) - is(len(tmp), 1228) - } - - { - script := &Script{} - err = script.unmarshalBinary(tmp) - is(err, nil) - - is(script.String(), str) - - value, err := vm.Run(script) - is(err, nil) - is(value, 6) - - tmp, err = script.marshalBinary() - is(err, nil) - is(len(tmp), 1228) - } - - { - version := scriptVersion - scriptVersion = "bogus" - - script := &Script{} - err = script.unmarshalBinary(tmp) - is(err, "version mismatch") - - is(script.String(), "// \n") - is(script.version, "") - is(script.program == nil, true) - is(script.filename, "") - is(script.src, "") - - scriptVersion = version - } - }) -} - -func TestFunctionCall_CallerLocation(t *testing.T) { - tt(t, func() { - vm := New() - vm.Set("loc", func(call FunctionCall) Value { - return toValue(call.CallerLocation()) - }) - script, err := vm.Compile("somefile.js", `var where = loc();`) - is(err, nil) - _, err = vm.Run(script) - is(err, nil) - where, err := vm.Get("where") - is(err, nil) - is(where, "somefile.js:1:13") - }) -} diff --git a/vendor/github.com/robertkrimen/otto/sourcemap_test.go b/vendor/github.com/robertkrimen/otto/sourcemap_test.go deleted file mode 100644 index afb8241059d..00000000000 --- a/vendor/github.com/robertkrimen/otto/sourcemap_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package otto - -import ( - "testing" -) - -const ( - testSourcemapCodeOriginal = "function functionA(argA, argB) {\n functionB(argA, argB);\n}\n\nfunction functionB(argA, argB) {\n functionExternal(argA, argB);\n}" - testSourcemapCodeMangled = "function functionA(argA,argB){functionB(argA,argB)}function functionB(argA,argB){functionExternal(argA,argB)}" - testSourcemapContent = `{"version":3,"sources":["hello.js"],"names":["functionA","argA","argB","functionB","functionExternal"],"mappings":"AAAA,QAASA,WAAUC,KAAMC,MACvBC,UAAUF,KAAMC,MAGlB,QAASC,WAAUF,KAAMC,MACvBE,iBAAiBH,KAAMC"}` - testSourcemapInline = "function functionA(argA,argB){functionB(argA,argB)}function functionB(argA,argB){functionExternal(argA,argB)}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImhlbGxvLmpzIl0sIm5hbWVzIjpbImZ1bmN0aW9uQSIsImFyZ0EiLCJhcmdCIiwiZnVuY3Rpb25CIiwiZnVuY3Rpb25FeHRlcm5hbCJdLCJtYXBwaW5ncyI6IkFBQUEsUUFBU0EsV0FBVUMsS0FBTUMsTUFDdkJDLFVBQVVGLEtBQU1DLE1BR2xCLFFBQVNDLFdBQVVGLEtBQU1DLE1BQ3ZCRSxpQkFBaUJILEtBQU1DIn0=" - testSourcemapOriginalStack = "ReferenceError: 'functionExternal' is not defined\n at functionB (hello.js:6:3)\n at functionA (hello.js:2:3)\n at :1:1\n" - testSourcemapMangledStack = "ReferenceError: 'functionExternal' is not defined\n at functionB (hello.js:1:82)\n at functionA (hello.js:1:31)\n at :1:1\n" - testSourcemapMappedStack = "ReferenceError: 'functionExternal' is not defined\n at functionB (hello.js:6:2)\n at functionA (hello.js:2:2)\n at :1:1\n" -) - -func TestSourceMapOriginalWithNoSourcemap(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.Compile("hello.js", testSourcemapCodeOriginal) - if err != nil { - panic(err) - } - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapOriginalStack) - }) -} - -func TestSourceMapMangledWithNoSourcemap(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.Compile("hello.js", testSourcemapCodeMangled) - if err != nil { - panic(err) - } - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapMangledStack) - }) -} - -func TestSourceMapMangledWithSourcemap(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.CompileWithSourceMap("hello.js", testSourcemapCodeMangled, testSourcemapContent) - if err != nil { - panic(err) - } - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapMappedStack) - }) -} - -func TestSourceMapMangledWithInlineSourcemap(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.CompileWithSourceMap("hello.js", testSourcemapInline, nil) - if err != nil { - panic(err) - } - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapMappedStack) - }) -} - -func TestSourceMapContextPosition(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.CompileWithSourceMap("hello.js", testSourcemapCodeMangled, testSourcemapContent) - if err != nil { - panic(err) - } - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - vm.Set("functionExternal", func(c FunctionCall) Value { - ctx := c.Otto.Context() - - is(ctx.Filename, "hello.js") - is(ctx.Line, 6) - is(ctx.Column, 2) - - return UndefinedValue() - }) - - if _, err := vm.Run(`functionA()`); err != nil { - panic(err) - } - }) -} - -func TestSourceMapContextStacktrace(t *testing.T) { - tt(t, func() { - vm := New() - - s, err := vm.CompileWithSourceMap("hello.js", testSourcemapCodeMangled, testSourcemapContent) - if err != nil { - panic(err) - } - - if _, err := vm.Run(s); err != nil { - panic(err) - } - - vm.Set("functionExternal", func(c FunctionCall) Value { - ctx := c.Otto.Context() - - is(ctx.Stacktrace, []string{ - "functionB (hello.js:6:2)", - "functionA (hello.js:2:2)", - ":1:1", - }) - - return UndefinedValue() - }) - - if _, err := vm.Run(`functionA()`); err != nil { - panic(err) - } - }) -} diff --git a/vendor/github.com/robertkrimen/otto/string_test.go b/vendor/github.com/robertkrimen/otto/string_test.go deleted file mode 100644 index b7b06324b7d..00000000000 --- a/vendor/github.com/robertkrimen/otto/string_test.go +++ /dev/null @@ -1,365 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = (new String("xyzzy")).length; - def = new String().length; - ghi = new String("Nothing happens.").length; - `) - test("abc", 5) - test("def", 0) - test("ghi", 16) - test(`"".length`, 0) - test(`"a\uFFFFbc".length`, 4) - test(`String(+0)`, "0") - test(`String(-0)`, "0") - test(`""+-0`, "0") - test(` - var abc = Object.getOwnPropertyDescriptor(String, "prototype"); - [ [ typeof String.prototype ], - [ abc.writable, abc.enumerable, abc.configurable ] ]; - `, "object,false,false,false") - }) -} - -func TestString_charAt(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = "xyzzy".charAt(0) - def = "xyzzy".charAt(11) - `) - test("abc", "x") - test("def", "") - }) -} - -func TestString_charCodeAt(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - abc = "xyzzy".charCodeAt(0) - def = "xyzzy".charCodeAt(11) - `) - test("abc", 120) - test("def", _NaN) - }) -} - -func TestString_fromCharCode(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`String.fromCharCode()`, []uint16{}) - test(`String.fromCharCode(88, 121, 122, 122, 121)`, []uint16{88, 121, 122, 122, 121}) // FIXME terst, Double-check these... - test(`String.fromCharCode("88", 121, 122, 122.05, 121)`, []uint16{88, 121, 122, 122, 121}) - test(`String.fromCharCode("88", 121, 122, NaN, 121)`, []uint16{88, 121, 122, 0, 121}) - test(`String.fromCharCode("0x21")`, []uint16{33}) - test(`String.fromCharCode(-1).charCodeAt(0)`, 65535) - test(`String.fromCharCode(65535).charCodeAt(0)`, 65535) - test(`String.fromCharCode(65534).charCodeAt(0)`, 65534) - test(`String.fromCharCode(4294967295).charCodeAt(0)`, 65535) - test(`String.fromCharCode(4294967294).charCodeAt(0)`, 65534) - test(`String.fromCharCode(0x0024) === "$"`, true) - }) -} - -func TestString_concat(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"".concat()`, "") - test(`"".concat("abc", "def")`, "abcdef") - test(`"".concat("abc", undefined, "def")`, "abcundefineddef") - }) -} - -func TestString_indexOf(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"".indexOf("")`, 0) - test(`"".indexOf("", 11)`, 0) - test(`"abc".indexOf("")`, 0) - test(`"abc".indexOf("", 11)`, 3) - test(`"abc".indexOf("a")`, 0) - test(`"abc".indexOf("bc")`, 1) - test(`"abc".indexOf("bc", 11)`, -1) - test(`"$$abcdabcd".indexOf("ab", function(){return -Infinity;}())`, 2) - test(`"$$abcdabcd".indexOf("ab", function(){return NaN;}())`, 2) - - test(` - var abc = {toString:function(){return "\u0041B";}} - var def = {valueOf:function(){return true;}} - var ghi = "ABB\u0041BABAB"; - var jkl; - with(ghi) { - jkl = indexOf(abc, def); - } - jkl; - `, 3) - }) -} - -func TestString_lastIndexOf(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"".lastIndexOf("")`, 0) - test(`"".lastIndexOf("", 11)`, 0) - test(`"abc".lastIndexOf("")`, 3) - test(`"abc".lastIndexOf("", 11)`, 3) - test(`"abc".lastIndexOf("a")`, 0) - test(`"abc".lastIndexOf("bc")`, 1) - test(`"abc".lastIndexOf("bc", 11)`, 1) - test(`"abc".lastIndexOf("bc", 0)`, -1) - test(`"abc".lastIndexOf("abcabcabc", 2)`, -1) - test(`"abc".lastIndexOf("abc", 0)`, 0) - test(`"abc".lastIndexOf("abc", 1)`, 0) - test(`"abc".lastIndexOf("abc", 2)`, 0) - test(`"abc".lastIndexOf("abc", 3)`, 0) - - test(` - abc = new Object(true); - abc.lastIndexOf = String.prototype.lastIndexOf; - abc.lastIndexOf(true, false); - `, 0) - }) -} - -func TestString_match(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc____abc_abc___".match(/__abc/)`, "__abc") - test(`"abc___abc_abc__abc__abc".match(/abc/g)`, "abc,abc,abc,abc,abc") - test(`"abc____abc_abc___".match(/__abc/g)`, "__abc") - test(` - abc = /abc/g - "abc___abc_abc__abc__abc".match(abc) - `, "abc,abc,abc,abc,abc") - test(`abc.lastIndex`, 23) - }) -} - -func TestString_replace(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc_abc".replace(/abc/, "$&123")`, "abc123_abc") - test(`"abc_abc".replace(/abc/g, "$&123")`, "abc123_abc123") - test(`"abc_abc_".replace(/abc/g, "$&123")`, "abc123_abc123_") - test(`"_abc_abc_".replace(/abc/g, "$&123")`, "_abc123_abc123_") - test(`"abc".replace(/abc/, "$&123")`, "abc123") - test(`"abc_".replace(/abc/, "$&123")`, "abc123_") - test("\"^abc$\".replace(/abc/, \"$`def\")", "^^def$") - test("\"^abc$\".replace(/abc/, \"def$`\")", "^def^$") - test(`"_abc_abd_".replace(/ab(c|d)/g, "$1")`, "_c_d_") - test(` - "_abc_abd_".replace(/ab(c|d)/g, function(){ - }) - `, "_undefined_undefined_") - - test(`"b".replace(/(a)?(b)?/, "_$1_")`, "__") - test(` - "b".replace(/(a)?(b)?/, function(a, b, c, d, e, f){ - return [a, b, c, d, e, f] - }) - `, "b,,b,0,b,") - - test(` - var abc = 'She sells seashells by the seashore.'; - var def = /sh/; - [ abc.replace(def, "$'" + 'sch') ]; - `, "She sells seaells by the seashore.schells by the seashore.") - }) -} - -func TestString_search(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc".search(/abc/)`, 0) - test(`"abc".search(/def/)`, -1) - test(`"abc".search(/c$/)`, 2) - test(`"abc".search(/$/)`, 3) - }) -} - -func TestString_split(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc".split("", 1)`, "a") - test(`"abc".split("", 2)`, "a,b") - test(`"abc".split("", 3)`, "a,b,c") - test(`"abc".split("", 4)`, "a,b,c") - test(`"abc".split("", 11)`, "a,b,c") - test(`"abc".split("", 0)`, "") - test(`"abc".split("")`, "a,b,c") - - test(`"abc".split(undefined)`, "abc") - - test(`"__1__3_1__2__".split("_")`, ",,1,,3,1,,2,,") - - test(`"__1__3_1__2__".split(/_/)`, ",,1,,3,1,,2,,") - - test(`"ab".split(/a*/)`, ",b") - - test(`_ = "Aboldandcoded".split(/<(\/)?([^<>]+)>/)`, "A,,B,bold,/,B,and,,CODE,coded,/,CODE,") - test(`_.length`, 13) - test(`_[1] === undefined`, true) - test(`_[12] === ""`, true) - - test(` - var abc = new String("one-1 two-2 three-3"); - var def = abc.split(new RegExp); - - [ def.constructor === Array, abc.length, def.length, def.join('') ]; - `, "true,19,19,one-1 two-2 three-3") - }) -} - -func TestString_slice(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc".slice()`, "abc") - test(`"abc".slice(0)`, "abc") - test(`"abc".slice(0,11)`, "abc") - test(`"abc".slice(0,-1)`, "ab") - test(`"abc".slice(-1,11)`, "c") - test(`abc = "abc"; abc.slice(abc.length+1, 0)`, "") - }) -} - -func TestString_substring(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc".substring()`, "abc") - test(`"abc".substring(0)`, "abc") - test(`"abc".substring(0,11)`, "abc") - test(`"abc".substring(11,0)`, "abc") - test(`"abc".substring(0,-1)`, "") - test(`"abc".substring(-1,11)`, "abc") - test(`"abc".substring(11,1)`, "bc") - test(`"abc".substring(1)`, "bc") - test(`"abc".substring(Infinity, Infinity)`, "") - }) -} - -func TestString_toCase(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`"abc".toLowerCase()`, "abc") - test(`"ABC".toLowerCase()`, "abc") - test(`"abc".toLocaleLowerCase()`, "abc") - test(`"ABC".toLocaleLowerCase()`, "abc") - test(`"abc".toUpperCase()`, "ABC") - test(`"ABC".toUpperCase()`, "ABC") - test(`"abc".toLocaleUpperCase()`, "ABC") - test(`"ABC".toLocaleUpperCase()`, "ABC") - }) -} - -func Test_floatToString(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`String(-1234567890)`, "-1234567890") - test(`-+String(-(-1234567890))`, -1234567890) - test(`String(-1e128)`, "-1e+128") - test(`String(0.12345)`, "0.12345") - test(`String(-0.00000012345)`, "-1.2345e-7") - test(`String(0.0000012345)`, "0.0000012345") - test(`String(1000000000000000000000)`, "1e+21") - test(`String(1e21)`, "1e+21") - test(`String(1E21)`, "1e+21") - test(`String(-1000000000000000000000)`, "-1e+21") - test(`String(-1e21)`, "-1e+21") - test(`String(-1E21)`, "-1e+21") - test(`String(0.0000001)`, "1e-7") - test(`String(1e-7)`, "1e-7") - test(`String(1E-7)`, "1e-7") - test(`String(-0.0000001)`, "-1e-7") - test(`String(-1e-7)`, "-1e-7") - test(`String(-1E-7)`, "-1e-7") - }) -} - -func TestString_indexing(t *testing.T) { - tt(t, func() { - test, _ := test() - - // Actually a test of stringToArrayIndex, under the hood. - test(` - abc = new String("abc"); - index = Math.pow(2, 32); - [ abc.length, abc[index], abc[index+1], abc[index+2], abc[index+3] ]; - `, "3,,,,") - }) -} - -func TestString_trim(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`' \n abc \t \n'.trim();`, "abc") - test(`" abc\u000B".trim()`, "abc") - test(`"abc ".trim()`, "abc") - test(` - var a = "\u180Eabc \u000B " - var b = a.trim() - a.length + b.length - `, 10) - }) -} - -func TestString_trimLeft(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`" abc\u000B".trimLeft()`, "abc\u000B") - test(`"abc ".trimLeft()`, "abc ") - test(` - var a = "\u180Eabc \u000B " - var b = a.trimLeft() - a.length + b.length - `, 13) - }) -} - -func TestString_trimRight(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`" abc\u000B".trimRight()`, " abc") - test(`" abc ".trimRight()`, " abc") - test(` - var a = "\u180Eabc \u000B " - var b = a.trimRight() - a.length + b.length - `, 11) - }) -} - -func TestString_localeCompare(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`'a'.localeCompare('c');`, -1) - test(`'c'.localeCompare('a');`, 1) - test(`'a'.localeCompare('a');`, 0) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/terst/terst.go b/vendor/github.com/robertkrimen/otto/terst/terst.go deleted file mode 100644 index a25ca8b9c80..00000000000 --- a/vendor/github.com/robertkrimen/otto/terst/terst.go +++ /dev/null @@ -1,669 +0,0 @@ -// This file was AUTOMATICALLY GENERATED by terst-import (smuggol) from github.com/robertkrimen/terst - -/* -Package terst is a terse (terst = test + terse), easy-to-use testing library for Go. - -terst is compatible with (and works via) the standard testing package: http://golang.org/pkg/testing - - var is = terst.Is - - func Test(t *testing.T) { - terst.Terst(t, func() { - is("abc", "abc") - - is(1, ">", 0) - - var abc []int - is(abc, nil) - } - } - -Do not import terst directly, instead use `terst-import` to copy it into your testing environment: - -https://github.com/robertkrimen/terst/tree/master/terst-import - - $ go get github.com/robertkrimen/terst/terst-import - - $ terst-import - -*/ -package terst - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "reflect" - "regexp" - "runtime" - "strings" - "sync" - "testing" - "time" -) - -// Is compares two values (got & expect) and returns true if the comparison is true, -// false otherwise. In addition, if the comparison is false, Is will report the error -// in a manner similar to testing.T.Error(...). Is also takes an optional argument, -// a comparator, that changes how the comparison is made. The following -// comparators are available: -// -// == # got == expect (default) -// != # got != expect -// -// > # got > expect (float32, uint, uint16, int, int64, ...) -// >= # got >= expect -// < # got < expect -// <= # got <= expect -// -// =~ # regexp.MustCompile(expect).Match{String}(got) -// !~ # !regexp.MustCompile(expect).Match{String}(got) -// -// Basic usage with the default comparator (==): -// -// Is(, ) -// -// Specifying a different comparator: -// -// Is(, , ) -// -// A simple comparison: -// -// Is(2 + 2, 4) -// -// A bit trickier: -// -// Is(1, ">", 0) -// Is(2 + 2, "!=", 5) -// Is("Nothing happens.", "=~", `ing(\s+)happens\.$`) -// -// Is should only be called under a Terst(t, ...) call. For a standalone version, -// use IsErr. If no scope is found and the comparison is false, then Is will panic the error. -// -func Is(arguments ...interface{}) bool { - err := IsErr(arguments...) - if err != nil { - call := Caller() - if call == nil { - panic(err) - } - call.Error(err) - return false - } - return true -} - -type ( - // ErrFail indicates a comparison failure (e.g. 0 > 1). - ErrFail error - - // ErrInvalid indicates an invalid comparison (e.g. bool == string). - ErrInvalid error -) - -var errInvalid = errors.New("invalid") - -var registry = struct { - table map[uintptr]*_scope - lock sync.RWMutex -}{ - table: map[uintptr]*_scope{}, -} - -func registerScope(pc uintptr, scope *_scope) { - registry.lock.Lock() - defer registry.lock.Unlock() - registry.table[pc] = scope -} - -func scope() *_scope { - scope, _ := findScope() - return scope -} - -func floatCompare(a float64, b float64) int { - if a > b { - return 1 - } else if a < b { - return -1 - } - // NaN == NaN - return 0 -} - -func bigIntCompare(a *big.Int, b *big.Int) int { - return a.Cmp(b) -} - -func bigInt(value int64) *big.Int { - return big.NewInt(value) -} - -func bigUint(value uint64) *big.Int { - return big.NewInt(0).SetUint64(value) -} - -type _toString interface { - String() string -} - -func toString(value interface{}) (string, error) { - switch value := value.(type) { - case string: - return value, nil - case _toString: - return value.String(), nil - case error: - return value.Error(), nil - } - return "", errInvalid -} - -func matchString(got string, expect *regexp.Regexp) (int, error) { - if expect.MatchString(got) { - return 0, nil - } - return -1, nil -} - -func match(got []byte, expect *regexp.Regexp) (int, error) { - if expect.Match(got) { - return 0, nil - } - return -1, nil -} - -func compareMatch(got, expect interface{}) (int, error) { - switch got := got.(type) { - case []byte: - switch expect := expect.(type) { - case string: - matcher, err := regexp.Compile(expect) - if err != nil { - return 0, err - } - return match(got, matcher) - case *regexp.Regexp: - return match(got, expect) - } - default: - if got, err := toString(got); err == nil { - switch expect := expect.(type) { - case string: - matcher, err := regexp.Compile(expect) - if err != nil { - return 0, err - } - return matchString(got, matcher) - case *regexp.Regexp: - return matchString(got, expect) - } - } else { - return 0, err - } - } - return 0, errInvalid -} - -func floatPromote(value reflect.Value) (float64, error) { - kind := value.Kind() - if reflect.Int <= kind && kind <= reflect.Int64 { - return float64(value.Int()), nil - } - if reflect.Uint <= kind && kind <= reflect.Uint64 { - return float64(value.Uint()), nil - } - if reflect.Float32 <= kind && kind <= reflect.Float64 { - return value.Float(), nil - } - return 0, errInvalid -} - -func bigIntPromote(value reflect.Value) (*big.Int, error) { - kind := value.Kind() - if reflect.Int <= kind && kind <= reflect.Int64 { - return bigInt(value.Int()), nil - } - if reflect.Uint <= kind && kind <= reflect.Uint64 { - return bigUint(value.Uint()), nil - } - return nil, errInvalid -} - -func compareOther(got, expect interface{}) (int, error) { - { - switch expect.(type) { - case float32, float64: - return compareNumber(got, expect) - case uint, uint8, uint16, uint32, uint64: - return compareNumber(got, expect) - case int, int8, int16, int32, int64: - return compareNumber(got, expect) - case string: - var err error - got, err = toString(got) - if err != nil { - return 0, err - } - case nil: - got := reflect.ValueOf(got) - switch got.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface: - if got.IsNil() { - return 0, nil - } - return -1, nil - case reflect.Invalid: // reflect.Invalid: var abc interface{} = nil - return 0, nil - } - return 0, errInvalid - } - } - - if reflect.ValueOf(got).Type() != reflect.ValueOf(expect).Type() { - return 0, errInvalid - } - - if reflect.DeepEqual(got, expect) { - return 0, nil - } - return -1, nil -} - -func compareNumber(got, expect interface{}) (int, error) { - { - got := reflect.ValueOf(got) - k0 := got.Kind() - expect := reflect.ValueOf(expect) - k1 := expect.Kind() - if reflect.Float32 <= k0 && k0 <= reflect.Float64 || - reflect.Float32 <= k1 && k1 <= reflect.Float64 { - got, err := floatPromote(got) - if err != nil { - return 0, err - } - expect, err := floatPromote(expect) - if err != nil { - return 0, err - } - return floatCompare(got, expect), nil - } else { - got, err := bigIntPromote(got) - if err != nil { - return 0, err - } - expect, err := bigIntPromote(expect) - if err != nil { - return 0, err - } - return got.Cmp(expect), nil - } - } - - return 0, errInvalid -} - -// IsErr compares two values (got & expect) and returns nil if the comparison is true, an ErrFail if -// the comparison is false, or an ErrInvalid if the comparison is invalid. IsErr also -// takes an optional argument, a comparator, that changes how the comparison is made. -// -// Is & IsErr are similar but different: -// -// Is(...) // Should only be called within a Terst(...) call -// IsErr(...) // A standalone comparator, the same as Is, just without the automatic reporting -// -func IsErr(arguments ...interface{}) error { - var got, expect interface{} - comparator := "==" - switch len(arguments) { - case 0, 1: - return fmt.Errorf("invalid number of arguments to IsErr: %d", len(arguments)) - case 2: - got, expect = arguments[0], arguments[1] - default: - if value, ok := arguments[1].(string); ok { - comparator = value - } else { - return fmt.Errorf("invalid comparator: %v", arguments[1]) - } - got, expect = arguments[0], arguments[2] - } - - var result int - var err error - - switch comparator { - case "<", "<=", ">", ">=": - result, err = compareNumber(got, expect) - case "=~", "!~": - result, err = compareMatch(got, expect) - case "==", "!=": - result, err = compareOther(got, expect) - default: - return fmt.Errorf("invalid comparator: %s", comparator) - } - - if err == errInvalid { - return ErrInvalid(fmt.Errorf( - "\nINVALID (%s):\n got: %v (%T)\n expected: %v (%T)", - comparator, - got, got, - expect, expect, - )) - } else if err != nil { - return err - } - - equality, pass := false, false - - switch comparator { - case "==", "=~": - equality = true - pass = result == 0 - case "!=", "!~": - equality = true - pass = result != 0 - case "<": - pass = result < 0 - case "<=": - pass = result <= 0 - case ">": - pass = result > 0 - case ">=": - pass = result >= 0 - } - - if !pass { - if equality { - if comparator[1] == '~' { - if value, ok := got.([]byte); ok { - return ErrFail(fmt.Errorf( - "\nFAIL (%s)\n got: %s %v%s\nexpected: %v%s", - comparator, - value, got, typeKindString(got), - expect, typeKindString(expect), - )) - } - } - return ErrFail(fmt.Errorf( - "\nFAIL (%s)\n got: %v%s\nexpected: %v%s", - comparator, - got, typeKindString(got), - expect, typeKindString(expect), - )) - } - return ErrFail(fmt.Errorf( - "\nFAIL (%s)\n got: %v%s\nexpected: %s %v%s", - comparator, - got, typeKindString(got), - comparator, expect, typeKindString(expect), - )) - } - - return nil -} - -func typeKindString(value interface{}) string { - reflectValue := reflect.ValueOf(value) - kind := reflectValue.Kind().String() - result := fmt.Sprintf("%T", value) - if kind == result { - if kind == "string" { - return "" - } - return fmt.Sprintf(" (%T)", value) - } - return fmt.Sprintf(" (%T=%s)", value, kind) -} - -func (scope *_scope) reset() { - scope.name = "" - scope.output = scope.output[:] - scope.start = time.Time{} - scope.duration = 0 -} - -// Terst creates a testing scope, where Is can be called and errors will be reported -// according to the top-level location of the comparison, and not where the Is call -// actually takes place. For example: -// -// func test(value int) { -// Is(value, 5) // <--- This failure is reported below. -// } -// -// Terst(t, func(){ -// -// Is(2, ">", 3) // <--- An error is reported here. -// -// test(5) // <--- An error is reported here. -// -// }) -// -func Terst(t *testing.T, arguments ...func()) { - scope := &_scope{ - t: t, - } - - pc, _, _, ok := runtime.Caller(1) // TODO Associate with the Test... func - if !ok { - panic("Here be dragons.") - } - - _, scope.testFunc = findTestFunc() - - registerScope(pc, scope) - - for _, fn := range arguments { - func() { - scope.reset() - name := scope.testFunc.Name() - index := strings.LastIndex(scope.testFunc.Name(), ".") - if index >= 0 { - name = name[index+1:] + "(Terst)" - } else { - name = "(Terst)" - } - name = "(Terst)" - scope.name = name - scope.start = time.Now() - defer func() { - scope.duration = time.Now().Sub(scope.start) - if err := recover(); err != nil { - scope.t.Fail() - scope.report() - panic(err) - } - scope.report() - }() - fn() - }() - } -} - -// From "testing" -func (scope *_scope) report() { - format := "~~~ %s: (Terst)\n%s" - if scope.t.Failed() { - fmt.Printf(format, "FAIL", scope.output) - } else if testing.Verbose() && len(scope.output) > 0 { - fmt.Printf(format, "PASS", scope.output) - } -} - -func (scope *_scope) log(call _entry, str string) { - scope.mu.Lock() - defer scope.mu.Unlock() - scope.output = append(scope.output, decorate(call, str)...) -} - -// decorate prefixes the string with the file and line of the call site -// and inserts the final newline if needed and indentation tabs for formascing. -func decorate(call _entry, s string) string { - - file, line := call.File, call.Line - if call.PC > 0 { - // Truncate file name at last file name separator. - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - } else { - file = "???" - line = 1 - } - buf := new(bytes.Buffer) - // Every line is indented at least one tab. - buf.WriteByte('\t') - fmt.Fprintf(buf, "%s:%d: ", file, line) - lines := strings.Split(s, "\n") - if l := len(lines); l > 1 && lines[l-1] == "" { - lines = lines[:l-1] - } - for i, line := range lines { - if i > 0 { - // Second and subsequent lines are indented an extra tab. - buf.WriteString("\n\t\t") - } - buf.WriteString(line) - } - buf.WriteByte('\n') - return buf.String() -} - -func findScope() (*_scope, _entry) { - registry.lock.RLock() - defer registry.lock.RUnlock() - table := registry.table - depth := 2 // Starting depth - call := _entry{} - for { - pc, _, _, ok := runtime.Caller(depth) - if !ok { - break - } - if scope, exists := table[pc]; exists { - pc, file, line, _ := runtime.Caller(depth - 3) // Terst(...) + func(){}() + fn() => ???() - call.PC = pc - call.File = file - call.Line = line - return scope, call - } - depth++ - } - return nil, _entry{} -} - -// Call is a reference to a line immediately under a Terst testing scope. -type Call struct { - scope *_scope - entry _entry -} - -// Caller will search the stack, looking for a Terst testing scope. If a scope -// is found, then Caller returns a Call for logging errors, accessing testing.T, etc. -// If no scope is found, Caller returns nil. -func Caller() *Call { - scope, entry := findScope() - if scope == nil { - return nil - } - return &Call{ - scope: scope, - entry: entry, - } -} - -// TestFunc returns the *runtime.Func entry for the top-level Test...(t testing.T) -// function. -func (cl *Call) TestFunc() *runtime.Func { - return cl.scope.testFunc -} - -// T returns the original testing.T passed to Terst(...) -func (cl *Call) T() *testing.T { - return cl.scope.t -} - -// Log is the terst version of `testing.T.Log` -func (cl *Call) Log(arguments ...interface{}) { - cl.scope.log(cl.entry, fmt.Sprintln(arguments...)) -} - -// Logf is the terst version of `testing.T.Logf` -func (cl *Call) Logf(format string, arguments ...interface{}) { - cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...)) -} - -// Error is the terst version of `testing.T.Error` -func (cl *Call) Error(arguments ...interface{}) { - cl.scope.log(cl.entry, fmt.Sprintln(arguments...)) - cl.scope.t.Fail() -} - -// Errorf is the terst version of `testing.T.Errorf` -func (cl *Call) Errorf(format string, arguments ...interface{}) { - cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...)) - cl.scope.t.Fail() -} - -// Skip is the terst version of `testing.T.Skip` -func (cl *Call) Skip(arguments ...interface{}) { - cl.scope.log(cl.entry, fmt.Sprintln(arguments...)) - cl.scope.t.SkipNow() -} - -// Skipf is the terst version of `testing.T.Skipf` -func (cl *Call) Skipf(format string, arguments ...interface{}) { - cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...)) - cl.scope.t.SkipNow() -} - -type _scope struct { - t *testing.T - testFunc *runtime.Func - name string - mu sync.RWMutex - output []byte - start time.Time - duration time.Duration -} - -type _entry struct { - PC uintptr - File string - Line int - Func *runtime.Func -} - -func _findFunc(match string) (_entry, *runtime.Func) { - depth := 2 // Starting depth - for { - pc, file, line, ok := runtime.Caller(depth) - if !ok { - break - } - fn := runtime.FuncForPC(pc) - name := fn.Name() - if index := strings.LastIndex(name, match); index >= 0 { - // Assume we have an instance of TestXyzzy in a _test file - return _entry{ - PC: pc, - File: file, - Line: line, - Func: fn, - }, fn - } - depth++ - } - return _entry{}, nil -} - -func findTestFunc() (_entry, *runtime.Func) { - return _findFunc(".Test") -} - -func findTerstFunc() (_entry, *runtime.Func) { - return _findFunc(".Terst") -} diff --git a/vendor/github.com/robertkrimen/otto/test/Makefile b/vendor/github.com/robertkrimen/otto/test/Makefile deleted file mode 100644 index ac76fdeacfc..00000000000 --- a/vendor/github.com/robertkrimen/otto/test/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -.PHONY: test fetch clean build err report - -TESTER := tester - -test: $(TESTER) - for test in test-*.js; do ./$^ -test=true $$test 1>/dev/null || exit 1; done - @echo PASS - -report: $(TESTER) - ./$^ -report | grep -v "MT READY" - -fetch: $(TESTER) - ./$^ fetch - -build: - go build -a -o $(TESTER) - -$(TESTER): tester.go - $(MAKE) build - -clean: - rm -f test-*.js - rm -f $(TESTER) - -err: $(TESTER) - for test in test-*.js; do ./$^ $$test; done 2>$@ diff --git a/vendor/github.com/robertkrimen/otto/test/tester.go b/vendor/github.com/robertkrimen/otto/test/tester.go deleted file mode 100644 index ea694fd8def..00000000000 --- a/vendor/github.com/robertkrimen/otto/test/tester.go +++ /dev/null @@ -1,196 +0,0 @@ -package main - -import ( - "encoding/json" - "flag" - "fmt" - "io/ioutil" - "net/http" - "os" - "regexp" - "strings" - "sync" - "text/tabwriter" - - "github.com/robertkrimen/otto" - "github.com/robertkrimen/otto/parser" -) - -var flag_test *bool = flag.Bool("test", false, "") -var flag_report *bool = flag.Bool("report", false, "") - -var match_ReferenceError_not_defined = regexp.MustCompile(`^ReferenceError: \S+ is not defined$`) -var match_lookahead = regexp.MustCompile(`Invalid regular expression: re2: Invalid \(\?[=!]\) `) -var match_backreference = regexp.MustCompile(`Invalid regular expression: re2: Invalid \\\d `) -var match_TypeError_undefined = regexp.MustCompile(`^TypeError: Cannot access member '[^']+' of undefined$`) - -var target = map[string]string{ - "test-angular-bindonce.js": "fail", // (anonymous): Line 1:944 Unexpected token ( (and 40 more errors) - "test-jsforce.js": "fail", // (anonymous): Line 9:28329 RuneError (and 5 more errors) - "test-chaplin.js": "parse", // Error: Chaplin requires Common.js or AMD modules - "test-dropbox.js.js": "parse", // Error: dropbox.js loaded in an unsupported JavaScript environment. - "test-epitome.js": "parse", // TypeError: undefined is not a function - "test-portal.js": "parse", // TypeError - "test-reactive-coffee.js": "parse", // Dependencies are not met for reactive: _ and $ not found - "test-scriptaculous.js": "parse", // script.aculo.us requires the Prototype JavaScript framework >= 1.6.0.3 - "test-waypoints.js": "parse", // TypeError: undefined is not a function - "test-webuploader.js": "parse", // Error: `jQuery` is undefined - "test-xuijs.js": "parse", // TypeError: undefined is not a function -} - -// http://cdnjs.com/ -// http://api.cdnjs.com/libraries - -func fetch(name, location string) error { - response, err := http.Get(location) - if err != nil { - return err - } - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) - if err != nil { - return err - } - - if !strings.HasSuffix(location, ".js") { - return nil - } - - filename := "test-" + name + ".js" - fmt.Println(filename, len(body)) - return ioutil.WriteFile(filename, body, 0644) -} - -func test(filename string) error { - script, err := ioutil.ReadFile(filename) - if err != nil { - return err - } - - if !*flag_report { - fmt.Fprintln(os.Stdout, filename, len(script)) - } - - parse := false - option := target[filename] - - if option != "parse" { - vm := otto.New() - _, err = vm.Run(string(script)) - if err != nil { - value := err.Error() - switch { - case match_ReferenceError_not_defined.MatchString(value): - case match_TypeError_undefined.MatchString(value): - case match_lookahead.MatchString(value): - case match_backreference.MatchString(value): - default: - return err - } - parse = true - } - } - - if parse { - _, err = parser.ParseFile(nil, filename, string(script), parser.IgnoreRegExpErrors) - if err != nil { - return err - } - target[filename] = "parse" - } - - return nil -} - -func main() { - flag.Parse() - - filename := "" - - err := func() error { - - if flag.Arg(0) == "fetch" { - response, err := http.Get("http://api.cdnjs.com/libraries") - if err != nil { - return err - } - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) - if err != nil { - return err - } - - var tmp map[string]interface{} - - err = json.Unmarshal(body, &tmp) - if err != nil { - return err - } - - var wg sync.WaitGroup - - for _, value := range tmp["results"].([]interface{}) { - wg.Add(1) - library := value.(map[string]interface{}) - go func() { - defer wg.Done() - fetch(library["name"].(string), library["latest"].(string)) - }() - } - - wg.Wait() - - return nil - } - - if *flag_report { - files, err := ioutil.ReadDir(".") - if err != nil { - return err - } - writer := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) - fmt.Fprintln(writer, "", "\t| Status") - fmt.Fprintln(writer, "---", "\t| ---") - for _, file := range files { - filename := file.Name() - if !strings.HasPrefix(filename, "test-") { - continue - } - err := test(filename) - option := target[filename] - name := strings.TrimPrefix(strings.TrimSuffix(filename, ".js"), "test-") - if err == nil { - switch option { - case "": - fmt.Fprintln(writer, name, "\t| pass") - case "parse": - fmt.Fprintln(writer, name, "\t| pass (parse)") - case "re2": - continue - fmt.Fprintln(writer, name, "\t| unknown (re2)") - } - } else { - fmt.Fprintln(writer, name, "\t| fail") - } - } - writer.Flush() - return nil - } - - filename = flag.Arg(0) - return test(filename) - - }() - if err != nil { - if filename != "" { - if *flag_test && target[filename] == "fail" { - goto exit - } - fmt.Fprintf(os.Stderr, "%s: %s\n", filename, err.Error()) - } else { - fmt.Fprintln(os.Stderr, err) - } - os.Exit(64) - } -exit: -} diff --git a/vendor/github.com/robertkrimen/otto/testing_test.go b/vendor/github.com/robertkrimen/otto/testing_test.go deleted file mode 100644 index 0ff40e8f86f..00000000000 --- a/vendor/github.com/robertkrimen/otto/testing_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package otto - -import ( - "./terst" - "errors" - "strings" - "testing" - "time" -) - -func tt(t *testing.T, arguments ...func()) { - halt := errors.New("A test was taking too long") - timer := time.AfterFunc(2*time.Second, func() { - panic(halt) - }) - defer func() { - timer.Stop() - }() - terst.Terst(t, arguments...) -} - -func is(arguments ...interface{}) bool { - var got, expect interface{} - - switch len(arguments) { - case 0, 1: - return terst.Is(arguments...) - case 2: - got, expect = arguments[0], arguments[1] - default: - got, expect = arguments[0], arguments[2] - } - - switch value := got.(type) { - case Value: - if value.value != nil { - got = value.value - } - case *Error: - if value != nil { - got = value.Error() - } - if expect == nil { - // FIXME This is weird - expect = "" - } - } - - if len(arguments) == 2 { - arguments[0] = got - arguments[1] = expect - } else { - arguments[0] = got - arguments[2] = expect - } - - return terst.Is(arguments...) -} - -func test(arguments ...interface{}) (func(string, ...interface{}) Value, *_tester) { - tester := newTester() - if len(arguments) > 0 { - tester.test(arguments[0].(string)) - } - return tester.test, tester -} - -type _tester struct { - vm *Otto -} - -func newTester() *_tester { - return &_tester{ - vm: New(), - } -} - -func (self *_tester) Get(name string) (Value, error) { - return self.vm.Get(name) -} - -func (self *_tester) Set(name string, value interface{}) Value { - err := self.vm.Set(name, value) - is(err, nil) - if err != nil { - terst.Caller().T().FailNow() - } - return self.vm.getValue(name) -} - -func (self *_tester) Run(src interface{}) (Value, error) { - return self.vm.Run(src) -} - -func (self *_tester) test(name string, expect ...interface{}) Value { - vm := self.vm - raise := false - defer func() { - if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() - } - if raise { - if len(expect) > 0 { - is(caught, expect[0]) - } - } else { - dbg("Panic, caught:", caught) - panic(caught) - } - } - }() - var value Value - var err error - if isIdentifier(name) { - value = vm.getValue(name) - } else { - source := name - index := strings.Index(source, "raise:") - if index == 0 { - raise = true - source = source[6:] - source = strings.TrimLeft(source, " ") - } - value, err = vm.runtime.cmpl_run(source, nil) - if err != nil { - panic(err) - } - } - value = value.resolve() - if len(expect) > 0 { - is(value, expect[0]) - } - return value -} diff --git a/vendor/github.com/robertkrimen/otto/type_go_slice_test.go b/vendor/github.com/robertkrimen/otto/type_go_slice_test.go deleted file mode 100644 index b604aae8204..00000000000 --- a/vendor/github.com/robertkrimen/otto/type_go_slice_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package otto - -import "testing" - -type GoSliceTest []int - -func (s GoSliceTest) Sum() int { - sum := 0 - for _, v := range s { - sum += v - } - return sum -} - -func TestGoSlice(t *testing.T) { - tt(t, func() { - test, vm := test() - vm.Set("TestSlice", GoSliceTest{1, 2, 3}) - is(test(`TestSlice.length`).export(), 3) - is(test(`TestSlice[1]`).export(), 2) - is(test(`TestSlice.Sum()`).export(), 6) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore/Makefile b/vendor/github.com/robertkrimen/otto/underscore/Makefile deleted file mode 100644 index fc872917f02..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -.PHONY: source - -source: source.go - -underscore.js: - curl -kL http://underscorejs.org/underscore.js > $@ - -source.go: underscore.js - go-bindata -f underscore -p underscore -u true < $< 2>/dev/null | grep -v '^//' | gofmt > $@ - head -4 $< >> $@ - mv $< .. diff --git a/vendor/github.com/robertkrimen/otto/underscore/README.markdown b/vendor/github.com/robertkrimen/otto/underscore/README.markdown deleted file mode 100644 index bce37b69532..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore/README.markdown +++ /dev/null @@ -1,53 +0,0 @@ -# underscore --- - import "github.com/robertkrimen/otto/underscore" - -Package underscore contains the source for the JavaScript utility-belt library. - - import ( - _ "github.com/robertkrimen/otto/underscore" - ) - // Every Otto runtime will now include underscore - -http://underscorejs.org - -https://github.com/documentcloud/underscore - -By importing this package, you'll automatically load underscore every time you -create a new Otto runtime. - -To prevent this behavior, you can do the following: - - import ( - "github.com/robertkrimen/otto/underscore" - ) - - func init() { - underscore.Disable() - } - -## Usage - -#### func Disable - -```go -func Disable() -``` -Disable underscore runtime inclusion. - -#### func Enable - -```go -func Enable() -``` -Enable underscore runtime inclusion. - -#### func Source - -```go -func Source() string -``` -Source returns the underscore source. - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/vendor/github.com/robertkrimen/otto/underscore/source.go b/vendor/github.com/robertkrimen/otto/underscore/source.go deleted file mode 100644 index 7c5df971451..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore/source.go +++ /dev/null @@ -1,3463 +0,0 @@ -package underscore - -func underscore() []byte { - return []byte{ - 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, - 0x73, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6a, 0x73, 0x20, 0x31, 0x2e, 0x34, - 0x2e, 0x34, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x6a, 0x73, 0x2e, 0x6f, 0x72, 0x67, 0x0a, 0x2f, 0x2f, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, - 0x39, 0x2d, 0x32, 0x30, 0x31, 0x33, 0x20, 0x4a, 0x65, 0x72, 0x65, 0x6d, - 0x79, 0x20, 0x41, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x61, 0x73, 0x2c, 0x20, - 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, - 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x66, 0x72, 0x65, 0x65, - 0x6c, 0x79, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x4d, 0x49, 0x54, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, - 0x2e, 0x0a, 0x0a, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x42, - 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x65, 0x74, 0x75, - 0x70, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x60, 0x77, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x60, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, - 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x60, - 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x60, 0x20, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x0a, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x3d, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x53, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, 0x5f, 0x60, 0x20, 0x76, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x55, - 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x3d, 0x20, - 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x5f, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x67, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x72, 0x65, - 0x61, 0x6b, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, - 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x72, - 0x65, 0x61, 0x6b, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x53, 0x61, 0x76, 0x65, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6d, 0x69, 0x6e, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x28, 0x62, 0x75, - 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x7a, 0x69, 0x70, 0x70, 0x65, - 0x64, 0x29, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, - 0x4f, 0x62, 0x6a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x20, 0x3d, 0x20, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, - 0x79, 0x70, 0x65, 0x2c, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x20, 0x3d, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x3b, - 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x65, 0x65, - 0x64, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x63, 0x6f, 0x72, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x70, - 0x75, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x2c, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x73, - 0x6c, 0x69, 0x63, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, - 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x3d, 0x20, 0x4f, 0x62, 0x6a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x4f, - 0x62, 0x6a, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x68, 0x61, 0x73, 0x4f, - 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x2a, 0x2a, - 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, - 0x2a, 0x2a, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x20, 0x68, 0x6f, 0x70, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x65, 0x64, - 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x46, - 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x2c, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x61, 0x70, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6d, 0x61, - 0x70, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x2c, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x64, - 0x75, 0x63, 0x65, 0x52, 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x3d, 0x20, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, - 0x65, 0x64, 0x75, 0x63, 0x65, 0x52, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, - 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x65, 0x76, 0x65, 0x72, - 0x79, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x73, 0x6f, 0x6d, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x4f, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, - 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x4f, 0x66, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x4f, 0x66, 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x4f, 0x66, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x2e, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, - 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x2c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x42, - 0x69, 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x3d, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x62, 0x69, 0x6e, 0x64, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x73, 0x61, 0x66, - 0x65, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, - 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x65, 0x20, 0x62, 0x65, 0x6c, - 0x6f, 0x77, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x5f, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, - 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x6f, 0x66, 0x20, 0x5f, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x21, 0x28, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x20, 0x5f, 0x29, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x65, 0x77, - 0x20, 0x5f, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, - 0x65, 0x64, 0x20, 0x3d, 0x20, 0x6f, 0x62, 0x6a, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x45, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x64, 0x65, - 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x2a, 0x2a, 0x4e, 0x6f, 0x64, 0x65, - 0x2e, 0x6a, 0x73, 0x2a, 0x2a, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, - 0x64, 0x73, 0x2d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x60, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x28, 0x29, 0x60, 0x20, 0x41, 0x50, 0x49, 0x2e, 0x20, 0x49, 0x66, - 0x20, 0x77, 0x65, 0x27, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x73, - 0x65, 0x72, 0x2c, 0x20, 0x61, 0x64, 0x64, 0x20, 0x60, 0x5f, 0x60, 0x20, - 0x61, 0x73, 0x20, 0x61, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x76, 0x69, 0x61, 0x20, 0x61, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2c, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x43, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, - 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x22, 0x61, - 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x22, 0x20, 0x6d, 0x6f, 0x64, - 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x74, 0x79, 0x70, - 0x65, 0x6f, 0x66, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, - 0x21, 0x3d, 0x3d, 0x20, 0x27, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x65, 0x64, 0x27, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6d, 0x6f, - 0x64, 0x75, 0x6c, 0x65, 0x20, 0x21, 0x3d, 0x3d, 0x20, 0x27, 0x75, 0x6e, - 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x27, 0x20, 0x26, 0x26, 0x20, - 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x6d, 0x6f, - 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, - 0x20, 0x3d, 0x20, 0x5f, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, - 0x5f, 0x20, 0x3d, 0x20, 0x5f, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x20, 0x65, - 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x6f, - 0x6f, 0x74, 0x2e, 0x5f, 0x20, 0x3d, 0x20, 0x5f, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, - 0x20, 0x3d, 0x20, 0x27, 0x31, 0x2e, 0x34, 0x2e, 0x34, 0x27, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, - 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x6e, 0x65, 0x72, 0x73, 0x74, 0x6f, - 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x20, 0x60, 0x65, 0x61, 0x63, 0x68, - 0x60, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6b, 0x61, 0x20, 0x60, 0x66, - 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x2d, 0x69, 0x6e, 0x20, - 0x60, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x60, 0x2c, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, - 0x61, 0x77, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, - 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x60, 0x66, 0x6f, 0x72, - 0x45, 0x61, 0x63, 0x68, 0x60, 0x20, 0x69, 0x66, 0x20, 0x61, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x65, - 0x61, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x66, 0x6f, 0x72, 0x45, - 0x61, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, - 0x46, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x20, 0x26, 0x26, 0x20, 0x6f, - 0x62, 0x6a, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, 0x68, 0x20, 0x3d, - 0x3d, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x46, 0x6f, 0x72, - 0x45, 0x61, 0x63, 0x68, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x66, 0x6f, 0x72, 0x45, 0x61, 0x63, - 0x68, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, - 0x3d, 0x3d, 0x3d, 0x20, 0x2b, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, - 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x6c, 0x20, 0x3d, 0x20, 0x6f, 0x62, 0x6a, - 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x20, 0x69, 0x20, 0x3c, - 0x20, 0x6c, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, - 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x6f, 0x62, - 0x6a, 0x5b, 0x69, 0x5d, 0x2c, 0x20, 0x69, 0x2c, 0x20, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, - 0x72, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x6b, - 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x5f, 0x2e, 0x68, 0x61, 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, - 0x6b, 0x65, 0x79, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x6f, 0x62, 0x6a, - 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, - 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x62, 0x72, 0x65, - 0x61, 0x6b, 0x65, 0x72, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, - 0x70, 0x70, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, - 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, - 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x60, 0x6d, - 0x61, 0x70, 0x60, 0x20, 0x69, 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6d, 0x61, - 0x70, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, - 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x4d, 0x61, 0x70, 0x20, 0x26, 0x26, 0x20, 0x6f, - 0x62, 0x6a, 0x2e, 0x6d, 0x61, 0x70, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x61, 0x70, 0x29, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x6d, 0x61, 0x70, - 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, - 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5b, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5d, 0x20, - 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, - 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x20, 0x3d, 0x20, 0x27, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x20, - 0x6f, 0x66, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x20, 0x69, - 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x27, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x2a, 0x2a, 0x52, - 0x65, 0x64, 0x75, 0x63, 0x65, 0x2a, 0x2a, 0x20, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x73, 0x20, 0x75, 0x70, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, - 0x6c, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x66, 0x72, - 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6b, 0x61, - 0x20, 0x60, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x60, 0x2c, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x6f, 0x72, 0x20, 0x60, 0x66, 0x6f, 0x6c, 0x64, - 0x6c, 0x60, 0x2e, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, - 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x60, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x60, 0x20, 0x69, 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x66, 0x6f, 0x6c, - 0x64, 0x6c, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x69, 0x6e, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x2c, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3e, 0x20, 0x32, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, - 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x6f, 0x62, - 0x6a, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, - 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x62, - 0x69, 0x6e, 0x64, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x3f, 0x20, 0x6f, - 0x62, 0x6a, 0x2e, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x28, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, - 0x29, 0x20, 0x3a, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x72, 0x65, 0x64, 0x75, - 0x63, 0x65, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, - 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x21, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, - 0x65, 0x6d, 0x6f, 0x20, 0x3d, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, - 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6d, 0x65, 0x6d, 0x6f, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x2c, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x61, 0x6c, 0x29, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, - 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x79, 0x70, 0x65, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x28, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x73, 0x73, 0x6f, 0x63, - 0x69, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x2c, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, - 0x20, 0x61, 0x73, 0x20, 0x60, 0x66, 0x6f, 0x6c, 0x64, 0x72, 0x60, 0x2e, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, - 0x41, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, - 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x60, 0x72, 0x65, - 0x64, 0x75, 0x63, 0x65, 0x52, 0x69, 0x67, 0x68, 0x74, 0x60, 0x20, 0x69, - 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x52, - 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x66, 0x6f, 0x6c, - 0x64, 0x72, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, - 0x6c, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3e, 0x20, 0x32, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, - 0x6a, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x6f, - 0x62, 0x6a, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x52, - 0x65, 0x64, 0x75, 0x63, 0x65, 0x52, 0x69, 0x67, 0x68, 0x74, 0x20, 0x26, - 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x52, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x52, 0x69, - 0x67, 0x68, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x29, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, - 0x20, 0x5f, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x28, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x20, 0x3f, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x65, 0x52, 0x69, 0x67, 0x68, 0x74, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x29, 0x20, 0x3a, - 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x52, - 0x69, 0x67, 0x68, 0x74, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x20, 0x3d, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x21, 0x3d, 0x3d, 0x20, 0x2b, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, - 0x3d, 0x20, 0x5f, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, - 0x6b, 0x65, 0x79, 0x73, 0x20, 0x3f, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x5b, - 0x2d, 0x2d, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5d, 0x20, 0x3a, 0x20, - 0x2d, 0x2d, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x6c, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x20, 0x3d, 0x20, 0x6f, - 0x62, 0x6a, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, - 0x6d, 0x6f, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x2c, 0x20, 0x6f, 0x62, - 0x6a, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2c, 0x20, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, - 0x21, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x29, 0x20, 0x74, 0x68, - 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x79, 0x70, 0x65, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x77, - 0x68, 0x69, 0x63, 0x68, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x73, 0x20, - 0x61, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x20, 0x74, 0x65, 0x73, 0x74, - 0x2e, 0x20, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, - 0x20, 0x60, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x60, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x5f, 0x2e, - 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x2c, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, - 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x20, 0x74, - 0x72, 0x75, 0x74, 0x68, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, - 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x60, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x60, 0x20, 0x69, 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x60, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, - 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x29, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, - 0x74, 0x29, 0x29, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5b, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x5d, 0x20, 0x3d, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, - 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, - 0x68, 0x20, 0x61, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x20, 0x74, 0x65, - 0x73, 0x74, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, - 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, - 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x21, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, - 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x20, 0x61, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x20, 0x60, 0x65, 0x76, 0x65, 0x72, 0x79, 0x60, 0x20, 0x69, 0x66, - 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x64, - 0x20, 0x61, 0x73, 0x20, 0x60, 0x61, 0x6c, 0x6c, 0x60, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x3d, 0x20, 0x5f, - 0x2e, 0x61, 0x6c, 0x6c, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x2e, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, - 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, - 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, - 0x2e, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x45, 0x76, 0x65, 0x72, 0x79, 0x29, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x65, - 0x76, 0x65, 0x72, 0x79, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x28, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x20, 0x26, 0x26, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x29, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x62, 0x72, 0x65, - 0x61, 0x6b, 0x65, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x21, 0x21, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x69, 0x66, 0x20, 0x61, - 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x61, 0x20, 0x74, 0x72, 0x75, 0x74, - 0x68, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x20, 0x60, 0x73, 0x6f, 0x6d, 0x65, 0x60, 0x20, 0x69, - 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, - 0x64, 0x20, 0x61, 0x73, 0x20, 0x60, 0x61, 0x6e, 0x79, 0x60, 0x2e, 0x0a, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x3d, 0x20, - 0x5f, 0x2e, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x61, - 0x6e, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x69, 0x74, 0x65, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, - 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x20, - 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x53, - 0x6f, 0x6d, 0x65, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x73, - 0x6f, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x53, 0x6f, 0x6d, 0x65, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x73, 0x6f, 0x6d, 0x65, 0x28, - 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, - 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x7c, 0x7c, - 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, - 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, - 0x6c, 0x69, 0x73, 0x74, 0x29, 0x29, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x21, 0x21, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x65, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x20, 0x6f, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x20, - 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x28, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x60, 0x3d, 0x3d, 0x3d, 0x60, - 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x60, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x20, - 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, - 0x2e, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, 0x3d, 0x3d, 0x3d, - 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x4f, 0x66, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, - 0x62, 0x6a, 0x2e, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x28, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x2d, 0x31, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x61, 0x6e, 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, - 0x3d, 0x3d, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, - 0x20, 0x61, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x28, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x29, 0x20, 0x6f, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, - 0x69, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, - 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, - 0x3d, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, - 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, - 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x69, - 0x73, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x6d, 0x61, 0x70, 0x28, - 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x28, 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x20, 0x3f, 0x20, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x20, 0x3a, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x5b, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5d, 0x29, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x79, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x61, - 0x72, 0x67, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, - 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x65, - 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x60, 0x6d, 0x61, - 0x70, 0x60, 0x3a, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, - 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x70, 0x6c, 0x75, 0x63, 0x6b, 0x20, 0x3d, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x6d, - 0x61, 0x70, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x7b, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x20, 0x63, - 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x60, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x60, 0x3a, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x20, 0x60, 0x6b, 0x65, 0x79, 0x3a, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x60, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x2c, 0x20, 0x61, 0x74, 0x74, 0x72, 0x73, 0x2c, 0x20, 0x66, 0x69, 0x72, - 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x5f, 0x2e, 0x69, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, - 0x61, 0x74, 0x74, 0x72, 0x73, 0x29, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x3f, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x20, 0x3a, 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5b, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x20, 0x3f, 0x20, 0x27, 0x66, 0x69, 0x6e, 0x64, - 0x27, 0x20, 0x3a, 0x20, 0x27, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x27, - 0x5d, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, - 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x61, - 0x74, 0x74, 0x72, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x74, 0x74, 0x72, - 0x73, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x20, 0x21, 0x3d, 0x3d, 0x20, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x29, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, - 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x20, 0x63, - 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x60, 0x66, 0x69, 0x6e, 0x64, - 0x60, 0x3a, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x63, 0x20, 0x60, 0x6b, 0x65, 0x79, 0x3a, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x60, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x57, 0x68, 0x65, 0x72, - 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x61, 0x74, 0x74, 0x72, 0x73, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x5f, 0x2e, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x61, 0x74, 0x74, 0x72, 0x73, 0x2c, 0x20, 0x74, 0x72, - 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x28, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x64, - 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x61, 0x6e, 0x27, - 0x74, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x73, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, - 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x36, 0x35, 0x2c, 0x35, 0x33, 0x35, - 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x53, 0x65, 0x65, 0x3a, 0x20, 0x68, 0x74, 0x74, - 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x62, 0x75, 0x67, 0x73, 0x2e, 0x77, 0x65, - 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x73, 0x68, 0x6f, - 0x77, 0x5f, 0x62, 0x75, 0x67, 0x2e, 0x63, 0x67, 0x69, 0x3f, 0x69, 0x64, - 0x3d, 0x38, 0x30, 0x37, 0x39, 0x37, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6d, - 0x61, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, - 0x21, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x26, 0x26, - 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x6f, - 0x62, 0x6a, 0x29, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x30, - 0x5d, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x2b, 0x6f, 0x62, 0x6a, 0x5b, 0x30, - 0x5d, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x20, 0x3c, 0x20, 0x36, 0x35, 0x35, 0x33, 0x35, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x6d, 0x61, 0x78, - 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x4d, 0x61, 0x74, 0x68, 0x2c, - 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x26, 0x26, 0x20, 0x5f, 0x2e, - 0x69, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x29, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x2d, 0x49, 0x6e, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, - 0x20, 0x7b, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x20, 0x3a, - 0x20, 0x2d, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x2c, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x20, 0x2d, 0x49, 0x6e, 0x66, 0x69, - 0x6e, 0x69, 0x74, 0x79, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, - 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, - 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x20, 0x3d, - 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3f, 0x20, - 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, - 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, - 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x3a, 0x20, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x20, 0x3e, 0x3d, 0x20, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x20, 0x26, 0x26, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x20, 0x3d, 0x20, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3a, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x20, 0x3a, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x65, 0x64, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x6f, 0x72, 0x20, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x63, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6d, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, - 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x20, 0x26, 0x26, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x26, 0x26, - 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x3d, 0x3d, 0x20, - 0x2b, 0x6f, 0x62, 0x6a, 0x5b, 0x30, 0x5d, 0x20, 0x26, 0x26, 0x20, 0x6f, - 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3c, 0x20, - 0x36, 0x35, 0x35, 0x33, 0x35, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x4d, 0x61, - 0x74, 0x68, 0x2e, 0x6d, 0x69, 0x6e, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, - 0x28, 0x4d, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x21, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x20, 0x26, 0x26, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x63, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x20, 0x3a, 0x20, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, - 0x74, 0x79, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x20, 0x49, - 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x7d, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, - 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, - 0x64, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x20, 0x3f, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, - 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x3a, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x20, 0x3c, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x64, 0x20, 0x26, 0x26, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x3a, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x63, 0x6f, 0x6d, - 0x70, 0x75, 0x74, 0x65, 0x64, 0x20, 0x3a, 0x20, 0x63, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x53, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x20, - 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x73, 0x68, 0x75, - 0x66, 0x66, 0x6c, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6f, 0x62, 0x6a, - 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x72, - 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2b, - 0x2b, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x68, - 0x75, 0x66, 0x66, 0x6c, 0x65, 0x64, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x20, 0x2d, 0x20, 0x31, 0x5d, 0x20, 0x3d, 0x20, 0x73, 0x68, 0x75, 0x66, - 0x66, 0x6c, 0x65, 0x64, 0x5b, 0x72, 0x61, 0x6e, 0x64, 0x5d, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, - 0x65, 0x64, 0x5b, 0x72, 0x61, 0x6e, 0x64, 0x5d, 0x20, 0x3d, 0x20, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x73, 0x68, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x64, 0x3b, 0x0a, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6e, - 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2e, - 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x46, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, - 0x20, 0x3f, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3a, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, - 0x5b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5d, 0x3b, 0x20, 0x7d, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x53, - 0x6f, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x27, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, - 0x62, 0x79, 0x20, 0x61, 0x20, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, - 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, - 0x62, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x73, 0x6f, 0x72, 0x74, - 0x42, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x74, 0x65, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, - 0x75, 0x70, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x28, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x70, 0x6c, 0x75, 0x63, - 0x6b, 0x28, 0x5f, 0x2e, 0x6d, 0x61, 0x70, 0x28, 0x6f, 0x62, 0x6a, 0x2c, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, - 0x6c, 0x69, 0x73, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x20, 0x3a, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, - 0x3a, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x20, 0x3a, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x29, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x29, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x28, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x65, 0x66, 0x74, 0x2c, 0x20, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x6c, 0x65, - 0x66, 0x74, 0x2e, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, - 0x20, 0x3d, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x63, 0x72, 0x69, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x20, 0x21, 0x3d, 0x3d, 0x20, 0x62, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x61, 0x20, 0x3e, 0x20, 0x62, 0x20, 0x7c, 0x7c, - 0x20, 0x61, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, - 0x30, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x61, 0x20, 0x3c, 0x20, 0x62, 0x20, 0x7c, 0x7c, 0x20, 0x62, 0x20, - 0x3d, 0x3d, 0x3d, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x30, 0x29, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x2d, 0x31, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x65, 0x66, 0x74, - 0x2e, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3c, 0x20, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x2e, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3f, 0x20, 0x2d, - 0x31, 0x20, 0x3a, 0x20, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x29, 0x2c, 0x20, 0x27, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x27, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x20, 0x22, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x62, - 0x79, 0x22, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x62, - 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, - 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x74, 0x65, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x7c, 0x7c, 0x20, 0x5f, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x20, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, - 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, - 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x28, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x27, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x62, - 0x79, 0x20, 0x61, 0x20, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x6f, - 0x6e, 0x2e, 0x20, 0x50, 0x61, 0x73, 0x73, 0x20, 0x65, 0x69, 0x74, 0x68, - 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, - 0x62, 0x79, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, - 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x79, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, - 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, - 0x5f, 0x2e, 0x68, 0x61, 0x73, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x3f, 0x20, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x20, 0x3a, 0x20, 0x28, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x20, - 0x3d, 0x20, 0x5b, 0x5d, 0x29, 0x29, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, - 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x62, 0x79, 0x20, 0x61, - 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x72, 0x69, - 0x74, 0x65, 0x72, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x50, 0x61, 0x73, 0x73, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x62, 0x79, 0x2c, 0x20, 0x6f, 0x72, 0x20, - 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, - 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x72, 0x69, - 0x74, 0x65, 0x72, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x6f, - 0x62, 0x6a, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2c, - 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x2e, 0x68, 0x61, 0x73, - 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2c, 0x20, 0x6b, 0x65, 0x79, - 0x29, 0x29, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6b, 0x65, - 0x79, 0x5d, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6b, 0x65, 0x79, - 0x5d, 0x2b, 0x2b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x55, 0x73, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, - 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x61, 0x6c, - 0x6c, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x61, - 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x73, - 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x73, - 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x20, 0x61, 0x73, 0x20, - 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x73, 0x20, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, - 0x20, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x3f, - 0x20, 0x5f, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, - 0x3a, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x28, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, - 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x6f, 0x77, - 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x3d, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, - 0x20, 0x28, 0x6c, 0x6f, 0x77, 0x20, 0x3c, 0x20, 0x68, 0x69, 0x67, 0x68, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x6d, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x28, 0x6c, 0x6f, 0x77, - 0x20, 0x2b, 0x20, 0x68, 0x69, 0x67, 0x68, 0x29, 0x20, 0x3e, 0x3e, 0x3e, - 0x20, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x5b, 0x6d, 0x69, 0x64, 0x5d, 0x29, 0x20, 0x3c, 0x20, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3f, 0x20, 0x6c, 0x6f, 0x77, 0x20, 0x3d, - 0x20, 0x6d, 0x69, 0x64, 0x20, 0x2b, 0x20, 0x31, 0x20, 0x3a, 0x20, 0x68, - 0x69, 0x67, 0x68, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x64, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x53, 0x61, 0x66, 0x65, - 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x61, - 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, - 0x72, 0x65, 0x61, 0x6c, 0x2c, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x74, 0x6f, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5b, 0x5d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x69, - 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x29, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x6c, 0x69, 0x63, - 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, - 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x3d, 0x20, - 0x2b, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x6d, 0x61, - 0x70, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x5f, 0x2e, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x73, 0x69, 0x7a, - 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x2b, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, 0x20, 0x3f, 0x20, 0x6f, 0x62, 0x6a, - 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3a, 0x20, 0x5f, 0x2e, - 0x6b, 0x65, 0x79, 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x2e, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, - 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x20, 0x50, - 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x2a, 0x2a, 0x6e, 0x2a, 0x2a, - 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x4e, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x2e, 0x20, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x64, 0x20, 0x61, - 0x73, 0x20, 0x60, 0x68, 0x65, 0x61, 0x64, 0x60, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x60, 0x74, 0x61, 0x6b, 0x65, 0x60, 0x2e, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x2a, 0x2a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x2a, 0x2a, 0x20, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, - 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x60, 0x5f, 0x2e, - 0x6d, 0x61, 0x70, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x66, 0x69, - 0x72, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x68, 0x65, 0x61, 0x64, - 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x2c, 0x20, 0x6e, 0x2c, 0x20, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, - 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x6f, - 0x69, 0x64, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x6e, 0x20, 0x21, 0x3d, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x26, 0x26, 0x20, 0x21, 0x67, 0x75, 0x61, - 0x72, 0x64, 0x20, 0x3f, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, - 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x30, - 0x2c, 0x20, 0x6e, 0x29, 0x20, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x5b, 0x30, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, - 0x65, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x62, - 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x20, 0x45, 0x73, 0x70, 0x65, - 0x63, 0x69, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, - 0x6c, 0x20, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x20, 0x50, 0x61, 0x73, 0x73, - 0x69, 0x6e, 0x67, 0x20, 0x2a, 0x2a, 0x6e, 0x2a, 0x2a, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x6c, - 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x20, 0x69, 0x6e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x65, 0x78, 0x63, 0x6c, - 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, - 0x73, 0x74, 0x20, 0x4e, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x2a, 0x2a, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x2a, 0x2a, 0x20, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x69, 0x74, 0x20, - 0x74, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x60, 0x5f, 0x2e, 0x6d, 0x61, 0x70, - 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x6e, 0x2c, 0x20, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x6c, 0x69, 0x63, - 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x2d, 0x20, 0x28, 0x28, 0x6e, 0x20, - 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x7c, 0x7c, 0x20, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x20, 0x3f, 0x20, 0x31, 0x20, 0x3a, 0x20, - 0x6e, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6c, 0x61, 0x73, 0x74, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x2e, 0x20, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x2a, 0x2a, - 0x6e, 0x2a, 0x2a, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, - 0x20, 0x4e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x2a, 0x2a, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x2a, 0x2a, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x69, 0x74, 0x20, 0x74, - 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x60, 0x5f, 0x2e, 0x6d, 0x61, 0x70, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, - 0x6e, 0x2c, 0x20, 0x67, 0x75, 0x61, 0x72, 0x64, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x30, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x28, 0x6e, - 0x20, 0x21, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x26, 0x26, - 0x20, 0x21, 0x67, 0x75, 0x61, 0x72, 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x6d, - 0x61, 0x78, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x20, 0x2d, 0x20, 0x6e, 0x2c, 0x20, 0x30, 0x29, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5b, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x2d, - 0x20, 0x31, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x74, - 0x68, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x2e, 0x20, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x64, 0x20, 0x61, - 0x73, 0x20, 0x60, 0x74, 0x61, 0x69, 0x6c, 0x60, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x60, 0x64, 0x72, 0x6f, 0x70, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x45, 0x73, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x6c, 0x79, - 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x20, 0x50, 0x61, 0x73, - 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x2a, 0x2a, 0x6e, 0x2a, - 0x2a, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, - 0x65, 0x73, 0x74, 0x20, 0x4e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x2a, 0x2a, 0x67, 0x75, 0x61, - 0x72, 0x64, 0x2a, 0x2a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x69, - 0x74, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x60, 0x5f, 0x2e, 0x6d, 0x61, 0x70, 0x60, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x72, 0x65, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x5f, - 0x2e, 0x74, 0x61, 0x69, 0x6c, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x64, 0x72, - 0x6f, 0x70, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x6e, 0x2c, 0x20, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x6c, 0x69, 0x63, - 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x2c, 0x20, 0x28, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, - 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x67, 0x75, 0x61, 0x72, 0x64, 0x20, 0x3f, - 0x20, 0x31, 0x20, 0x3a, 0x20, 0x6e, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x72, 0x69, 0x6d, - 0x20, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61, 0x6c, - 0x73, 0x79, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x66, 0x72, - 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, - 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, - 0x5f, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x69, 0x6d, 0x70, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x6f, 0x66, 0x20, 0x61, 0x20, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, - 0x76, 0x65, 0x20, 0x60, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x60, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, - 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, - 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x3f, 0x20, - 0x70, 0x75, 0x73, 0x68, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x29, 0x20, 0x3a, 0x20, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, - 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x6c, - 0x79, 0x20, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x65, 0x64, 0x20, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, - 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x2c, - 0x20, 0x5b, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, - 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x28, 0x73, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, - 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, 0x20, - 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2d, 0x66, 0x72, - 0x65, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, - 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, - 0x79, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, - 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x79, 0x6f, 0x75, 0x20, - 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, - 0x20, 0x61, 0x20, 0x66, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6c, - 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, - 0x20, 0x60, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x60, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x75, 0x6e, 0x69, 0x71, 0x20, 0x3d, 0x20, 0x5f, 0x2e, - 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, - 0x20, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x69, 0x74, - 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3d, - 0x20, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x3f, 0x20, 0x5f, 0x2e, - 0x6d, 0x61, 0x70, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x73, 0x65, 0x65, - 0x6e, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x28, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x3f, 0x20, - 0x28, 0x21, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x7c, 0x7c, 0x20, 0x73, - 0x65, 0x65, 0x6e, 0x5b, 0x73, 0x65, 0x65, 0x6e, 0x2e, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x20, 0x2d, 0x20, 0x31, 0x5d, 0x20, 0x21, 0x3d, 0x3d, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x3a, 0x20, 0x21, 0x5f, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x28, 0x73, 0x65, - 0x65, 0x6e, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x65, - 0x65, 0x6e, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x70, 0x75, 0x73, 0x68, - 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5b, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x61, - 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x65, 0x61, 0x63, - 0x68, 0x20, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, 0x20, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x2d, 0x69, - 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x73, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, - 0x75, 0x6e, 0x69, 0x71, 0x28, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, - 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x20, - 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, - 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x2d, 0x69, - 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x73, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, - 0x3d, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, - 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, - 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x28, - 0x5f, 0x2e, 0x75, 0x6e, 0x69, 0x71, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x29, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x69, 0x74, 0x65, 0x6d, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x65, - 0x76, 0x65, 0x72, 0x79, 0x28, 0x72, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x4f, 0x66, 0x28, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, - 0x20, 0x69, 0x74, 0x65, 0x6d, 0x29, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x61, 0x6b, 0x65, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6f, 0x6e, - 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x61, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, - 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, - 0x6a, 0x75, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, - 0x73, 0x74, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, 0x3d, 0x20, - 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, - 0x28, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2c, - 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, - 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, - 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x28, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x21, 0x5f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x28, 0x72, 0x65, 0x73, 0x74, 0x2c, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x5a, 0x69, 0x70, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x6c, 0x69, - 0x73, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, - 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x2d, 0x2d, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x20, 0x67, 0x6f, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x7a, 0x69, 0x70, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x72, 0x67, - 0x73, 0x20, 0x3d, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, - 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x6d, 0x61, - 0x78, 0x28, 0x5f, 0x2e, 0x70, 0x6c, 0x75, 0x63, 0x6b, 0x28, 0x61, 0x72, - 0x67, 0x73, 0x2c, 0x20, 0x27, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x27, - 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x6e, 0x65, - 0x77, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, - 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, - 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x5b, 0x69, 0x5d, - 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x70, 0x6c, 0x75, 0x63, 0x6b, 0x28, 0x61, - 0x72, 0x67, 0x73, 0x2c, 0x20, 0x22, 0x22, 0x20, 0x2b, 0x20, 0x69, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x73, 0x20, - 0x6c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, 0x20, 0x50, 0x61, 0x73, 0x73, - 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x20, 0x73, 0x69, - 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, - 0x66, 0x20, 0x60, 0x5b, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x5d, 0x60, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x70, 0x61, - 0x69, 0x72, 0x73, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x77, 0x6f, 0x20, - 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x61, 0x6d, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x2d, - 0x2d, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x65, 0x79, - 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, - 0x66, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, - 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x69, 0x73, 0x74, 0x2c, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6c, 0x69, 0x73, 0x74, 0x20, - 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, - 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x2c, - 0x20, 0x6c, 0x20, 0x3d, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6c, 0x3b, - 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6c, 0x69, 0x73, 0x74, 0x5b, - 0x69, 0x5d, 0x5d, 0x20, 0x3d, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x5b, 0x69, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6c, - 0x69, 0x73, 0x74, 0x5b, 0x69, 0x5d, 0x5b, 0x30, 0x5d, 0x5d, 0x20, 0x3d, - 0x20, 0x6c, 0x69, 0x73, 0x74, 0x5b, 0x69, 0x5d, 0x5b, 0x31, 0x5d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x20, - 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, - 0x6c, 0x79, 0x20, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, 0x28, 0x49, 0x27, 0x6d, 0x20, - 0x6c, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x74, 0x20, 0x79, - 0x6f, 0x75, 0x2c, 0x20, 0x2a, 0x2a, 0x4d, 0x53, 0x49, 0x45, 0x2a, 0x2a, - 0x29, 0x2c, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x77, 0x65, 0x20, 0x6e, - 0x65, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, - 0x72, 0x73, 0x74, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6e, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x2d, - 0x31, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x74, 0x65, - 0x6d, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x20, 0x60, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, - 0x60, 0x20, 0x69, 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x69, 0x73, - 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, - 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, - 0x72, 0x74, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x70, 0x61, - 0x73, 0x73, 0x20, 0x60, 0x74, 0x72, 0x75, 0x65, 0x60, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x2a, 0x2a, 0x69, 0x73, 0x53, - 0x6f, 0x72, 0x74, 0x65, 0x64, 0x2a, 0x2a, 0x20, 0x74, 0x6f, 0x20, 0x75, - 0x73, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x73, 0x65, - 0x61, 0x72, 0x63, 0x68, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, - 0x69, 0x74, 0x65, 0x6d, 0x2c, 0x20, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x2d, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x69, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x6c, 0x20, 0x3d, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x69, 0x73, 0x53, - 0x6f, 0x72, 0x74, 0x65, 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x74, 0x79, 0x70, 0x65, 0x6f, - 0x66, 0x20, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x3d, - 0x3d, 0x20, 0x27, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x27, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x20, - 0x3d, 0x20, 0x28, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, - 0x3c, 0x20, 0x30, 0x20, 0x3f, 0x20, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x6d, - 0x61, 0x78, 0x28, 0x30, 0x2c, 0x20, 0x6c, 0x20, 0x2b, 0x20, 0x69, 0x73, - 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x29, 0x20, 0x3a, 0x20, 0x69, 0x73, - 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x20, 0x3d, 0x20, - 0x5f, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2c, 0x20, 0x69, 0x74, 0x65, - 0x6d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x6d, - 0x20, 0x3f, 0x20, 0x69, 0x20, 0x3a, 0x20, 0x2d, 0x31, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, 0x26, - 0x26, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x4f, 0x66, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x29, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x28, 0x69, 0x74, 0x65, 0x6d, - 0x2c, 0x20, 0x69, 0x73, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x3b, 0x20, - 0x69, 0x20, 0x3c, 0x20, 0x6c, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5b, 0x69, 0x5d, - 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x29, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x2d, 0x31, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x20, 0x60, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x4f, 0x66, 0x60, 0x20, 0x69, 0x66, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6c, 0x61, - 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x2c, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x2c, 0x20, 0x66, 0x72, - 0x6f, 0x6d, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x2d, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x68, 0x61, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, - 0x72, 0x6f, 0x6d, 0x20, 0x21, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x61, 0x74, - 0x69, 0x76, 0x65, 0x4c, 0x61, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x4f, 0x66, 0x20, 0x26, 0x26, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, - 0x6c, 0x61, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x20, - 0x3d, 0x3d, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4c, 0x61, - 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x68, 0x61, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3f, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x6c, 0x61, 0x73, 0x74, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x28, 0x69, 0x74, 0x65, 0x6d, 0x2c, - 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x29, 0x20, 0x3a, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x2e, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x4f, 0x66, 0x28, 0x69, 0x74, 0x65, 0x6d, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x69, 0x20, 0x3d, 0x20, 0x28, 0x68, 0x61, 0x73, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x20, 0x3f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x3a, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, - 0x28, 0x69, 0x2d, 0x2d, 0x29, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x69, - 0x74, 0x65, 0x6d, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x69, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x2d, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, - 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x69, - 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x20, 0x70, - 0x6f, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x50, - 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x20, 0x60, 0x72, 0x61, 0x6e, 0x67, 0x65, - 0x28, 0x29, 0x60, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x20, 0x53, 0x65, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x5b, - 0x74, 0x68, 0x65, 0x20, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x20, 0x64, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5d, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x64, 0x6f, 0x63, - 0x73, 0x2e, 0x70, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x2e, 0x6f, 0x72, 0x67, - 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2f, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x23, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x74, 0x61, 0x72, 0x74, 0x2c, 0x20, - 0x73, 0x74, 0x6f, 0x70, 0x2c, 0x20, 0x73, 0x74, 0x65, 0x70, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x3d, 0x20, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x7c, 0x7c, 0x20, 0x30, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, - 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x3d, 0x20, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x7c, - 0x7c, 0x20, 0x31, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x6c, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x4d, 0x61, 0x74, 0x68, - 0x2e, 0x6d, 0x61, 0x78, 0x28, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x63, 0x65, - 0x69, 0x6c, 0x28, 0x28, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x2d, 0x20, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x29, 0x20, 0x2f, 0x20, 0x73, 0x74, 0x65, 0x70, - 0x29, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x69, 0x64, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x28, 0x6c, 0x65, 0x6e, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x69, 0x64, 0x78, 0x20, 0x3c, - 0x20, 0x6c, 0x65, 0x6e, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5b, 0x69, 0x64, 0x78, 0x2b, - 0x2b, 0x5d, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, - 0x2b, 0x3d, 0x20, 0x73, 0x74, 0x65, 0x70, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x46, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x61, 0x68, 0x65, 0x6d, 0x29, - 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, - 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x67, 0x69, - 0x76, 0x65, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x28, - 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x60, 0x74, - 0x68, 0x69, 0x73, 0x60, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, - 0x29, 0x2e, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, - 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, 0x6e, - 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x60, 0x46, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x60, 0x20, 0x69, 0x66, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x62, 0x69, 0x6e, - 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x20, - 0x3d, 0x3d, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x42, 0x69, - 0x6e, 0x64, 0x20, 0x26, 0x26, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, - 0x42, 0x69, 0x6e, 0x64, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, - 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, - 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, - 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x2c, 0x20, 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x2e, 0x63, 0x6f, - 0x6e, 0x63, 0x61, 0x74, 0x28, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, - 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x29, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x61, 0x70, - 0x70, 0x6c, 0x79, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x68, 0x61, - 0x64, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, - 0x73, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x20, 0x70, 0x72, 0x65, 0x2d, 0x66, 0x69, 0x6c, - 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, - 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, - 0x73, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x20, 0x60, 0x74, - 0x68, 0x69, 0x73, 0x60, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, - 0x6c, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x66, 0x75, 0x6e, 0x63, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, - 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, - 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x6c, - 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, - 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x73, 0x6c, 0x69, 0x63, - 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x29, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x42, 0x69, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, - 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x27, 0x73, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x6c, 0x6c, - 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x20, 0x64, - 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x6e, - 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x62, 0x65, 0x6c, 0x6f, - 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2e, 0x0a, 0x20, 0x20, - 0x5f, 0x2e, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x6c, 0x6c, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x6c, 0x69, 0x63, - 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x73, 0x2e, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x30, - 0x29, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x2e, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x28, 0x6f, 0x62, - 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, - 0x28, 0x66, 0x75, 0x6e, 0x63, 0x73, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x29, 0x20, 0x7b, 0x20, 0x6f, 0x62, - 0x6a, 0x5b, 0x66, 0x5d, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x62, 0x69, 0x6e, - 0x64, 0x28, 0x6f, 0x62, 0x6a, 0x5b, 0x66, 0x5d, 0x2c, 0x20, 0x6f, 0x62, - 0x6a, 0x29, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4d, - 0x65, 0x6d, 0x6f, 0x69, 0x7a, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, - 0x70, 0x65, 0x6e, 0x73, 0x69, 0x76, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x73, 0x74, 0x6f, 0x72, - 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, 0x68, 0x61, - 0x73, 0x68, 0x65, 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x20, 0x3d, 0x20, 0x7b, - 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, - 0x72, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x68, 0x61, 0x73, 0x68, 0x65, 0x72, - 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x20, 0x68, 0x61, 0x73, 0x68, - 0x65, 0x72, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, - 0x73, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x68, 0x61, 0x73, 0x28, 0x6d, 0x65, - 0x6d, 0x6f, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x3f, 0x20, 0x6d, - 0x65, 0x6d, 0x6f, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x20, 0x3a, 0x20, 0x28, - 0x6d, 0x65, 0x6d, 0x6f, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, - 0x68, 0x69, 0x73, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x44, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x74, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, - 0x63, 0x2c, 0x20, 0x77, 0x61, 0x69, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, - 0x3d, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, - 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, - 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, - 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x6e, 0x75, 0x6c, 0x6c, - 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x29, 0x3b, 0x20, 0x7d, 0x2c, 0x20, - 0x77, 0x61, 0x69, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x66, 0x65, 0x72, 0x73, - 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, - 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x69, 0x6e, 0x67, 0x20, - 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x74, 0x61, - 0x63, 0x6b, 0x20, 0x68, 0x61, 0x73, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x63, 0x6c, 0x65, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x64, 0x65, 0x66, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x5f, 0x2e, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, - 0x6c, 0x79, 0x28, 0x5f, 0x2c, 0x20, 0x5b, 0x66, 0x75, 0x6e, 0x63, 0x2c, - 0x20, 0x31, 0x5d, 0x2e, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x28, 0x73, - 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, 0x29, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x76, - 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67, - 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x73, 0x74, - 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x64, - 0x75, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x6e, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x74, 0x68, - 0x72, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x2c, 0x20, - 0x77, 0x61, 0x69, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, - 0x20, 0x61, 0x72, 0x67, 0x73, 0x2c, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x6f, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, - 0x44, 0x61, 0x74, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x6e, 0x75, - 0x6c, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, - 0x20, 0x44, 0x61, 0x74, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, - 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x77, 0x61, 0x69, 0x74, 0x20, 0x2d, 0x20, - 0x28, 0x6e, 0x6f, 0x77, 0x20, 0x2d, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, - 0x6f, 0x75, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72, - 0x67, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, - 0x3c, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x28, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, - 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, - 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x6e, 0x6f, - 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x21, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x65, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x61, 0x74, - 0x65, 0x72, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, - 0x67, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x6c, 0x6f, 0x6e, 0x67, - 0x20, 0x61, 0x73, 0x20, 0x69, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, - 0x6e, 0x75, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x69, - 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x77, 0x69, 0x6c, 0x6c, - 0x20, 0x6e, 0x6f, 0x74, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x62, 0x65, - 0x20, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, - 0x6c, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x69, 0x74, - 0x20, 0x73, 0x74, 0x6f, 0x70, 0x73, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, - 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4e, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, - 0x60, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x60, 0x20, - 0x69, 0x73, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x2c, 0x20, 0x74, - 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x6c, 0x65, 0x61, 0x64, - 0x69, 0x6e, 0x67, 0x20, 0x65, 0x64, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, - 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x64, 0x65, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, - 0x75, 0x6e, 0x63, 0x2c, 0x20, 0x77, 0x61, 0x69, 0x74, 0x2c, 0x20, 0x69, - 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x68, 0x69, - 0x73, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x72, - 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x6e, 0x75, - 0x6c, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x21, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, - 0x74, 0x65, 0x29, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x61, 0x72, 0x67, - 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, - 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x69, 0x6d, 0x6d, - 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x26, 0x26, 0x20, 0x21, 0x74, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x28, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x77, - 0x61, 0x69, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x63, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x77, 0x29, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, - 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, - 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x6d, - 0x65, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x72, - 0x20, 0x68, 0x6f, 0x77, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x6f, 0x66, - 0x74, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6c, 0x6c, - 0x20, 0x69, 0x74, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x69, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6f, 0x6e, 0x63, 0x65, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, - 0x63, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x20, 0x72, 0x61, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x61, 0x6e, 0x29, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x61, 0x6e, 0x20, 0x3d, 0x20, - 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6d, 0x65, 0x6d, 0x6f, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x2e, - 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, - 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, - 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, - 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, - 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2c, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, - 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x6a, - 0x75, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x2c, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, - 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, - 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x77, 0x72, 0x61, 0x70, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, 0x63, - 0x2c, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, - 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x5b, 0x66, 0x75, 0x6e, 0x63, 0x5d, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x75, 0x73, 0x68, - 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x73, 0x2c, - 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x61, 0x72, - 0x67, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, - 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x6c, - 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, - 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, - 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, - 0x72, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x73, 0x2e, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x2d, 0x20, 0x31, 0x3b, 0x20, - 0x69, 0x20, 0x3e, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x2d, 0x2d, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, - 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x5b, 0x66, 0x75, 0x6e, 0x63, 0x73, - 0x5b, 0x69, 0x5d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, - 0x69, 0x73, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, 0x29, 0x5d, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x72, 0x67, - 0x73, 0x5b, 0x30, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, - 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x20, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x61, - 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x4e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x20, 0x3c, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x29, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x2d, - 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x3c, 0x20, 0x31, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x2e, 0x61, 0x70, - 0x70, 0x6c, 0x79, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x61, 0x72, - 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x27, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x6f, - 0x20, 0x2a, 0x2a, 0x45, 0x43, 0x4d, 0x41, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x20, 0x35, 0x2a, 0x2a, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x20, 0x60, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x6b, - 0x65, 0x79, 0x73, 0x60, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6b, 0x65, 0x79, - 0x73, 0x20, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, - 0x79, 0x73, 0x20, 0x7c, 0x7c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x21, 0x3d, - 0x3d, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x29, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, - 0x20, 0x54, 0x79, 0x70, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x27, - 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x27, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, - 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x68, 0x61, 0x73, 0x28, - 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x29, 0x20, 0x6b, - 0x65, 0x79, 0x73, 0x5b, 0x6b, 0x65, 0x79, 0x73, 0x2e, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x5d, 0x20, 0x3d, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6b, - 0x65, 0x79, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, - 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x27, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, - 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x3d, - 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, - 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, - 0x68, 0x61, 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, - 0x29, 0x29, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x70, 0x75, - 0x73, 0x68, 0x28, 0x6f, 0x62, 0x6a, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x29, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, - 0x74, 0x20, 0x6f, 0x66, 0x20, 0x60, 0x5b, 0x6b, 0x65, 0x79, 0x2c, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5d, 0x60, 0x20, 0x70, 0x61, 0x69, 0x72, - 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x70, 0x61, 0x69, 0x72, 0x73, - 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x5b, - 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, - 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, - 0x62, 0x6a, 0x29, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x68, 0x61, - 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x29, - 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, - 0x5b, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x6b, 0x65, - 0x79, 0x5d, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, - 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x65, - 0x79, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, - 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x7b, - 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, - 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, - 0x62, 0x6a, 0x29, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x68, 0x61, - 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x29, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6f, 0x62, 0x6a, 0x5b, - 0x6b, 0x65, 0x79, 0x5d, 0x5d, 0x20, 0x3d, 0x20, 0x6b, 0x65, 0x79, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x6c, - 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x60, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x60, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x20, 0x3d, 0x20, 0x5b, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, - 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, - 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, - 0x62, 0x6a, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x29, 0x29, 0x20, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x6b, 0x65, 0x79, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, - 0x73, 0x2e, 0x73, 0x6f, 0x72, 0x74, 0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x45, 0x78, 0x74, - 0x65, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, - 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, - 0x73, 0x73, 0x65, 0x64, 0x2d, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x28, 0x73, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x65, - 0x78, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x73, 0x6c, 0x69, - 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, 0x2c, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x20, - 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, - 0x62, 0x6a, 0x5b, 0x70, 0x72, 0x6f, 0x70, 0x5d, 0x20, 0x3d, 0x20, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5b, 0x70, 0x72, 0x6f, 0x70, 0x5d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x61, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x6f, 0x6e, - 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, - 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x70, 0x69, - 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x3d, 0x20, - 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x6b, 0x65, 0x79, 0x73, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, - 0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2c, 0x20, 0x73, 0x6c, 0x69, 0x63, - 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x6b, 0x65, 0x79, 0x73, - 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6b, - 0x65, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, - 0x62, 0x6a, 0x29, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x5b, 0x6b, 0x65, 0x79, - 0x5d, 0x20, 0x3d, 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x6b, 0x65, 0x79, 0x5d, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x70, - 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, - 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, - 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x61, 0x63, 0x6b, - 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6f, - 0x6d, 0x69, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x3d, - 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x63, - 0x61, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2c, 0x20, 0x73, 0x6c, 0x69, - 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, 0x29, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, - 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x21, 0x5f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, - 0x28, 0x6b, 0x65, 0x79, 0x73, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x29, - 0x20, 0x63, 0x6f, 0x70, 0x79, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x20, 0x3d, - 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x46, 0x69, 0x6c, - 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, - 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, - 0x28, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, - 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x31, - 0x29, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, 0x70, - 0x72, 0x6f, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x5b, 0x70, - 0x72, 0x6f, 0x70, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, - 0x29, 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x70, 0x72, 0x6f, 0x70, 0x5d, 0x20, - 0x3d, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5b, 0x70, 0x72, 0x6f, - 0x70, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x28, 0x73, 0x68, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x2d, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x64, 0x29, 0x20, 0x64, - 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x20, 0x3d, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, - 0x5f, 0x2e, 0x69, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x6f, - 0x62, 0x6a, 0x29, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x6f, 0x62, 0x6a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, - 0x79, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x3f, 0x20, 0x6f, 0x62, 0x6a, - 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x28, 0x29, 0x20, 0x3a, 0x20, 0x5f, - 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x28, 0x7b, 0x7d, 0x2c, 0x20, - 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x73, - 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x2e, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, - 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, - 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x22, - 0x74, 0x61, 0x70, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x22, 0x20, 0x61, 0x20, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x2c, 0x20, 0x69, 0x6e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f, - 0x72, 0x6d, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, - 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, - 0x74, 0x61, 0x70, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, - 0x6f, 0x72, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x63, - 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x60, 0x69, 0x73, 0x45, 0x71, - 0x75, 0x61, 0x6c, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x65, 0x71, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x61, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x2c, 0x20, 0x62, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, - 0x2e, 0x20, 0x60, 0x30, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x2d, 0x30, 0x60, - 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x61, - 0x72, 0x65, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x6c, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x61, 0x72, 0x6d, - 0x6f, 0x6e, 0x79, 0x20, 0x60, 0x65, 0x67, 0x61, 0x6c, 0x60, 0x20, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6b, 0x69, 0x2e, 0x65, 0x63, 0x6d, - 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x2f, - 0x64, 0x6f, 0x6b, 0x75, 0x2e, 0x70, 0x68, 0x70, 0x3f, 0x69, 0x64, 0x3d, - 0x68, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x79, 0x3a, 0x65, 0x67, 0x61, 0x6c, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x20, - 0x3d, 0x3d, 0x3d, 0x20, 0x62, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x61, 0x20, 0x21, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x7c, 0x7c, - 0x20, 0x31, 0x20, 0x2f, 0x20, 0x61, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, - 0x2f, 0x20, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x41, 0x20, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x6e, - 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x20, 0x62, 0x65, 0x63, - 0x61, 0x75, 0x73, 0x65, 0x20, 0x60, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x3d, - 0x3d, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x60, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x20, - 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x7c, 0x7c, 0x20, 0x62, - 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x62, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x55, 0x6e, 0x77, - 0x72, 0x61, 0x70, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x77, 0x72, 0x61, 0x70, - 0x70, 0x65, 0x64, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2e, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x20, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, 0x66, 0x20, 0x5f, 0x29, - 0x20, 0x61, 0x20, 0x3d, 0x20, 0x61, 0x2e, 0x5f, 0x77, 0x72, 0x61, 0x70, - 0x70, 0x65, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x62, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, - 0x66, 0x20, 0x5f, 0x29, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x62, 0x2e, 0x5f, - 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x20, - 0x60, 0x5b, 0x5b, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x5d, 0x5d, 0x60, 0x20, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, - 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, - 0x6d, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x62, 0x29, 0x29, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, - 0x20, 0x28, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x74, 0x65, 0x73, 0x2c, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, - 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, - 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x5d, 0x27, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, - 0x69, 0x72, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, - 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, - 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x3b, - 0x20, 0x74, 0x68, 0x75, 0x73, 0x2c, 0x20, 0x60, 0x22, 0x35, 0x22, 0x60, - 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, - 0x74, 0x20, 0x74, 0x6f, 0x20, 0x60, 0x6e, 0x65, 0x77, 0x20, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x28, 0x22, 0x35, 0x22, 0x29, 0x60, 0x2e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x61, 0x20, 0x3d, 0x3d, 0x20, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x28, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x20, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5d, 0x27, 0x3a, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x60, 0x4e, 0x61, 0x4e, 0x60, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x65, - 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, - 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x66, 0x6c, 0x65, - 0x78, 0x69, 0x76, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x20, 0x60, 0x65, 0x67, - 0x61, 0x6c, 0x60, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, - 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, - 0x6d, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x21, 0x3d, - 0x20, 0x2b, 0x61, 0x20, 0x3f, 0x20, 0x62, 0x20, 0x21, 0x3d, 0x20, 0x2b, - 0x62, 0x20, 0x3a, 0x20, 0x28, 0x61, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, - 0x3f, 0x20, 0x31, 0x20, 0x2f, 0x20, 0x61, 0x20, 0x3d, 0x3d, 0x20, 0x31, - 0x20, 0x2f, 0x20, 0x62, 0x20, 0x3a, 0x20, 0x61, 0x20, 0x3d, 0x3d, 0x20, - 0x2b, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, - 0x61, 0x73, 0x65, 0x20, 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x20, 0x44, 0x61, 0x74, 0x65, 0x5d, 0x27, 0x3a, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x27, 0x5b, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x20, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, - 0x5d, 0x27, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x65, 0x72, 0x63, 0x65, 0x20, 0x64, 0x61, - 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x6f, 0x6c, - 0x65, 0x61, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x75, 0x6d, 0x65, - 0x72, 0x69, 0x63, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x20, 0x44, 0x61, - 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x69, - 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, - 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x72, - 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x6f, 0x66, 0x20, 0x60, 0x4e, 0x61, 0x4e, 0x60, 0x20, 0x61, - 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, - 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x2b, 0x61, - 0x20, 0x3d, 0x3d, 0x20, 0x2b, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x67, 0x45, 0x78, 0x70, 0x73, - 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, - 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, - 0x20, 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x52, 0x65, - 0x67, 0x45, 0x78, 0x70, 0x5d, 0x27, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, - 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x62, - 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x26, 0x26, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x61, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x3d, - 0x3d, 0x20, 0x62, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x26, - 0x26, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x62, 0x2e, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x26, 0x26, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x61, 0x2e, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x61, - 0x73, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x62, 0x2e, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x43, 0x61, 0x73, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x74, 0x79, - 0x70, 0x65, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x27, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x6f, 0x66, 0x20, 0x62, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x27, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x20, - 0x65, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x63, 0x79, 0x63, 0x6c, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, - 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, - 0x63, 0x79, 0x63, 0x6c, 0x69, 0x63, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, - 0x20, 0x69, 0x73, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x64, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x45, 0x53, 0x20, 0x35, 0x2e, 0x31, 0x20, - 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x35, 0x2e, 0x31, - 0x32, 0x2e, 0x33, 0x2c, 0x20, 0x61, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x60, 0x4a, 0x4f, 0x60, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, - 0x72, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x61, - 0x53, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, - 0x28, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2d, 0x2d, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4c, 0x69, - 0x6e, 0x65, 0x61, 0x72, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, - 0x20, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, - 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x6c, - 0x79, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, - 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x5b, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5d, 0x20, 0x3d, 0x3d, 0x20, 0x61, - 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x62, 0x53, 0x74, - 0x61, 0x63, 0x6b, 0x5b, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5d, 0x20, - 0x3d, 0x3d, 0x20, 0x62, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x74, 0x61, 0x63, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x76, - 0x65, 0x72, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x53, 0x74, 0x61, 0x63, - 0x6b, 0x2e, 0x70, 0x75, 0x73, 0x68, 0x28, 0x61, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x62, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x70, 0x75, - 0x73, 0x68, 0x28, 0x62, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x30, 0x2c, - 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, - 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, - 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, - 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, - 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x5d, 0x27, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, - 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x65, 0x20, 0x69, 0x66, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, - 0x70, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, - 0x20, 0x69, 0x73, 0x20, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, - 0x79, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x69, 0x7a, - 0x65, 0x20, 0x3d, 0x20, 0x61, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x3d, - 0x20, 0x62, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x65, 0x70, 0x20, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x69, 0x67, 0x6e, - 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x6e, 0x75, - 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x73, 0x69, 0x7a, - 0x65, 0x2d, 0x2d, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x28, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x65, 0x71, 0x28, 0x61, - 0x5b, 0x73, 0x69, 0x7a, 0x65, 0x5d, 0x2c, 0x20, 0x62, 0x5b, 0x73, 0x69, - 0x7a, 0x65, 0x5d, 0x2c, 0x20, 0x61, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x2c, - 0x20, 0x62, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x29, 0x29, 0x29, 0x20, 0x62, - 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x64, - 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x61, 0x72, - 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, - 0x6c, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x60, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x60, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x64, 0x69, - 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x61, 0x6d, - 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x43, 0x74, 0x6f, 0x72, 0x20, - 0x3d, 0x20, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x62, 0x43, 0x74, 0x6f, 0x72, 0x20, 0x3d, - 0x20, 0x62, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x61, 0x43, 0x74, 0x6f, 0x72, 0x20, 0x21, 0x3d, 0x3d, 0x20, - 0x62, 0x43, 0x74, 0x6f, 0x72, 0x20, 0x26, 0x26, 0x20, 0x21, 0x28, 0x5f, - 0x2e, 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x61, 0x43, 0x74, 0x6f, 0x72, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x61, - 0x43, 0x74, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, - 0x65, 0x6f, 0x66, 0x20, 0x61, 0x43, 0x74, 0x6f, 0x72, 0x29, 0x20, 0x26, - 0x26, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x2e, 0x69, - 0x73, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x62, 0x43, - 0x74, 0x6f, 0x72, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x43, 0x74, - 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x6f, - 0x66, 0x20, 0x62, 0x43, 0x74, 0x6f, 0x72, 0x29, 0x29, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x65, 0x70, 0x20, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x28, 0x76, 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, - 0x61, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x68, 0x61, 0x73, 0x28, 0x61, - 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x70, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x20, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, - 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2b, 0x2b, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, - 0x65, 0x65, 0x70, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x2e, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x21, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, - 0x3d, 0x20, 0x5f, 0x2e, 0x68, 0x61, 0x73, 0x28, 0x62, 0x2c, 0x20, 0x6b, - 0x65, 0x79, 0x29, 0x20, 0x26, 0x26, 0x20, 0x65, 0x71, 0x28, 0x61, 0x5b, - 0x6b, 0x65, 0x79, 0x5d, 0x2c, 0x20, 0x62, 0x5b, 0x6b, 0x65, 0x79, 0x5d, - 0x2c, 0x20, 0x61, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x2c, 0x20, 0x62, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x29, 0x29, 0x29, 0x20, 0x62, 0x72, 0x65, 0x61, - 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6b, 0x65, 0x79, 0x20, 0x69, - 0x6e, 0x20, 0x62, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x68, - 0x61, 0x73, 0x28, 0x62, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x26, - 0x26, 0x20, 0x21, 0x28, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x2d, 0x29, 0x29, - 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x21, - 0x73, 0x69, 0x7a, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x2e, 0x70, 0x6f, 0x70, 0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x62, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x2e, 0x70, 0x6f, 0x70, - 0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x3b, 0x0a, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x50, 0x65, - 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, 0x70, - 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x20, - 0x74, 0x6f, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x69, 0x66, 0x20, - 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x3d, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x61, 0x2c, - 0x20, 0x62, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x71, 0x28, 0x61, 0x2c, 0x20, 0x62, - 0x2c, 0x20, 0x5b, 0x5d, 0x2c, 0x20, 0x5b, 0x5d, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x73, - 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, - 0x6f, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x65, 0x6d, - 0x70, 0x74, 0x79, 0x3f, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x6e, - 0x20, 0x22, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x65, - 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x77, - 0x6e, 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x5f, 0x2e, 0x69, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, - 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x5f, 0x2e, 0x69, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x29, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x2e, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x30, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, - 0x61, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x62, - 0x6a, 0x29, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x2e, 0x68, 0x61, 0x73, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x29, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x73, 0x20, 0x61, 0x20, 0x67, - 0x69, 0x76, 0x65, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x61, - 0x20, 0x44, 0x4f, 0x4d, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x3f, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x45, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x21, 0x21, 0x28, - 0x6f, 0x62, 0x6a, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x20, 0x3d, 0x3d, 0x3d, 0x20, - 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x49, 0x73, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x3f, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, - 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x45, 0x43, 0x4d, 0x41, 0x35, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x69, 0x73, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x3d, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x49, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x7c, 0x7c, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x3d, 0x3d, - 0x20, 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x41, 0x72, - 0x72, 0x61, 0x79, 0x5d, 0x27, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x73, 0x20, 0x61, 0x20, 0x67, - 0x69, 0x76, 0x65, 0x6e, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3f, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x20, 0x3d, - 0x3d, 0x3d, 0x20, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x6f, 0x62, - 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x41, 0x64, 0x64, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, - 0x69, 0x73, 0x54, 0x79, 0x70, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x73, 0x3a, 0x20, 0x69, 0x73, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x69, 0x73, 0x46, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x2c, 0x20, 0x69, 0x73, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2c, - 0x20, 0x69, 0x73, 0x44, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x69, 0x73, 0x52, - 0x65, 0x67, 0x45, 0x78, 0x70, 0x2e, 0x0a, 0x20, 0x20, 0x65, 0x61, 0x63, - 0x68, 0x28, 0x5b, 0x27, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x27, 0x2c, 0x20, 0x27, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x27, 0x2c, 0x20, 0x27, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x27, - 0x2c, 0x20, 0x27, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x27, 0x2c, 0x20, - 0x27, 0x44, 0x61, 0x74, 0x65, 0x27, 0x2c, 0x20, 0x27, 0x52, 0x65, 0x67, - 0x45, 0x78, 0x70, 0x27, 0x5d, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5b, 0x27, 0x69, 0x73, 0x27, 0x20, 0x2b, - 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x74, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, - 0x61, 0x6c, 0x6c, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x3d, 0x3d, 0x20, - 0x27, 0x5b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x27, 0x20, 0x2b, - 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2b, 0x20, 0x27, 0x5d, 0x27, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x29, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x66, 0x69, - 0x6e, 0x65, 0x20, 0x61, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, - 0x69, 0x6e, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x73, 0x20, - 0x28, 0x61, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x49, 0x45, 0x29, 0x2c, 0x20, - 0x77, 0x68, 0x65, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x61, - 0x6e, 0x79, 0x20, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x61, 0x62, - 0x6c, 0x65, 0x20, 0x22, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x21, 0x5f, 0x2e, 0x69, 0x73, 0x41, 0x72, 0x67, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x28, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x5f, 0x2e, 0x69, 0x73, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x21, 0x21, 0x28, - 0x6f, 0x62, 0x6a, 0x20, 0x26, 0x26, 0x20, 0x5f, 0x2e, 0x68, 0x61, 0x73, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x27, 0x63, 0x61, 0x6c, 0x6c, 0x65, - 0x65, 0x27, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4f, - 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x20, 0x60, 0x69, 0x73, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x60, 0x20, 0x69, 0x66, 0x20, - 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x65, 0x2e, - 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x74, 0x79, 0x70, 0x65, 0x6f, - 0x66, 0x20, 0x28, 0x2f, 0x2e, 0x2f, 0x29, 0x20, 0x21, 0x3d, 0x3d, 0x20, - 0x27, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x46, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x6f, 0x66, 0x20, 0x6f, 0x62, 0x6a, - 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x27, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x27, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x73, - 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x20, 0x61, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, - 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3f, 0x0a, 0x20, 0x20, 0x5f, - 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x69, 0x73, 0x46, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x28, - 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x26, 0x26, 0x20, 0x21, 0x69, 0x73, 0x4e, - 0x61, 0x4e, 0x28, 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x6c, 0x6f, 0x61, - 0x74, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x20, 0x60, 0x4e, 0x61, 0x4e, 0x60, 0x3f, 0x20, 0x28, 0x4e, - 0x61, 0x4e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, - 0x6c, 0x79, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x77, 0x68, - 0x69, 0x63, 0x68, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, - 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, - 0x66, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x4e, 0x61, - 0x4e, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x4e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x26, - 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x20, 0x21, 0x3d, 0x20, 0x2b, 0x6f, 0x62, - 0x6a, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x49, 0x73, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, - 0x6c, 0x65, 0x61, 0x6e, 0x3f, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x73, - 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x74, 0x72, 0x75, - 0x65, 0x20, 0x7c, 0x7c, 0x20, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x3d, - 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x20, 0x7c, 0x7c, 0x20, 0x74, 0x6f, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, - 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x5b, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x20, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, - 0x5d, 0x27, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x49, 0x73, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x65, 0x71, 0x75, 0x61, - 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3f, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x6e, - 0x75, 0x6c, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x73, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, - 0x65, 0x6e, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x75, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x3f, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x62, 0x6a, 0x20, - 0x3d, 0x3d, 0x3d, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x30, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x53, - 0x68, 0x6f, 0x72, 0x74, 0x63, 0x75, 0x74, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x66, 0x20, 0x61, 0x6e, 0x20, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, - 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, - 0x72, 0x74, 0x79, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x6f, 0x6e, 0x20, 0x69, 0x74, 0x73, - 0x65, 0x6c, 0x66, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x6e, 0x6f, 0x74, - 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, - 0x79, 0x70, 0x65, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x68, 0x61, - 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x68, 0x61, 0x73, 0x4f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, - 0x74, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6f, 0x62, 0x6a, 0x2c, - 0x20, 0x6b, 0x65, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x75, 0x6e, 0x20, 0x55, 0x6e, 0x64, - 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x6a, 0x73, 0x20, 0x69, - 0x6e, 0x20, 0x2a, 0x6e, 0x6f, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, - 0x74, 0x2a, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, - 0x5f, 0x60, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x69, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x2e, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, - 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, - 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6e, 0x6f, 0x43, 0x6f, 0x6e, 0x66, - 0x6c, 0x69, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x5f, 0x20, 0x3d, 0x20, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3b, 0x0a, 0x20, 0x20, - 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4b, 0x65, 0x65, - 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x75, 0x6e, 0x20, - 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2a, - 0x2a, 0x6e, 0x2a, 0x2a, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x2c, 0x20, - 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x63, 0x63, 0x75, 0x6d, 0x20, 0x3d, - 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x28, 0x6e, 0x29, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x76, 0x61, 0x72, 0x20, - 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6e, - 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x61, 0x63, 0x63, 0x75, 0x6d, - 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, - 0x6f, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x2c, 0x20, 0x69, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x63, 0x63, 0x75, - 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x72, - 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, - 0x72, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x69, - 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x28, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x29, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x3d, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x69, 0x6e, - 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x6d, 0x61, 0x78, 0x20, 0x3d, 0x3d, 0x20, - 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x20, 0x3d, - 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x69, 0x6e, - 0x20, 0x2b, 0x20, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x66, 0x6c, 0x6f, 0x6f, - 0x72, 0x28, 0x4d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61, 0x6e, 0x64, 0x6f, - 0x6d, 0x28, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x61, 0x78, 0x20, 0x2d, - 0x20, 0x6d, 0x69, 0x6e, 0x20, 0x2b, 0x20, 0x31, 0x29, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4c, - 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x20, - 0x20, 0x76, 0x61, 0x72, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, - 0x61, 0x70, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, - 0x73, 0x63, 0x61, 0x70, 0x65, 0x3a, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x27, 0x26, 0x27, 0x3a, 0x20, 0x27, 0x26, 0x61, 0x6d, - 0x70, 0x3b, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, - 0x3c, 0x27, 0x3a, 0x20, 0x27, 0x26, 0x6c, 0x74, 0x3b, 0x27, 0x2c, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x3e, 0x27, 0x3a, 0x20, 0x27, - 0x26, 0x67, 0x74, 0x3b, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x27, 0x22, 0x27, 0x3a, 0x20, 0x27, 0x26, 0x71, 0x75, 0x6f, 0x74, - 0x3b, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x27, - 0x22, 0x3a, 0x20, 0x27, 0x26, 0x23, 0x78, 0x32, 0x37, 0x3b, 0x27, 0x2c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x2f, 0x27, 0x3a, 0x20, - 0x27, 0x26, 0x23, 0x78, 0x32, 0x46, 0x3b, 0x27, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x2e, 0x75, 0x6e, 0x65, 0x73, - 0x63, 0x61, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x69, 0x6e, 0x76, - 0x65, 0x72, 0x74, 0x28, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, - 0x70, 0x2e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x29, 0x3b, 0x0a, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x67, 0x65, 0x78, 0x65, 0x73, - 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, - 0x65, 0x64, 0x20, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x6c, 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x2e, 0x0a, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x67, 0x65, 0x78, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3a, 0x20, 0x20, 0x20, - 0x6e, 0x65, 0x77, 0x20, 0x52, 0x65, 0x67, 0x45, 0x78, 0x70, 0x28, 0x27, - 0x5b, 0x27, 0x20, 0x2b, 0x20, 0x5f, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x2e, 0x65, 0x73, - 0x63, 0x61, 0x70, 0x65, 0x29, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x27, - 0x27, 0x29, 0x20, 0x2b, 0x20, 0x27, 0x5d, 0x27, 0x2c, 0x20, 0x27, 0x67, - 0x27, 0x29, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x6e, 0x65, 0x73, - 0x63, 0x61, 0x70, 0x65, 0x3a, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x52, 0x65, - 0x67, 0x45, 0x78, 0x70, 0x28, 0x27, 0x28, 0x27, 0x20, 0x2b, 0x20, 0x5f, - 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x28, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x4d, 0x61, 0x70, 0x2e, 0x75, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, - 0x29, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28, 0x27, 0x7c, 0x27, 0x29, 0x20, - 0x2b, 0x20, 0x27, 0x29, 0x27, 0x2c, 0x20, 0x27, 0x67, 0x27, 0x29, 0x0a, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x75, 0x6e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x69, 0x6e, 0x67, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x6f, 0x2f, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x65, 0x61, 0x63, 0x68, 0x28, 0x5b, 0x27, - 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x27, 0x2c, 0x20, 0x27, 0x75, 0x6e, - 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x27, 0x5d, 0x2c, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5b, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x3d, 0x20, - 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x20, 0x27, 0x27, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x27, 0x27, 0x20, 0x2b, 0x20, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x29, 0x2e, 0x72, 0x65, 0x70, 0x6c, - 0x61, 0x63, 0x65, 0x28, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x67, 0x65, 0x78, 0x65, 0x73, 0x5b, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x5d, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x61, 0x70, 0x5b, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x5d, 0x5b, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x5d, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x29, 0x3b, - 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x20, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6e, - 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x3b, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, - 0x73, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, - 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x66, 0x20, 0x28, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, - 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x3d, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5b, 0x70, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x2e, 0x69, 0x73, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x29, 0x20, 0x3f, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x63, - 0x61, 0x6c, 0x6c, 0x28, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x29, 0x20, - 0x3a, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x64, 0x64, 0x20, - 0x79, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x64, - 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6d, 0x69, 0x78, 0x69, - 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x28, 0x5f, 0x2e, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x2c, 0x20, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x61, 0x6d, 0x65, - 0x29, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x5f, 0x5b, 0x6e, 0x61, - 0x6d, 0x65, 0x5d, 0x20, 0x3d, 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x6e, 0x61, - 0x6d, 0x65, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x5b, 0x6e, - 0x61, 0x6d, 0x65, 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x61, 0x72, 0x67, 0x73, - 0x20, 0x3d, 0x20, 0x5b, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x5f, 0x77, 0x72, - 0x61, 0x70, 0x70, 0x65, 0x64, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x70, 0x75, 0x73, 0x68, 0x2e, 0x61, 0x70, 0x70, - 0x6c, 0x79, 0x28, 0x61, 0x72, 0x67, 0x73, 0x2c, 0x20, 0x61, 0x72, 0x67, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, - 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x2e, 0x61, - 0x70, 0x70, 0x6c, 0x79, 0x28, 0x5f, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x73, - 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, - 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x20, 0x69, 0x64, - 0x20, 0x28, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x69, - 0x72, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x55, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x20, 0x44, 0x4f, - 0x4d, 0x20, 0x69, 0x64, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x20, 0x69, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x3d, - 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x75, 0x6e, 0x69, 0x71, - 0x75, 0x65, 0x49, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x29, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x64, - 0x20, 0x3d, 0x20, 0x2b, 0x2b, 0x69, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x65, 0x72, 0x20, 0x2b, 0x20, 0x27, 0x27, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x20, 0x3f, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, - 0x2b, 0x20, 0x69, 0x64, 0x20, 0x3a, 0x20, 0x69, 0x64, 0x3b, 0x0a, 0x20, - 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x42, 0x79, - 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x20, 0x55, 0x6e, - 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x73, 0x20, 0x45, 0x52, 0x42, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x64, 0x65, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, - 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, - 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x5f, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x20, 0x2f, 0x3c, 0x25, 0x28, 0x5b, - 0x5c, 0x73, 0x5c, 0x53, 0x5d, 0x2b, 0x3f, 0x29, 0x25, 0x3e, 0x2f, 0x67, - 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x3a, 0x20, 0x2f, 0x3c, 0x25, 0x3d, - 0x28, 0x5b, 0x5c, 0x73, 0x5c, 0x53, 0x5d, 0x2b, 0x3f, 0x29, 0x25, 0x3e, - 0x2f, 0x67, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x73, 0x63, 0x61, - 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x20, 0x2f, 0x3c, - 0x25, 0x2d, 0x28, 0x5b, 0x5c, 0x73, 0x5c, 0x53, 0x5d, 0x2b, 0x3f, 0x29, - 0x25, 0x3e, 0x2f, 0x67, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x20, 0x60, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x60, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, - 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, - 0x6f, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x0a, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x65, 0x76, 0x61, 0x6c, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x73, - 0x63, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x67, 0x65, 0x78, - 0x2c, 0x20, 0x77, 0x65, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x6f, 0x6e, - 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x65, - 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6e, 0x6f, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x2f, 0x28, 0x2e, 0x29, - 0x5e, 0x2f, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x65, - 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, - 0x74, 0x65, 0x72, 0x73, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, - 0x20, 0x62, 0x65, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x20, - 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, - 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, - 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6c, 0x69, 0x74, 0x65, 0x72, - 0x61, 0x6c, 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x65, 0x73, - 0x63, 0x61, 0x70, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x22, 0x27, 0x22, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x22, 0x27, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x27, 0x5c, 0x5c, - 0x27, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x5c, 0x5c, 0x27, 0x2c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x27, 0x5c, 0x72, 0x27, 0x3a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x27, 0x72, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x27, 0x5c, 0x6e, 0x27, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x6e, - 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x27, 0x5c, 0x74, 0x27, 0x3a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x74, 0x27, 0x2c, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x27, 0x5c, 0x75, 0x32, 0x30, 0x32, 0x38, 0x27, 0x3a, 0x20, - 0x27, 0x75, 0x32, 0x30, 0x32, 0x38, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x27, 0x5c, 0x75, 0x32, 0x30, 0x32, 0x39, 0x27, 0x3a, 0x20, 0x27, - 0x75, 0x32, 0x30, 0x32, 0x39, 0x27, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, - 0x65, 0x72, 0x20, 0x3d, 0x20, 0x2f, 0x5c, 0x5c, 0x7c, 0x27, 0x7c, 0x5c, - 0x72, 0x7c, 0x5c, 0x6e, 0x7c, 0x5c, 0x74, 0x7c, 0x5c, 0x75, 0x32, 0x30, - 0x32, 0x38, 0x7c, 0x5c, 0x75, 0x32, 0x30, 0x32, 0x39, 0x2f, 0x67, 0x3b, - 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x4a, 0x61, 0x76, 0x61, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x2d, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2c, 0x20, - 0x73, 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x4a, - 0x6f, 0x68, 0x6e, 0x20, 0x52, 0x65, 0x73, 0x69, 0x67, 0x27, 0x73, 0x20, - 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x55, 0x6e, 0x64, - 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x73, 0x20, 0x61, 0x72, 0x62, 0x69, 0x74, 0x72, 0x61, 0x72, 0x79, - 0x20, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72, 0x73, 0x2c, - 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x73, 0x20, 0x77, - 0x68, 0x69, 0x74, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2c, 0x0a, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x63, 0x74, 0x6c, 0x79, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, - 0x73, 0x20, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, - 0x61, 0x74, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x0a, 0x20, - 0x20, 0x5f, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, - 0x65, 0x78, 0x74, 0x2c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x73, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, - 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x2e, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x73, 0x28, 0x7b, 0x7d, 0x2c, 0x20, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x5f, 0x2e, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x65, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, - 0x6f, 0x6e, 0x65, 0x20, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x20, - 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x76, - 0x69, 0x61, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6e, 0x65, - 0x77, 0x20, 0x52, 0x65, 0x67, 0x45, 0x78, 0x70, 0x28, 0x5b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x7c, 0x7c, - 0x20, 0x6e, 0x6f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x29, 0x2e, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x7c, 0x7c, - 0x20, 0x6e, 0x6f, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x29, 0x2e, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x65, 0x76, - 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x7c, 0x7c, 0x20, 0x6e, 0x6f, - 0x4d, 0x61, 0x74, 0x63, 0x68, 0x29, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5d, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, - 0x28, 0x27, 0x7c, 0x27, 0x29, 0x20, 0x2b, 0x20, 0x27, 0x7c, 0x24, 0x27, - 0x2c, 0x20, 0x27, 0x67, 0x27, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x2f, 0x2f, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2c, 0x20, 0x65, 0x73, 0x63, - 0x61, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x20, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x70, - 0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x2e, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x3d, - 0x20, 0x22, 0x5f, 0x5f, 0x70, 0x2b, 0x3d, 0x27, 0x22, 0x3b, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x72, 0x65, 0x70, 0x6c, - 0x61, 0x63, 0x65, 0x28, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2c, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x2c, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2c, - 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x65, - 0x2c, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x2c, 0x20, - 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x2b, - 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x73, 0x6c, 0x69, 0x63, 0x65, - 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x6f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x65, 0x73, 0x63, - 0x61, 0x70, 0x65, 0x72, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x28, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x29, 0x20, 0x7b, 0x20, - 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x27, 0x5c, 0x5c, 0x27, 0x20, - 0x2b, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x73, 0x5b, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x5d, 0x3b, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x65, 0x73, 0x63, - 0x61, 0x70, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x2b, 0x3d, - 0x20, 0x22, 0x27, 0x2b, 0x5c, 0x6e, 0x28, 0x28, 0x5f, 0x5f, 0x74, 0x3d, - 0x28, 0x22, 0x20, 0x2b, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, - 0x2b, 0x20, 0x22, 0x29, 0x29, 0x3d, 0x3d, 0x6e, 0x75, 0x6c, 0x6c, 0x3f, - 0x27, 0x27, 0x3a, 0x5f, 0x2e, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x28, - 0x5f, 0x5f, 0x74, 0x29, 0x29, 0x2b, 0x5c, 0x6e, 0x27, 0x22, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, - 0x2b, 0x3d, 0x20, 0x22, 0x27, 0x2b, 0x5c, 0x6e, 0x28, 0x28, 0x5f, 0x5f, - 0x74, 0x3d, 0x28, 0x22, 0x20, 0x2b, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x29, 0x29, - 0x3d, 0x3d, 0x6e, 0x75, 0x6c, 0x6c, 0x3f, 0x27, 0x27, 0x3a, 0x5f, 0x5f, - 0x74, 0x29, 0x2b, 0x5c, 0x6e, 0x27, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x66, 0x20, 0x28, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x29, - 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x2b, 0x3d, 0x20, 0x22, 0x27, 0x3b, - 0x5c, 0x6e, 0x22, 0x20, 0x2b, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, - 0x74, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x5c, 0x6e, 0x5f, 0x5f, 0x70, 0x2b, - 0x3d, 0x27, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x20, 0x3d, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x2b, 0x20, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x20, 0x2b, 0x3d, 0x20, 0x22, 0x27, 0x3b, 0x5c, - 0x6e, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, - 0x49, 0x66, 0x20, 0x61, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, - 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, - 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, - 0x20, 0x28, 0x21, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, - 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x20, 0x3d, 0x20, 0x27, 0x77, 0x69, 0x74, 0x68, - 0x28, 0x6f, 0x62, 0x6a, 0x7c, 0x7c, 0x7b, 0x7d, 0x29, 0x7b, 0x5c, 0x6e, - 0x27, 0x20, 0x2b, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x2b, - 0x20, 0x27, 0x7d, 0x5c, 0x6e, 0x27, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x76, - 0x61, 0x72, 0x20, 0x5f, 0x5f, 0x74, 0x2c, 0x5f, 0x5f, 0x70, 0x3d, 0x27, - 0x27, 0x2c, 0x5f, 0x5f, 0x6a, 0x3d, 0x41, 0x72, 0x72, 0x61, 0x79, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x6a, 0x6f, - 0x69, 0x6e, 0x2c, 0x22, 0x20, 0x2b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x22, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x3d, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x5f, 0x5f, 0x70, 0x2b, 0x3d, - 0x5f, 0x5f, 0x6a, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x61, 0x72, 0x67, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x27, 0x27, 0x29, 0x3b, 0x7d, - 0x3b, 0x5c, 0x6e, 0x22, 0x20, 0x2b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x5f, 0x70, 0x3b, 0x5c, 0x6e, - 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x79, 0x20, - 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x46, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x7c, 0x7c, 0x20, 0x27, 0x6f, 0x62, 0x6a, 0x27, 0x2c, 0x20, 0x27, 0x5f, - 0x27, 0x2c, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x63, 0x61, 0x74, 0x63, 0x68, 0x20, - 0x28, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x3d, 0x20, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x65, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x64, 0x61, 0x74, 0x61, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x64, 0x61, 0x74, - 0x61, 0x2c, 0x20, 0x5f, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x61, 0x72, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x64, - 0x61, 0x74, 0x61, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x74, 0x68, 0x69, 0x73, - 0x2c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2c, 0x20, 0x5f, 0x29, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e, - 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x20, 0x3d, 0x20, 0x27, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x27, 0x20, 0x2b, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x2e, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, - 0x7c, 0x7c, 0x20, 0x27, 0x6f, 0x62, 0x6a, 0x27, 0x29, 0x20, 0x2b, 0x20, - 0x27, 0x29, 0x7b, 0x5c, 0x6e, 0x27, 0x20, 0x2b, 0x20, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x20, 0x2b, 0x20, 0x27, 0x7d, 0x27, 0x3b, 0x0a, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, - 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x64, 0x64, 0x20, - 0x61, 0x20, 0x22, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, - 0x68, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, - 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, - 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x28, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x4f, 0x4f, 0x50, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2d, 0x2d, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x49, 0x66, 0x20, 0x55, - 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x73, - 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, - 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x69, - 0x74, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, - 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, - 0x20, 0x4f, 0x4f, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x20, 0x54, - 0x68, 0x69, 0x73, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, - 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x65, - 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, - 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, - 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x20, 0x20, - 0x2f, 0x2f, 0x20, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x28, 0x6f, 0x62, 0x6a, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x2e, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x3f, 0x20, 0x5f, 0x28, - 0x6f, 0x62, 0x6a, 0x29, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x28, 0x29, - 0x20, 0x3a, 0x20, 0x6f, 0x62, 0x6a, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, - 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, 0x64, 0x64, 0x20, 0x61, - 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x6e, - 0x64, 0x65, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x6d, 0x69, - 0x78, 0x69, 0x6e, 0x28, 0x5f, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, - 0x2f, 0x20, 0x41, 0x64, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x75, - 0x74, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, - 0x2e, 0x0a, 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x5b, 0x27, 0x70, - 0x6f, 0x70, 0x27, 0x2c, 0x20, 0x27, 0x70, 0x75, 0x73, 0x68, 0x27, 0x2c, - 0x20, 0x27, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x27, 0x2c, 0x20, - 0x27, 0x73, 0x68, 0x69, 0x66, 0x74, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x6f, - 0x72, 0x74, 0x27, 0x2c, 0x20, 0x27, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, - 0x27, 0x2c, 0x20, 0x27, 0x75, 0x6e, 0x73, 0x68, 0x69, 0x66, 0x74, 0x27, - 0x5d, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, - 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x72, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x3d, - 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5b, - 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x5b, 0x6e, - 0x61, 0x6d, 0x65, 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x20, 0x3d, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x2e, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, - 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x28, 0x6f, 0x62, - 0x6a, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, - 0x28, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x73, - 0x68, 0x69, 0x66, 0x74, 0x27, 0x20, 0x7c, 0x7c, 0x20, 0x6e, 0x61, 0x6d, - 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, - 0x27, 0x29, 0x20, 0x26, 0x26, 0x20, 0x6f, 0x62, 0x6a, 0x2e, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, - 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x5b, 0x30, - 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x63, - 0x61, 0x6c, 0x6c, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x6f, 0x62, - 0x6a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, - 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x41, - 0x64, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x6f, 0x72, 0x20, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x66, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e, 0x0a, - 0x20, 0x20, 0x65, 0x61, 0x63, 0x68, 0x28, 0x5b, 0x27, 0x63, 0x6f, 0x6e, - 0x63, 0x61, 0x74, 0x27, 0x2c, 0x20, 0x27, 0x6a, 0x6f, 0x69, 0x6e, 0x27, - 0x2c, 0x20, 0x27, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x27, 0x5d, 0x2c, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x61, 0x6d, - 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, - 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x3d, 0x20, 0x41, 0x72, - 0x72, 0x61, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x5b, 0x6e, 0x61, 0x6d, - 0x65, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x5b, 0x6e, 0x61, 0x6d, 0x65, - 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x79, - 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, - 0x65, 0x64, 0x2c, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, - 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x5f, 0x2e, 0x65, - 0x78, 0x74, 0x65, 0x6e, 0x64, 0x28, 0x5f, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x7b, 0x0a, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x77, 0x72, - 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x73, - 0x63, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x3a, 0x20, - 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, - 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, - 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x7d, 0x2c, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, - 0x20, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, - 0x61, 0x6e, 0x64, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x69, - 0x73, 0x2e, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3b, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x7d, 0x29, 0x3b, - 0x0a, 0x0a, 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x74, 0x68, - 0x69, 0x73, 0x29, 0x3b, 0x0a, - } -} - -// Underscore.js 1.4.4 -// http://underscorejs.org -// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore may be freely distributed under the MIT license. diff --git a/vendor/github.com/robertkrimen/otto/underscore/testify b/vendor/github.com/robertkrimen/otto/underscore/testify deleted file mode 100755 index 7f6e0f7c119..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore/testify +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -my $underscore_test = shift @ARGV || ""; -if (!-d $underscore_test) { - print <<_END_; -Usage: - - testify ./underscore/test - - # Should look something like: - arrays.js - chaining.js - collections.js - functions.js - index.html - objects.js - speed.js - utility.js - vendor - -_END_ - if ($underscore_test) { - die "!: Not a directory: $underscore_test\n" - } - exit; -} - -chdir $underscore_test or die "!: $!"; - -my @js = <*.js>; - -for my $file (@js) { - open my $fh, '<', $file or die "!: $!"; - my $tests = join "", <$fh>; - my @tests = $tests =~ m/ - ^(\s{2}test\(.*? - ^\s{2}}\);)$ - /mgxs; - close $fh; - next unless @tests; - print "$file: ", scalar(@tests), "\n"; - my $underscore_name = "underscore_$file"; - $underscore_name =~ s/.js$//; - my $go_file = "${underscore_name}_test.go"; - $go_file =~ s/.js$/.go/; - open $fh, '>', $go_file or die "!: $!"; - - $fh->print(<<_END_); -package otto - -import ( - "testing" -) - -_END_ - - my $count = 0; - for my $test (@tests) { - $test =~ s/`([^`]+)`/<$1>/g; - my ($name) = $test =~ m/^\s*test\(['"]([^'"]+)['"]/; - $fh->print(<<_END_); -// $name -func Test_${underscore_name}_$count(t *testing.T) { - tt(t, func(){ - test := underscoreTest() - - test(` -$test - `) - }) -} - -_END_ - $count++; - } -} - -# test('#779 - delimeters are applied to unescaped text.', 1, function() { -# var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g}); -# strictEqual(template(), '<<\nx\n>>'); -# }); diff --git a/vendor/github.com/robertkrimen/otto/underscore/underscore.go b/vendor/github.com/robertkrimen/otto/underscore/underscore.go deleted file mode 100644 index 714b8f3cf9f..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore/underscore.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Package underscore contains the source for the JavaScript utility-belt library. - - import ( - _ "github.com/robertkrimen/otto/underscore" - ) - // Every Otto runtime will now include underscore - -http://underscorejs.org - -https://github.com/documentcloud/underscore - -By importing this package, you'll automatically load underscore every time you create a new Otto runtime. - -To prevent this behavior, you can do the following: - - import ( - "github.com/robertkrimen/otto/underscore" - ) - - func init() { - underscore.Disable() - } - -*/ -package underscore - -import ( - "github.com/robertkrimen/otto/registry" -) - -var entry *registry.Entry = registry.Register(func() string { - return Source() -}) - -// Enable underscore runtime inclusion. -func Enable() { - entry.Enable() -} - -// Disable underscore runtime inclusion. -func Disable() { - entry.Disable() -} - -// Source returns the underscore source. -func Source() string { - return string(underscore()) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore_arrays_test.go b/vendor/github.com/robertkrimen/otto/underscore_arrays_test.go deleted file mode 100644 index 9d62978203a..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_arrays_test.go +++ /dev/null @@ -1,344 +0,0 @@ -package otto - -import ( - "testing" -) - -// first -func Test_underscore_arrays_0(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("first", function() { - equal(_.first([1,2,3]), 1, 'can pull out the first element of an array'); - equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"'); - equal(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first'); - equal(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first'); - equal(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first'); - var result = (function(){ return _.first(arguments); })(4, 3, 2, 1); - equal(result, 4, 'works on an arguments object.'); - result = _.map([[1,2,3],[1,2,3]], _.first); - equal(result.join(','), '1,1', 'works well with _.map'); - result = (function() { return _.take([1,2,3], 2); })(); - equal(result.join(','), '1,2', 'aliased as take'); - - equal(_.first(null), undefined, 'handles nulls'); - }); - `) - }) -} - -// rest -func Test_underscore_arrays_1(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("rest", function() { - var numbers = [1, 2, 3, 4]; - equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()'); - equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)'); - equal(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index'); - var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4); - equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object'); - result = _.map([[1,2,3],[1,2,3]], _.rest); - equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map'); - result = (function(){ return _(arguments).drop(); })(1, 2, 3, 4); - equal(result.join(', '), '2, 3, 4', 'aliased as drop and works on arguments object'); - }); - `) - }) -} - -// initial -func Test_underscore_arrays_2(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("initial", function() { - equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()'); - equal(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index'); - var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4); - equal(result.join(", "), "1, 2, 3", 'initial works on arguments object'); - result = _.map([[1,2,3],[1,2,3]], _.initial); - equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map'); - }); - `) - }) -} - -// last -func Test_underscore_arrays_3(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("last", function() { - equal(_.last([1,2,3]), 3, 'can pull out the last element of an array'); - equal(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last'); - equal(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last'); - equal(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last'); - var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4); - equal(result, 4, 'works on an arguments object'); - result = _.map([[1,2,3],[1,2,3]], _.last); - equal(result.join(','), '3,3', 'works well with _.map'); - - equal(_.last(null), undefined, 'handles nulls'); - }); - `) - }) -} - -// compact -func Test_underscore_arrays_4(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("compact", function() { - equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); - var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3); - equal(result, 3, 'works on an arguments object'); - }); - `) - }) -} - -// flatten -func Test_underscore_arrays_5(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("flatten", function() { - var list = [1, [2], [3, [[[4]]]]]; - deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays'); - deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly flatten nested arrays'); - var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]); - deepEqual(result, [1,2,3,4], 'works on an arguments object'); - }); - `) - }) -} - -// without -func Test_underscore_arrays_6(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("without", function() { - var list = [1, 2, 1, 0, 3, 1, 4]; - equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object'); - var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4); - equal(result.join(', '), '2, 3, 4', 'works on an arguments object'); - - var list = [{one : 1}, {two : 2}]; - ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.'); - ok(_.without(list, list[0]).length == 1, 'ditto.'); - }); - `) - }) -} - -// uniq -func Test_underscore_arrays_7(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("uniq", function() { - var list = [1, 2, 1, 3, 1, 4]; - equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array'); - - var list = [1, 1, 1, 2, 2, 3]; - equal(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster'); - - var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}]; - var iterator = function(value) { return value.name; }; - equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator'); - - equal(_.map(_.uniq(list, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator without specifying whether array is sorted'); - - var iterator = function(value) { return value +1; }; - var list = [1, 2, 2, 3, 4, 4]; - equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array'); - - var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4); - equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object'); - }); - `) - }) -} - -// intersection -func Test_underscore_arrays_8(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("intersection", function() { - var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho']; - equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays'); - equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection'); - var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry'); - equal(result.join(''), 'moe', 'works on an arguments object'); - }); - `) - }) -} - -// union -func Test_underscore_arrays_9(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("union", function() { - var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]); - equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays'); - - var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]); - equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays'); - }); - `) - }) -} - -// difference -func Test_underscore_arrays_10(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("difference", function() { - var result = _.difference([1, 2, 3], [2, 30, 40]); - equal(result.join(' '), '1 3', 'takes the difference of two arrays'); - - var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]); - equal(result.join(' '), '3 4', 'takes the difference of three arrays'); - }); - `) - }) -} - -// zip -func Test_underscore_arrays_11(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('zip', function() { - var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true]; - var stooges = _.zip(names, ages, leaders); - equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths'); - }); - `) - }) -} - -// object -func Test_underscore_arrays_12(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('object', function() { - var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]); - var shouldBe = {moe: 30, larry: 40, curly: 50}; - ok(_.isEqual(result, shouldBe), 'two arrays zipped together into an object'); - - result = _.object([['one', 1], ['two', 2], ['three', 3]]); - shouldBe = {one: 1, two: 2, three: 3}; - ok(_.isEqual(result, shouldBe), 'an array of pairs zipped together into an object'); - - var stooges = {moe: 30, larry: 40, curly: 50}; - ok(_.isEqual(_.object(_.pairs(stooges)), stooges), 'an object converted to pairs and back to an object'); - - ok(_.isEqual(_.object(null), {}), 'handles nulls'); - }); - `) - }) -} - -// indexOf -func Test_underscore_arrays_13(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("indexOf", function() { - var numbers = [1, 2, 3]; - numbers.indexOf = null; - equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function'); - var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3); - equal(result, 1, 'works on an arguments object'); - equal(_.indexOf(null, 2), -1, 'handles nulls properly'); - - var numbers = [10, 20, 30, 40, 50], num = 35; - var index = _.indexOf(numbers, num, true); - equal(index, -1, '35 is not in the list'); - - numbers = [10, 20, 30, 40, 50]; num = 40; - index = _.indexOf(numbers, num, true); - equal(index, 3, '40 is in the list'); - - numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40; - index = _.indexOf(numbers, num, true); - equal(index, 1, '40 is in the list'); - - numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; - index = _.indexOf(numbers, 2, 5); - equal(index, 7, 'supports the fromIndex argument'); - }); - `) - }) -} - -// lastIndexOf -func Test_underscore_arrays_14(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("lastIndexOf", function() { - var numbers = [1, 0, 1]; - equal(_.lastIndexOf(numbers, 1), 2); - - numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0]; - numbers.lastIndexOf = null; - equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function'); - equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element'); - var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0); - equal(result, 5, 'works on an arguments object'); - equal(_.indexOf(null, 2), -1, 'handles nulls properly'); - - numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; - var index = _.lastIndexOf(numbers, 2, 2); - equal(index, 1, 'supports the fromIndex argument'); - }); - `) - }) -} - -// range -func Test_underscore_arrays_15(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("range", function() { - equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array'); - equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1'); - equal(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1'); - equal(_.range(8, 5).join(''), '', 'range with two arguments a & b, b<a generates an empty array'); - equal(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c'); - equal(_.range(3, 10, 15).join(''), '3', 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a'); - equal(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b'); - equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs'); - }); - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore_chaining_test.go b/vendor/github.com/robertkrimen/otto/underscore_chaining_test.go deleted file mode 100644 index accf04fdc69..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_chaining_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package otto - -import ( - "testing" -) - -// map/flatten/reduce -func Test_underscore_chaining_0(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("map/flatten/reduce", function() { - var lyrics = [ - "I'm a lumberjack and I'm okay", - "I sleep all night and I work all day", - "He's a lumberjack and he's okay", - "He sleeps all night and he works all day" - ]; - var counts = _(lyrics).chain() - .map(function(line) { return line.split(''); }) - .flatten() - .reduce(function(hash, l) { - hash[l] = hash[l] || 0; - hash[l]++; - return hash; - }, {}).value(); - ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song'); - }); - `) - }) -} - -// select/reject/sortBy -func Test_underscore_chaining_1(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("select/reject/sortBy", function() { - var numbers = [1,2,3,4,5,6,7,8,9,10]; - numbers = _(numbers).chain().select(function(n) { - return n % 2 == 0; - }).reject(function(n) { - return n % 4 == 0; - }).sortBy(function(n) { - return -n; - }).value(); - equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); - }); - `) - }) -} - -// select/reject/sortBy in functional style -func Test_underscore_chaining_2(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("select/reject/sortBy in functional style", function() { - var numbers = [1,2,3,4,5,6,7,8,9,10]; - numbers = _.chain(numbers).select(function(n) { - return n % 2 == 0; - }).reject(function(n) { - return n % 4 == 0; - }).sortBy(function(n) { - return -n; - }).value(); - equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers"); - }); - `) - }) -} - -// reverse/concat/unshift/pop/map -func Test_underscore_chaining_3(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("reverse/concat/unshift/pop/map", function() { - var numbers = [1,2,3,4,5]; - numbers = _(numbers).chain() - .reverse() - .concat([5, 5, 5]) - .unshift(17) - .pop() - .map(function(n){ return n * 2; }) - .value(); - equal(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.'); - }); - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore_collections_test.go b/vendor/github.com/robertkrimen/otto/underscore_collections_test.go deleted file mode 100644 index 9afc2a2b23d..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_collections_test.go +++ /dev/null @@ -1,698 +0,0 @@ -package otto - -import ( - "testing" -) - -// each -func Test_underscore_collections_0(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("each", function() { - _.each([1, 2, 3], function(num, i) { - equal(num, i + 1, 'each iterators provide value and iteration count'); - }); - - var answers = []; - _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5}); - equal(answers.join(', '), '5, 10, 15', 'context object property accessed'); - - answers = []; - _.forEach([1, 2, 3], function(num){ answers.push(num); }); - equal(answers.join(', '), '1, 2, 3', 'aliased as "forEach"'); - - answers = []; - var obj = {one : 1, two : 2, three : 3}; - obj.constructor.prototype.four = 4; - _.each(obj, function(value, key){ answers.push(key); }); - equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); - delete obj.constructor.prototype.four; - - var answer = null; - _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); - ok(answer, 'can reference the original collection from inside the iterator'); - - answers = 0; - _.each(null, function(){ ++answers; }); - equal(answers, 0, 'handles a null properly'); - }); - `) - }) -} - -// map -func Test_underscore_collections_1(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('map', function() { - var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); - equal(doubled.join(', '), '2, 4, 6', 'doubled numbers'); - - doubled = _.collect([1, 2, 3], function(num){ return num * 2; }); - equal(doubled.join(', '), '2, 4, 6', 'aliased as "collect"'); - - var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3}); - equal(tripled.join(', '), '3, 6, 9', 'tripled numbers with context'); - - var doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); - equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers'); - - // TEST: ReferenceError: document is not defined - return; - - if (document.querySelectorAll) { - var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; }); - deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.'); - } - - var ids = _.map($('#map-test').children(), function(n){ return n.id; }); - deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.'); - - var ids = _.map(document.images, function(n){ return n.id; }); - ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections'); - - var ifnull = _.map(null, function(){}); - ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly'); - }); - `) - }) -} - -// reduce -func Test_underscore_collections_2(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('reduce', function() { - var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); - equal(sum, 6, 'can sum up an array'); - - var context = {multiplier : 3}; - sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context); - equal(sum, 18, 'can reduce with a context object'); - - sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0); - equal(sum, 6, 'aliased as "inject"'); - - sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0); - equal(sum, 6, 'OO-style reduce'); - - var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }); - equal(sum, 6, 'default initial value'); - - var ifnull; - try { - _.reduce(null, function(){}); - } catch (ex) { - ifnull = ex; - } - ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); - - ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); - equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); - raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); - }); - `) - }) -} - -// reduceRight -func Test_underscore_collections_3(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('reduceRight', function() { - var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); - equal(list, 'bazbarfoo', 'can perform right folds'); - - var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, ''); - equal(list, 'bazbarfoo', 'aliased as "foldr"'); - - var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }); - equal(list, 'bazbarfoo', 'default initial value'); - - var ifnull; - try { - _.reduceRight(null, function(){}); - } catch (ex) { - ifnull = ex; - } - ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); - - var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; }); - equal(sum, 6, 'default initial value on object'); - - ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); - - equal(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); - raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value'); - - // Assert that the correct arguments are being passed. - - var args, - memo = {}, - object = {a: 1, b: 2}, - lastKey = _.keys(object).pop(); - - var expected = lastKey == 'a' - ? [memo, 1, 'a', object] - : [memo, 2, 'b', object]; - - _.reduceRight(object, function() { - args || (args = _.toArray(arguments)); - }, memo); - - deepEqual(args, expected); - - // And again, with numeric keys. - - object = {'2': 'a', '1': 'b'}; - lastKey = _.keys(object).pop(); - args = null; - - expected = lastKey == '2' - ? [memo, 'a', '2', object] - : [memo, 'b', '1', object]; - - _.reduceRight(object, function() { - args || (args = _.toArray(arguments)); - }, memo); - - deepEqual(args, expected); - }); - `) - }) -} - -// find -func Test_underscore_collections_4(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('find', function() { - var array = [1, 2, 3, 4]; - strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found '); - strictEqual(_.find(array, function() { return false; }), void 0, 'should return if is not found'); - }); - `) - }) -} - -// detect -func Test_underscore_collections_5(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('detect', function() { - var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; }); - equal(result, 2, 'found the first "2" and broke the loop'); - }); - `) - }) -} - -// select -func Test_underscore_collections_6(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('select', function() { - var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); - equal(evens.join(', '), '2, 4, 6', 'selected each even number'); - - evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); - equal(evens.join(', '), '2, 4, 6', 'aliased as "filter"'); - }); - `) - }) -} - -// reject -func Test_underscore_collections_7(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('reject', function() { - var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; }); - equal(odds.join(', '), '1, 3, 5', 'rejected each even number'); - - var context = "obj"; - - var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){ - equal(context, "obj"); - return num % 2 != 0; - }, context); - equal(evens.join(', '), '2, 4, 6', 'rejected each odd number'); - }); - `) - }) -} - -// all -func Test_underscore_collections_8(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('all', function() { - ok(_.all([], _.identity), 'the empty set'); - ok(_.all([true, true, true], _.identity), 'all true values'); - ok(!_.all([true, false, true], _.identity), 'one false value'); - ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers'); - ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number'); - ok(_.all([1], _.identity) === true, 'cast to boolean - true'); - ok(_.all([0], _.identity) === false, 'cast to boolean - false'); - ok(_.every([true, true, true], _.identity), 'aliased as "every"'); - ok(!_.all([undefined, undefined, undefined], _.identity), 'works with arrays of undefined'); - }); - `) - }) -} - -// any -func Test_underscore_collections_9(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('any', function() { - var nativeSome = Array.prototype.some; - Array.prototype.some = null; - ok(!_.any([]), 'the empty set'); - ok(!_.any([false, false, false]), 'all false values'); - ok(_.any([false, false, true]), 'one true value'); - ok(_.any([null, 0, 'yes', false]), 'a string'); - ok(!_.any([null, 0, '', false]), 'falsy values'); - ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers'); - ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number'); - ok(_.any([1], _.identity) === true, 'cast to boolean - true'); - ok(_.any([0], _.identity) === false, 'cast to boolean - false'); - ok(_.some([false, false, true]), 'aliased as "some"'); - Array.prototype.some = nativeSome; - }); - `) - }) -} - -// include -func Test_underscore_collections_10(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('include', function() { - ok(_.include([1,2,3], 2), 'two is in the array'); - ok(!_.include([1,3,9], 2), 'two is not in the array'); - ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values'); - ok(_([1,2,3]).include(2), 'OO-style include'); - }); - `) - }) -} - -// invoke -func Test_underscore_collections_11(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('invoke', function() { - var list = [[5, 1, 7], [3, 2, 1]]; - var result = _.invoke(list, 'sort'); - equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); - equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); - }); - `) - }) -} - -// invoke w/ function reference -func Test_underscore_collections_12(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('invoke w/ function reference', function() { - var list = [[5, 1, 7], [3, 2, 1]]; - var result = _.invoke(list, Array.prototype.sort); - equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); - equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); - }); - `) - }) -} - -// invoke when strings have a call method -func Test_underscore_collections_13(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('invoke when strings have a call method', function() { - String.prototype.call = function() { - return 42; - }; - var list = [[5, 1, 7], [3, 2, 1]]; - var s = "foo"; - equal(s.call(), 42, "call function exists"); - var result = _.invoke(list, 'sort'); - equal(result[0].join(', '), '1, 5, 7', 'first array sorted'); - equal(result[1].join(', '), '1, 2, 3', 'second array sorted'); - delete String.prototype.call; - equal(s.call, undefined, "call function removed"); - }); - `) - }) -} - -// pluck -func Test_underscore_collections_14(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('pluck', function() { - var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}]; - equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects'); - }); - `) - }) -} - -// where -func Test_underscore_collections_15(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('where', function() { - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; - var result = _.where(list, {a: 1}); - equal(result.length, 3); - equal(result[result.length - 1].b, 4); - result = _.where(list, {b: 2}); - equal(result.length, 2); - equal(result[0].a, 1); - }); - `) - }) -} - -// findWhere -func Test_underscore_collections_16(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('findWhere', function() { - var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}]; - var result = _.findWhere(list, {a: 1}); - deepEqual(result, {a: 1, b: 2}); - result = _.findWhere(list, {b: 4}); - deepEqual(result, {a: 1, b: 4}); - }); - `) - }) -} - -// max -func Test_underscore_collections_17(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('max', function() { - equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); - - var neg = _.max([1, 2, 3], function(num){ return -num; }); - equal(neg, 1, 'can perform a computation-based max'); - - equal(-Infinity, _.max({}), 'Maximum value of an empty object'); - equal(-Infinity, _.max([]), 'Maximum value of an empty array'); - equal(_.max({'a': 'a'}), -Infinity, 'Maximum value of a non-numeric collection'); - - // TEST: Takes too long - return; - - equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array"); - }); - `) - }) -} - -// min -func Test_underscore_collections_18(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('min', function() { - equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); - - var neg = _.min([1, 2, 3], function(num){ return -num; }); - equal(neg, 3, 'can perform a computation-based min'); - - equal(Infinity, _.min({}), 'Minimum value of an empty object'); - equal(Infinity, _.min([]), 'Minimum value of an empty array'); - equal(_.min({'a': 'a'}), Infinity, 'Minimum value of a non-numeric collection'); - - var now = new Date(9999999999); - var then = new Date(0); - equal(_.min([now, then]), then); - - // TEST: Takes too long - return; - - equal(1, _.min(_.range(1,300000)), "Minimum value of a too-big array"); - }); - `) - }) -} - -// sortBy -func Test_underscore_collections_19(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('sortBy', function() { - var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}]; - people = _.sortBy(people, function(person){ return person.age; }); - equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age'); - - var list = [undefined, 4, 1, undefined, 3, 2]; - equal(_.sortBy(list, _.identity).join(','), '1,2,3,4,,', 'sortBy with undefined values'); - - var list = ["one", "two", "three", "four", "five"]; - var sorted = _.sortBy(list, 'length'); - equal(sorted.join(' '), 'one two four five three', 'sorted by length'); - - function Pair(x, y) { - this.x = x; - this.y = y; - } - - var collection = [ - new Pair(1, 1), new Pair(1, 2), - new Pair(1, 3), new Pair(1, 4), - new Pair(1, 5), new Pair(1, 6), - new Pair(2, 1), new Pair(2, 2), - new Pair(2, 3), new Pair(2, 4), - new Pair(2, 5), new Pair(2, 6), - new Pair(undefined, 1), new Pair(undefined, 2), - new Pair(undefined, 3), new Pair(undefined, 4), - new Pair(undefined, 5), new Pair(undefined, 6) - ]; - - var actual = _.sortBy(collection, function(pair) { - return pair.x; - }); - - deepEqual(actual, collection, 'sortBy should be stable'); - }); - `) - }) -} - -// groupBy -func Test_underscore_collections_20(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('groupBy', function() { - var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }); - ok('0' in parity && '1' in parity, 'created a group for each value'); - equal(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group'); - - var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; - var grouped = _.groupBy(list, 'length'); - equal(grouped['3'].join(' '), 'one two six ten'); - equal(grouped['4'].join(' '), 'four five nine'); - equal(grouped['5'].join(' '), 'three seven eight'); - - var context = {}; - _.groupBy([{}], function(){ ok(this === context); }, context); - - grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { - return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; - }); - equal(grouped.constructor.length, 1); - equal(grouped.hasOwnProperty.length, 2); - - var array = [{}]; - _.groupBy(array, function(value, index, obj){ ok(obj === array); }); - - var array = [1, 2, 1, 2, 3]; - var grouped = _.groupBy(array); - equal(grouped['1'].length, 2); - equal(grouped['3'].length, 1); - }); - `) - }) -} - -// countBy -func Test_underscore_collections_21(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('countBy', function() { - var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; }); - equal(parity['true'], 2); - equal(parity['false'], 3); - - var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; - var grouped = _.countBy(list, 'length'); - equal(grouped['3'], 4); - equal(grouped['4'], 3); - equal(grouped['5'], 3); - - var context = {}; - _.countBy([{}], function(){ ok(this === context); }, context); - - grouped = _.countBy([4.2, 6.1, 6.4], function(num) { - return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; - }); - equal(grouped.constructor, 1); - equal(grouped.hasOwnProperty, 2); - - var array = [{}]; - _.countBy(array, function(value, index, obj){ ok(obj === array); }); - - var array = [1, 2, 1, 2, 3]; - var grouped = _.countBy(array); - equal(grouped['1'], 2); - equal(grouped['3'], 1); - }); - `) - }) -} - -// sortedIndex -func Test_underscore_collections_22(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('sortedIndex', function() { - var numbers = [10, 20, 30, 40, 50], num = 35; - var indexForNum = _.sortedIndex(numbers, num); - equal(indexForNum, 3, '35 should be inserted at index 3'); - - var indexFor30 = _.sortedIndex(numbers, 30); - equal(indexFor30, 2, '30 should be inserted at index 2'); - - var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}]; - var iterator = function(obj){ return obj.x; }; - strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2); - strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3); - - var context = {1: 2, 2: 3, 3: 4}; - iterator = function(obj){ return this[obj]; }; - strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1); - }); - `) - }) -} - -// shuffle -func Test_underscore_collections_23(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('shuffle', function() { - var numbers = _.range(10); - var shuffled = _.shuffle(numbers).sort(); - notStrictEqual(numbers, shuffled, 'original object is unmodified'); - equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle'); - }); - `) - }) -} - -// toArray -func Test_underscore_collections_24(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('toArray', function() { - ok(!_.isArray(arguments), 'arguments object is not an array'); - ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array'); - var a = [1,2,3]; - ok(_.toArray(a) !== a, 'array is cloned'); - equal(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements'); - - var numbers = _.toArray({one : 1, two : 2, three : 3}); - equal(numbers.join(', '), '1, 2, 3', 'object flattened into array'); - - // TEST: ReferenceError: document is not defined - return; - - // test in IE < 9 - try { - var actual = _.toArray(document.childNodes); - } catch(ex) { } - - ok(_.isArray(actual), 'should not throw converting a node list'); - }); - `) - }) -} - -// size -func Test_underscore_collections_25(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test('size', function() { - equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object'); - equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); - - var func = function() { - return _.size(arguments); - }; - - equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object'); - - equal(_.size('hello'), 5, 'can compute the size of a string'); - - equal(_.size(null), 0, 'handles nulls'); - }); - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore_functions_test.go b/vendor/github.com/robertkrimen/otto/underscore_functions_test.go deleted file mode 100644 index be59e16b3e9..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_functions_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package otto - -import ( - "testing" -) - -// bind -func Test_underscore_functions_0(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("bind", function() { - var context = {name : 'moe'}; - var func = function(arg) { return "name: " + (this.name || arg); }; - var bound = _.bind(func, context); - equal(bound(), 'name: moe', 'can bind a function to a context'); - - bound = _(func).bind(context); - equal(bound(), 'name: moe', 'can do OO-style binding'); - - bound = _.bind(func, null, 'curly'); - equal(bound(), 'name: curly', 'can bind without specifying a context'); - - func = function(salutation, name) { return salutation + ': ' + name; }; - func = _.bind(func, this, 'hello'); - equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); - - func = _.bind(func, this, 'curly'); - equal(func(), 'hello: curly', 'the function was completely applied in advance'); - - func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; - func = _.bind(func, this, 'hello', 'moe', 'curly'); - equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); - - func = function(context, message) { equal(this, context, message); }; - _.bind(func, 0, 0, 'can bind a function to <0>')(); - _.bind(func, '', '', 'can bind a function to an empty string')(); - _.bind(func, false, false, 'can bind a function to ')(); - - // These tests are only meaningful when using a browser without a native bind function - // To test this with a modern browser, set underscore's nativeBind to undefined - var F = function () { return this; }; - var Boundf = _.bind(F, {hello: "moe curly"}); - equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); - }); - `) - }) -} - -// partial -func Test_underscore_functions_1(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("partial", function() { - var obj = {name: 'moe'}; - var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); }; - - obj.func = _.partial(func, 'a', 'b'); - equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply'); - }); - `) - }) -} - -// bindAll -func Test_underscore_functions_2(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("bindAll", function() { - var curly = {name : 'curly'}, moe = { - name : 'moe', - getName : function() { return 'name: ' + this.name; }, - sayHi : function() { return 'hi: ' + this.name; } - }; - curly.getName = moe.getName; - _.bindAll(moe, 'getName', 'sayHi'); - curly.sayHi = moe.sayHi; - equal(curly.getName(), 'name: curly', 'unbound function is bound to current object'); - equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); - - curly = {name : 'curly'}; - moe = { - name : 'moe', - getName : function() { return 'name: ' + this.name; }, - sayHi : function() { return 'hi: ' + this.name; } - }; - _.bindAll(moe); - curly.sayHi = moe.sayHi; - equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object'); - }); - `) - }) -} - -// memoize -func Test_underscore_functions_3(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("memoize", function() { - var fib = function(n) { - return n < 2 ? n : fib(n - 1) + fib(n - 2); - }; - var fastFib = _.memoize(fib); - equal(fib(10), 55, 'a memoized version of fibonacci produces identical results'); - equal(fastFib(10), 55, 'a memoized version of fibonacci produces identical results'); - - var o = function(str) { - return str; - }; - var fastO = _.memoize(o); - equal(o('toString'), 'toString', 'checks hasOwnProperty'); - equal(fastO('toString'), 'toString', 'checks hasOwnProperty'); - }); - `) - }) -} - -// once -func Test_underscore_functions_4(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("once", function() { - var num = 0; - var increment = _.once(function(){ num++; }); - increment(); - increment(); - equal(num, 1); - }); - `) - }) -} - -// wrap -func Test_underscore_functions_5(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("wrap", function() { - var greet = function(name){ return "hi: " + name; }; - var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); - equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function'); - - var inner = function(){ return "Hello "; }; - var obj = {name : "Moe"}; - obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; }); - equal(obj.hi(), "Hello Moe"); - - var noop = function(){}; - var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); }); - var ret = wrapped(['whats', 'your'], 'vector', 'victor'); - deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']); - }); - `) - }) -} - -// compose -func Test_underscore_functions_6(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("compose", function() { - var greet = function(name){ return "hi: " + name; }; - var exclaim = function(sentence){ return sentence + '!'; }; - var composed = _.compose(exclaim, greet); - equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another'); - - composed = _.compose(greet, exclaim); - equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative'); - }); - `) - }) -} - -// after -func Test_underscore_functions_7(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("after", function() { - var testAfter = function(afterAmount, timesCalled) { - var afterCalled = 0; - var after = _.after(afterAmount, function() { - afterCalled++; - }); - while (timesCalled--) after(); - return afterCalled; - }; - - equal(testAfter(5, 5), 1, "after(N) should fire after being called N times"); - equal(testAfter(5, 4), 0, "after(N) should not fire unless called N times"); - equal(testAfter(0, 0), 1, "after(0) should fire immediately"); - }); - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore_objects_test.go b/vendor/github.com/robertkrimen/otto/underscore_objects_test.go deleted file mode 100644 index 1973af8ddfd..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_objects_test.go +++ /dev/null @@ -1,826 +0,0 @@ -package otto - -import ( - "testing" -) - -// keys -func Test_underscore_objects_0(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("keys", function() { - equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object'); - // the test above is not safe because it relies on for-in enumeration order - var a = []; a[1] = 0; - equal(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95'); - raises(function() { _.keys(null); }, TypeError, 'throws an error for values'); - raises(function() { _.keys(void 0); }, TypeError, 'throws an error for values'); - raises(function() { _.keys(1); }, TypeError, 'throws an error for number primitives'); - raises(function() { _.keys('a'); }, TypeError, 'throws an error for string primitives'); - raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives'); - }); - `) - }) -} - -// values -func Test_underscore_objects_1(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("values", function() { - equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object'); - equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is "length"'); - }); - `) - }) -} - -// pairs -func Test_underscore_objects_2(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("pairs", function() { - deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs'); - deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"'); - }); - `) - }) -} - -// invert -func Test_underscore_objects_3(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("invert", function() { - var obj = {first: 'Moe', second: 'Larry', third: 'Curly'}; - equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object'); - ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started'); - - var obj = {length: 3}; - ok(_.invert(obj)['3'] == 'length', 'can invert an object with "length"') - }); - `) - }) -} - -// functions -func Test_underscore_objects_4(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("functions", function() { - var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce}; - ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object'); - - var Animal = function(){}; - Animal.prototype.run = function(){}; - equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype'); - }); - `) - }) -} - -// extend -func Test_underscore_objects_5(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("extend", function() { - var result; - equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another'); - equal(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination'); - equal(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden'); - result = _.extend({x:'x'}, {a:'a'}, {b:'b'}); - ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects'); - result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'}); - ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps'); - result = _.extend({}, {a: void 0, b: null}); - equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); - - try { - result = {}; - _.extend(result, null, undefined, {a:1}); - } catch(ex) {} - - equal(result.a, 1, 'should not error on or sources'); - }); - `) - }) -} - -// pick -func Test_underscore_objects_6(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("pick", function() { - var result; - result = _.pick({a:1, b:2, c:3}, 'a', 'c'); - ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named'); - result = _.pick({a:1, b:2, c:3}, ['b', 'c']); - ok(_.isEqual(result, {b:2, c:3}), 'can restrict properties to those named in an array'); - result = _.pick({a:1, b:2, c:3}, ['a'], 'b'); - ok(_.isEqual(result, {a:1, b:2}), 'can restrict properties to those named in mixed args'); - - var Obj = function(){}; - Obj.prototype = {a: 1, b: 2, c: 3}; - ok(_.isEqual(_.pick(new Obj, 'a', 'c'), {a:1, c: 3}), 'include prototype props'); - }); - `) - }) -} - -// omit -func Test_underscore_objects_7(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("omit", function() { - var result; - result = _.omit({a:1, b:2, c:3}, 'b'); - ok(_.isEqual(result, {a:1, c:3}), 'can omit a single named property'); - result = _.omit({a:1, b:2, c:3}, 'a', 'c'); - ok(_.isEqual(result, {b:2}), 'can omit several named properties'); - result = _.omit({a:1, b:2, c:3}, ['b', 'c']); - ok(_.isEqual(result, {a:1}), 'can omit properties named in an array'); - - var Obj = function(){}; - Obj.prototype = {a: 1, b: 2, c: 3}; - ok(_.isEqual(_.omit(new Obj, 'b'), {a:1, c: 3}), 'include prototype props'); - }); - `) - }) -} - -// defaults -func Test_underscore_objects_8(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("defaults", function() { - var result; - var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"}; - - _.defaults(options, {zero: 1, one: 10, twenty: 20}); - equal(options.zero, 0, 'value exists'); - equal(options.one, 1, 'value exists'); - equal(options.twenty, 20, 'default applied'); - - _.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"}); - equal(options.empty, "", 'value exists'); - ok(_.isNaN(options.nan), "NaN isn't overridden"); - equal(options.word, "word", 'new value is added, first one wins'); - - try { - options = {}; - _.defaults(options, null, undefined, {a:1}); - } catch(ex) {} - - equal(options.a, 1, 'should not error on or sources'); - }); - `) - }) -} - -// clone -func Test_underscore_objects_9(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("clone", function() { - var moe = {name : 'moe', lucky : [13, 27, 34]}; - var clone = _.clone(moe); - equal(clone.name, 'moe', 'the clone as the attributes of the original'); - - clone.name = 'curly'; - ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original'); - - clone.lucky.push(101); - equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original'); - - equal(_.clone(undefined), void 0, 'non objects should not be changed by clone'); - equal(_.clone(1), 1, 'non objects should not be changed by clone'); - equal(_.clone(null), null, 'non objects should not be changed by clone'); - }); - `) - }) -} - -// isEqual -func Test_underscore_objects_10(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isEqual", function() { - function First() { - this.value = 1; - } - First.prototype.value = 1; - function Second() { - this.value = 1; - } - Second.prototype.value = 2; - - // Basic equality and identity comparisons. - ok(_.isEqual(null, null), " is equal to "); - ok(_.isEqual(), " is equal to "); - - ok(!_.isEqual(0, -0), "<0> is not equal to <-0>"); - ok(!_.isEqual(-0, 0), "Commutative equality is implemented for <0> and <-0>"); - ok(!_.isEqual(null, undefined), " is not equal to "); - ok(!_.isEqual(undefined, null), "Commutative equality is implemented for and "); - - // String object and primitive comparisons. - ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal"); - ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal"); - ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal"); - ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives"); - - ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal"); - ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal"); - ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom method are not equal"); - - // Number object and primitive comparisons. - ok(_.isEqual(75, 75), "Identical number primitives are equal"); - ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal"); - ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal"); - ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives"); - ok(!_.isEqual(new Number(0), -0), " and <-0> are not equal"); - ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for and <-0>"); - - ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal"); - ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a method are not equal"); - - // Comparisons involving . - ok(_.isEqual(NaN, NaN), " is equal to "); - ok(!_.isEqual(61, NaN), "A number primitive is not equal to "); - ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to "); - ok(!_.isEqual(Infinity, NaN), " is not equal to "); - - // Boolean object and primitive comparisons. - ok(_.isEqual(true, true), "Identical boolean primitives are equal"); - ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal"); - ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal"); - ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans"); - ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal"); - - // Common type coercions. - ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive "); - ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal"); - ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal"); - ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values"); - ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal"); - ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal"); - ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal"); - ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal"); - ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal"); - - // Dates. - ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal"); - ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal"); - ok(!_.isEqual(new Date(2009, 11, 13), { - getTime: function(){ - return 12606876e5; - } - }), "Date objects and objects with a method are not equal"); - ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal"); - - // Functions. - ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal"); - - // RegExps. - ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal"); - ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal"); - ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal"); - ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps"); - ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal"); - - // Empty arrays, array-like objects, and object literals. - ok(_.isEqual({}, {}), "Empty object literals are equal"); - ok(_.isEqual([], []), "Empty array literals are equal"); - ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal"); - ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal."); - ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects"); - - ok(!_.isEqual({}, []), "Object literals and array literals are not equal"); - ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays"); - - // Arrays with primitive and object values. - ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal"); - ok(_.isEqual([(/Moe/g), new Date(2009, 9, 25)], [(/Moe/g), new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal"); - - // Multi-dimensional arrays. - var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; - var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}]; - ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared"); - - // Overwrite the methods defined in ES 5.1 section 15.4.4. - a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null; - b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null; - - // Array elements and properties. - ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal"); - a.push("White Rocks"); - ok(!_.isEqual(a, b), "Arrays of different lengths are not equal"); - a.push("East Boulder"); - b.push("Gunbarrel Ranch", "Teller Farm"); - ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal"); - - // Sparse arrays. - ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal"); - ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty"); - - // Simple objects. - ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal"); - ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal"); - ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal"); - ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal"); - ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal"); - ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects"); - ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent"); - - // contains nested objects and arrays. - a = { - name: new String("Moe Howard"), - age: new Number(77), - stooge: true, - hobbies: ["acting"], - film: { - name: "Sing a Song of Six Pants", - release: new Date(1947, 9, 30), - stars: [new String("Larry Fine"), "Shemp Howard"], - minutes: new Number(16), - seconds: 54 - } - }; - - // contains equivalent nested objects and arrays. - b = { - name: new String("Moe Howard"), - age: new Number(77), - stooge: true, - hobbies: ["acting"], - film: { - name: "Sing a Song of Six Pants", - release: new Date(1947, 9, 30), - stars: [new String("Larry Fine"), "Shemp Howard"], - minutes: new Number(16), - seconds: 54 - } - }; - ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared"); - - // Instances. - ok(_.isEqual(new First, new First), "Object instances are equal"); - ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal"); - ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal"); - ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined"); - - // Circular Arrays. - (a = []).push(a); - (b = []).push(b); - ok(_.isEqual(a, b), "Arrays containing circular references are equal"); - a.push(new String("Larry")); - b.push(new String("Larry")); - ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal"); - a.push("Shemp"); - b.push("Curly"); - ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal"); - - // More circular arrays #767. - a = ["everything is checked but", "this", "is not"]; - a[1] = a; - b = ["everything is checked but", ["this", "array"], "is not"]; - ok(!_.isEqual(a, b), "Comparison of circular references with non-circular references are not equal"); - - // Circular Objects. - a = {abc: null}; - b = {abc: null}; - a.abc = a; - b.abc = b; - ok(_.isEqual(a, b), "Objects containing circular references are equal"); - a.def = 75; - b.def = 75; - ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal"); - a.def = new Number(75); - b.def = new Number(63); - ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal"); - - // More circular objects #767. - a = {everything: "is checked", but: "this", is: "not"}; - a.but = a; - b = {everything: "is checked", but: {that:"object"}, is: "not"}; - ok(!_.isEqual(a, b), "Comparison of circular references with non-circular object references are not equal"); - - // Cyclic Structures. - a = [{abc: null}]; - b = [{abc: null}]; - (a[0].abc = a).push(a); - (b[0].abc = b).push(b); - ok(_.isEqual(a, b), "Cyclic structures are equal"); - a[0].def = "Larry"; - b[0].def = "Larry"; - ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal"); - a[0].def = new String("Larry"); - b[0].def = new String("Curly"); - ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal"); - - // Complex Circular References. - a = {foo: {b: {foo: {c: {foo: null}}}}}; - b = {foo: {b: {foo: {c: {foo: null}}}}}; - a.foo.b.foo.c.foo = a; - b.foo.b.foo.c.foo = b; - ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal"); - - // Chaining. - ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); - - a = _({x: 1, y: 2}).chain(); - b = _({x: 1, y: 2}).chain(); - equal(_.isEqual(a.isEqual(b), _(true)), true, ' can be chained'); - - // TEST: ??? - return; - - // Objects from another frame. - ok(_.isEqual({}, iObject)); - }); - `) - }) -} - -// isEmpty -func Test_underscore_objects_11(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isEmpty", function() { - ok(!_([1]).isEmpty(), '[1] is not empty'); - ok(_.isEmpty([]), '[] is empty'); - ok(!_.isEmpty({one : 1}), '{one : 1} is not empty'); - ok(_.isEmpty({}), '{} is empty'); - ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty'); - ok(_.isEmpty(null), 'null is empty'); - ok(_.isEmpty(), 'undefined is empty'); - ok(_.isEmpty(''), 'the empty string is empty'); - ok(!_.isEmpty('moe'), 'but other strings are not'); - - var obj = {one : 1}; - delete obj.one; - ok(_.isEmpty(obj), 'deleting all the keys from an object empties it'); - }); - `) - }) -} - -// isElement -func Test_underscore_objects_12(t *testing.T) { - // TEST: ReferenceError: $ is not defined - if true { - return - } - - tt(t, func() { - test, _ := test_() - - test(` - test("isElement", function() { - ok(!_.isElement('div'), 'strings are not dom elements'); - ok(_.isElement($('html')[0]), 'the html tag is a DOM element'); - ok(_.isElement(iElement), 'even from another frame'); - }); - `) - }) -} - -// isArguments -func Test_underscore_objects_13(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isArguments", function() { - var args = (function(){ return arguments; })(1, 2, 3); - ok(!_.isArguments('string'), 'a string is not an arguments object'); - ok(!_.isArguments(_.isArguments), 'a function is not an arguments object'); - ok(_.isArguments(args), 'but the arguments object is an arguments object'); - ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array'); - ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.'); - - // TEST: ReferenceError: iArguments is not defined - return; - ok(_.isArguments(iArguments), 'even from another frame'); - }); - `) - }) -} - -// isObject -func Test_underscore_objects_14(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isObject", function() { - ok(_.isObject(arguments), 'the arguments object is object'); - ok(_.isObject([1, 2, 3]), 'and arrays'); - // TEST: ReferenceError: $ is not defined - return; - ok(_.isObject($('html')[0]), 'and DOM element'); - ok(_.isObject(iElement), 'even from another frame'); - ok(_.isObject(function () {}), 'and functions'); - ok(_.isObject(iFunction), 'even from another frame'); - ok(!_.isObject(null), 'but not null'); - ok(!_.isObject(undefined), 'and not undefined'); - ok(!_.isObject('string'), 'and not string'); - ok(!_.isObject(12), 'and not number'); - ok(!_.isObject(true), 'and not boolean'); - ok(_.isObject(new String('string')), 'but new String()'); - }); - `) - }) -} - -// isArray -func Test_underscore_objects_15(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isArray", function() { - ok(!_.isArray(arguments), 'the arguments object is not an array'); - ok(_.isArray([1, 2, 3]), 'but arrays are'); - // TEST: ??? - return; - ok(_.isArray(iArray), 'even from another frame'); - }); - `) - }) -} - -// isString -func Test_underscore_objects_16(t *testing.T) { - // TEST: ReferenceError: document is not defined - if true { - return - } - - tt(t, func() { - test, _ := test_() - - test(` - test("isString", function() { - ok(!_.isString(document.body), 'the document body is not a string'); - ok(_.isString([1, 2, 3].join(', ')), 'but strings are'); - // TEST: ??? - return; - ok(_.isString(iString), 'even from another frame'); - }); - `) - }) -} - -// isNumber -func Test_underscore_objects_17(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isNumber", function() { - ok(!_.isNumber('string'), 'a string is not a number'); - ok(!_.isNumber(arguments), 'the arguments object is not a number'); - ok(!_.isNumber(undefined), 'undefined is not a number'); - ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are'); - ok(_.isNumber(NaN), 'NaN *is* a number'); - ok(_.isNumber(Infinity), 'Infinity is a number'); - // TEST: ??? - return; - ok(_.isNumber(iNumber), 'even from another frame'); - ok(!_.isNumber('1'), 'numeric strings are not numbers'); - }); - `) - }) -} - -// isBoolean -func Test_underscore_objects_18(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isBoolean", function() { - ok(!_.isBoolean(2), 'a number is not a boolean'); - ok(!_.isBoolean("string"), 'a string is not a boolean'); - ok(!_.isBoolean("false"), 'the string "false" is not a boolean'); - ok(!_.isBoolean("true"), 'the string "true" is not a boolean'); - ok(!_.isBoolean(arguments), 'the arguments object is not a boolean'); - ok(!_.isBoolean(undefined), 'undefined is not a boolean'); - ok(!_.isBoolean(NaN), 'NaN is not a boolean'); - ok(!_.isBoolean(null), 'null is not a boolean'); - ok(_.isBoolean(true), 'but true is'); - ok(_.isBoolean(false), 'and so is false'); - // TEST: ??? - return; - ok(_.isBoolean(iBoolean), 'even from another frame'); - }); - `) - }) -} - -// isFunction -func Test_underscore_objects_19(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isFunction", function() { - ok(!_.isFunction([1, 2, 3]), 'arrays are not functions'); - ok(!_.isFunction('moe'), 'strings are not functions'); - ok(_.isFunction(_.isFunction), 'but functions are'); - // TEST: ??? - return; - ok(_.isFunction(iFunction), 'even from another frame'); - }); - `) - }) -} - -// isDate -func Test_underscore_objects_20(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isDate", function() { - ok(!_.isDate(100), 'numbers are not dates'); - ok(!_.isDate({}), 'objects are not dates'); - ok(_.isDate(new Date()), 'but dates are'); - // TEST: ??? - return; - ok(_.isDate(iDate), 'even from another frame'); - }); - `) - }) -} - -// isRegExp -func Test_underscore_objects_21(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isRegExp", function() { - ok(!_.isRegExp(_.identity), 'functions are not RegExps'); - ok(_.isRegExp(/identity/), 'but RegExps are'); - // TEST: ??? - return; - ok(_.isRegExp(iRegExp), 'even from another frame'); - }); - `) - }) -} - -// isFinite -func Test_underscore_objects_22(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isFinite", function() { - ok(!_.isFinite(undefined), 'undefined is not Finite'); - ok(!_.isFinite(null), 'null is not Finite'); - ok(!_.isFinite(NaN), 'NaN is not Finite'); - ok(!_.isFinite(Infinity), 'Infinity is not Finite'); - ok(!_.isFinite(-Infinity), '-Infinity is not Finite'); - ok(_.isFinite('12'), 'Numeric strings are numbers'); - ok(!_.isFinite('1a'), 'Non numeric strings are not numbers'); - ok(!_.isFinite(''), 'Empty strings are not numbers'); - var obj = new Number(5); - ok(_.isFinite(obj), 'Number instances can be finite'); - ok(_.isFinite(0), '0 is Finite'); - ok(_.isFinite(123), 'Ints are Finite'); - ok(_.isFinite(-12.44), 'Floats are Finite'); - }); - `) - }) -} - -// isNaN -func Test_underscore_objects_23(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isNaN", function() { - ok(!_.isNaN(undefined), 'undefined is not NaN'); - ok(!_.isNaN(null), 'null is not NaN'); - ok(!_.isNaN(0), '0 is not NaN'); - ok(_.isNaN(NaN), 'but NaN is'); - // TEST: ??? - return; - ok(_.isNaN(iNaN), 'even from another frame'); - ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN'); - }); - `) - }) -} - -// isNull -func Test_underscore_objects_24(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isNull", function() { - ok(!_.isNull(undefined), 'undefined is not null'); - ok(!_.isNull(NaN), 'NaN is not null'); - ok(_.isNull(null), 'but null is'); - // TEST: ??? - return; - ok(_.isNull(iNull), 'even from another frame'); - }); - `) - }) -} - -// isUndefined -func Test_underscore_objects_25(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("isUndefined", function() { - ok(!_.isUndefined(1), 'numbers are defined'); - ok(!_.isUndefined(null), 'null is defined'); - ok(!_.isUndefined(false), 'false is defined'); - ok(!_.isUndefined(NaN), 'NaN is defined'); - ok(_.isUndefined(), 'nothing is undefined'); - ok(_.isUndefined(undefined), 'undefined is undefined'); - // TEST: ??? - return; - ok(_.isUndefined(iUndefined), 'even from another frame'); - }); - `) - }) -} - -// tap -func Test_underscore_objects_26(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("tap", function() { - var intercepted = null; - var interceptor = function(obj) { intercepted = obj; }; - var returned = _.tap(1, interceptor); - equal(intercepted, 1, "passes tapped object to interceptor"); - equal(returned, 1, "returns tapped object"); - - returned = _([1,2,3]).chain(). - map(function(n){ return n * 2; }). - max(). - tap(interceptor). - value(); - ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); - }); - `) - }) -} - -// has -func Test_underscore_objects_27(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("has", function () { - var obj = {foo: "bar", func: function () {} }; - ok (_.has(obj, "foo"), "has() checks that the object has a property."); - ok (_.has(obj, "baz") == false, "has() returns false if the object doesn't have the property."); - ok (_.has(obj, "func"), "has() works for functions too."); - obj.hasOwnProperty = null; - ok (_.has(obj, "foo"), "has() works even when the hasOwnProperty method is deleted."); - var child = {}; - child.prototype = obj; - ok (_.has(child, "foo") == false, "has() does not check the prototype chain for a property.") - }); - `) - }) -} diff --git a/vendor/github.com/robertkrimen/otto/underscore_test.go b/vendor/github.com/robertkrimen/otto/underscore_test.go deleted file mode 100644 index d8bf2da18d9..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_test.go +++ /dev/null @@ -1,165 +0,0 @@ -package otto - -import ( - "./terst" - "testing" - - "github.com/robertkrimen/otto/underscore" -) - -func init() { - underscore.Disable() -} - -// A persistent handle for the underscore tester -// We do not run underscore tests in parallel, so it is okay to stash globally -// (Maybe use sync.Pool in the future...) -var tester_ *_tester - -// A tester for underscore: test_ => test(underscore) :) -func test_(arguments ...interface{}) (func(string, ...interface{}) Value, *_tester) { - tester := tester_ - if tester == nil { - tester = newTester() - tester.underscore() // Load underscore and testing shim, etc. - tester_ = tester - } - - return tester.test, tester -} - -func (self *_tester) underscore() { - vm := self.vm - _, err := vm.Run(underscore.Source()) - if err != nil { - panic(err) - } - - vm.Set("assert", func(call FunctionCall) Value { - if !call.Argument(0).bool() { - message := "Assertion failed" - if len(call.ArgumentList) > 1 { - message = call.ArgumentList[1].string() - } - t := terst.Caller().T() - is(message, nil) - t.Fail() - return falseValue - } - return trueValue - }) - - vm.Run(` - var templateSettings; - - function _setup() { - templateSettings = _.clone(_.templateSettings); - } - - function _teardown() { - _.templateSettings = templateSettings; - } - - function module() { - /* Nothing happens. */ - } - - function equals(a, b, emit) { - assert(a == b, emit + ", <" + a + "> != <" + b + ">"); - } - var equal = equals; - - function notStrictEqual(a, b, emit) { - assert(a !== b, emit); - } - - function strictEqual(a, b, emit) { - assert(a === b, emit); - } - - function ok(a, emit) { - assert(a, emit); - } - - function raises(fn, want, emit) { - var have, _ok = false; - if (typeof want === "string") { - emit = want; - want = null; - } - - try { - fn(); - } catch(tmp) { - have = tmp; - } - - if (have) { - if (!want) { - _ok = true; - } - else if (want instanceof RegExp) { - _ok = want.test(have); - } - else if (have instanceof want) { - _ok = true - } - else if (want.call({}, have) === true) { - _ok = true; - } - } - - ok(_ok, emit); - } - - function test(name){ - _setup() - try { - templateSettings = _.clone(_.templateSettings); - if (arguments.length == 3) { - count = 0 - for (count = 0; count < arguments[1]; count++) { - arguments[2]() - } - } else { - // For now. - arguments[1]() - } - } - finally { - _teardown() - } - } - - function deepEqual(a, b, emit) { - // Also, for now. - assert(_.isEqual(a, b), emit) - } - `) -} - -func Test_underscore(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - _.map([1, 2, 3], function(value){ - return value + 1 - }) - `, "2,3,4") - - test(` - abc = _.find([1, 2, 3, -1], function(value) { return value == -1 }) - `, -1) - - test(`_.isEqual(1, 1)`, true) - test(`_.isEqual([], [])`, true) - test(`_.isEqual(['b', 'd'], ['b', 'd'])`, true) - test(`_.isEqual(['b', 'd', 'c'], ['b', 'd', 'e'])`, false) - test(`_.isFunction(function(){})`, true) - test(`_.template('

\u2028<%= "\\u2028\\u2029" %>\u2029

')()`, "

\u2028\u2028\u2029\u2029

") - }) -} - -// TODO Test: typeof An argument reference -// TODO Test: abc = {}; abc == Object(abc) diff --git a/vendor/github.com/robertkrimen/otto/underscore_utility_test.go b/vendor/github.com/robertkrimen/otto/underscore_utility_test.go deleted file mode 100644 index ebabb083be9..00000000000 --- a/vendor/github.com/robertkrimen/otto/underscore_utility_test.go +++ /dev/null @@ -1,419 +0,0 @@ -package otto - -import ( - "testing" -) - -// #750 - Return _ instance. -func Test_underscore_utility_0(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("#750 - Return _ instance.", 2, function() { - var instance = _([]); - ok(_(instance) === instance); - ok(new _(instance) === instance); - }); - `) - }) -} - -// identity -func Test_underscore_utility_1(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("identity", function() { - var moe = {name : 'moe'}; - equal(_.identity(moe), moe, 'moe is the same as his identity'); - }); - `) - }) -} - -// random -func Test_underscore_utility_2(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("random", function() { - var array = _.range(1000); - var min = Math.pow(2, 31); - var max = Math.pow(2, 62); - - ok(_.every(array, function() { - return _.random(min, max) >= min; - }), "should produce a random number greater than or equal to the minimum number"); - - ok(_.some(array, function() { - return _.random(Number.MAX_VALUE) > 0; - }), "should produce a random number when passed "); - }); - `) - }) -} - -// uniqueId -func Test_underscore_utility_3(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("uniqueId", function() { - var ids = [], i = 0; - while(i++ < 100) ids.push(_.uniqueId()); - equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); - }); - `) - }) -} - -// times -func Test_underscore_utility_4(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("times", function() { - var vals = []; - _.times(3, function (i) { vals.push(i); }); - ok(_.isEqual(vals, [0,1,2]), "is 0 indexed"); - // - vals = []; - _(3).times(function(i) { vals.push(i); }); - ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); - // collects return values - ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values"); - }); - `) - }) -} - -// mixin -func Test_underscore_utility_5(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("mixin", function() { - _.mixin({ - myReverse: function(string) { - return string.split('').reverse().join(''); - } - }); - equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); - equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); - }); - `) - }) -} - -// _.escape -func Test_underscore_utility_6(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("_.escape", function() { - equal(_.escape("Curly & Moe"), "Curly & Moe"); - equal(_.escape("Curly & Moe"), "Curly &amp; Moe"); - equal(_.escape(null), ''); - }); - `) - }) -} - -// _.unescape -func Test_underscore_utility_7(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("_.unescape", function() { - var string = "Curly & Moe"; - equal(_.unescape("Curly & Moe"), string); - equal(_.unescape("Curly &amp; Moe"), "Curly & Moe"); - equal(_.unescape(null), ''); - equal(_.unescape(_.escape(string)), string); - }); - `) - }) -} - -// template -func Test_underscore_utility_8(t *testing.T) { - tt(t, func() { - test, _ := test_() - - test(` - test("template", function() { - var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); - var result = basicTemplate({thing : 'This'}); - equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); - - var sansSemicolonTemplate = _.template("A <% this %> B"); - equal(sansSemicolonTemplate(), "A B"); - - var backslashTemplate = _.template("<%= thing %> is \\ridanculous"); - equal(backslashTemplate({thing: 'This'}), "This is \\ridanculous"); - - var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); - equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); - - var fancyTemplate = _.template("
    <% \ - for (var key in people) { \ - %>
  • <%= people[key] %>
  • <% } %>
"); - result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); - equal(result, "
  • Moe
  • Larry
  • Curly
", 'can run arbitrary javascript in templates'); - - var escapedCharsInJavascriptTemplate = _.template("
    <% _.each(numbers.split('\\n'), function(item) { %>
  • <%= item %>
  • <% }) %>
"); - result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"}); - equal(result, "
  • one
  • two
  • three
  • four
", 'Can use escaped characters (e.g. \\n) in Javascript'); - - var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
\">
<% }); %>"); - result = namespaceCollisionTemplate({ - pageCount: 3, - thumbnails: { - 1: "p1-thumbnail.gif", - 2: "p2-thumbnail.gif", - 3: "p3-thumbnail.gif" - } - }); - equal(result, "3 p3-thumbnail.gif
"); - - var noInterpolateTemplate = _.template("

Just some text. Hey, I know this is silly but it aids consistency.

"); - result = noInterpolateTemplate(); - equal(result, "

Just some text. Hey, I know this is silly but it aids consistency.

"); - - var quoteTemplate = _.template("It's its, not it's"); - equal(quoteTemplate({}), "It's its, not it's"); - - var quoteInStatementAndBody = _.template("<%\ - if(foo == 'bar'){ \ - %>Statement quotes and 'quotes'.<% } %>"); - equal(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'."); - - var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); - equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); - - var template = _.template("<%- value %>"); - var result = template({value: " - - - diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/template.txt b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/template.txt deleted file mode 100644 index b396900b8af..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/template.txt +++ /dev/null @@ -1,286 +0,0 @@ -/* - {4} ({1} and []{1}) - -------------------------------------------------- -*/ - -// {4} gets the value as a {1}, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) {4}(optionalDefault ...{1}) {1} { - if s, ok := v.data.({1}); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return {3} -} - -// Must{4} gets the value as a {1}. -// -// Panics if the object is not a {1}. -func (v *Value) Must{4}() {1} { - return v.data.({1}) -} - -// {4}Slice gets the value as a []{1}, returns the optionalDefault -// value or nil if the value is not a []{1}. -func (v *Value) {4}Slice(optionalDefault ...[]{1}) []{1} { - if s, ok := v.data.([]{1}); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// Must{4}Slice gets the value as a []{1}. -// -// Panics if the object is not a []{1}. -func (v *Value) Must{4}Slice() []{1} { - return v.data.([]{1}) -} - -// Is{4} gets whether the object contained is a {1} or not. -func (v *Value) Is{4}() bool { - _, ok := v.data.({1}) - return ok -} - -// Is{4}Slice gets whether the object contained is a []{1} or not. -func (v *Value) Is{4}Slice() bool { - _, ok := v.data.([]{1}) - return ok -} - -// Each{4} calls the specified callback for each object -// in the []{1}. -// -// Panics if the object is the wrong type. -func (v *Value) Each{4}(callback func(int, {1}) bool) *Value { - - for index, val := range v.Must{4}Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// Where{4} uses the specified decider function to select items -// from the []{1}. The object contained in the result will contain -// only the selected items. -func (v *Value) Where{4}(decider func(int, {1}) bool) *Value { - - var selected []{1} - - v.Each{4}(func(index int, val {1}) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data:selected} - -} - -// Group{4} uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]{1}. -func (v *Value) Group{4}(grouper func(int, {1}) string) *Value { - - groups := make(map[string][]{1}) - - v.Each{4}(func(index int, val {1}) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]{1}, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data:groups} - -} - -// Replace{4} uses the specified function to replace each {1}s -// by iterating each item. The data in the returned result will be a -// []{1} containing the replaced items. -func (v *Value) Replace{4}(replacer func(int, {1}) {1}) *Value { - - arr := v.Must{4}Slice() - replaced := make([]{1}, len(arr)) - - v.Each{4}(func(index int, val {1}) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data:replaced} - -} - -// Collect{4} uses the specified collector function to collect a value -// for each of the {1}s in the slice. The data returned will be a -// []interface{}. -func (v *Value) Collect{4}(collector func(int, {1}) interface{}) *Value { - - arr := v.Must{4}Slice() - collected := make([]interface{}, len(arr)) - - v.Each{4}(func(index int, val {1}) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data:collected} -} - -// ************************************************************ -// TESTS -// ************************************************************ - -func Test{4}(t *testing.T) { - - val := {1}( {2} ) - m := map[string]interface{}{"value": val, "nothing": nil} - assert.Equal(t, val, New(m).Get("value").{4}()) - assert.Equal(t, val, New(m).Get("value").Must{4}()) - assert.Equal(t, {1}({3}), New(m).Get("nothing").{4}()) - assert.Equal(t, val, New(m).Get("nothing").{4}({2})) - - assert.Panics(t, func() { - New(m).Get("age").Must{4}() - }) - -} - -func Test{4}Slice(t *testing.T) { - - val := {1}( {2} ) - m := map[string]interface{}{"value": []{1}{ val }, "nothing": nil} - assert.Equal(t, val, New(m).Get("value").{4}Slice()[0]) - assert.Equal(t, val, New(m).Get("value").Must{4}Slice()[0]) - assert.Equal(t, []{1}(nil), New(m).Get("nothing").{4}Slice()) - assert.Equal(t, val, New(m).Get("nothing").{4}Slice( []{1}{ {1}({2}) } )[0]) - - assert.Panics(t, func() { - New(m).Get("nothing").Must{4}Slice() - }) - -} - -func TestIs{4}(t *testing.T) { - - var v *Value - - v = &Value{data: {1}({2})} - assert.True(t, v.Is{4}()) - - v = &Value{data: []{1}{ {1}({2}) }} - assert.True(t, v.Is{4}Slice()) - -} - -func TestEach{4}(t *testing.T) { - - v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} - count := 0 - replacedVals := make([]{1}, 0) - assert.Equal(t, v, v.Each{4}(func(i int, val {1}) bool { - - count++ - replacedVals = append(replacedVals, val) - - // abort early - if i == 2 { - return false - } - - return true - - })) - - assert.Equal(t, count, 3) - assert.Equal(t, replacedVals[0], v.Must{4}Slice()[0]) - assert.Equal(t, replacedVals[1], v.Must{4}Slice()[1]) - assert.Equal(t, replacedVals[2], v.Must{4}Slice()[2]) - -} - -func TestWhere{4}(t *testing.T) { - - v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} - - selected := v.Where{4}(func(i int, val {1}) bool { - return i%2==0 - }).Must{4}Slice() - - assert.Equal(t, 3, len(selected)) - -} - -func TestGroup{4}(t *testing.T) { - - v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} - - grouped := v.Group{4}(func(i int, val {1}) string { - return fmt.Sprintf("%v", i%2==0) - }).data.(map[string][]{1}) - - assert.Equal(t, 2, len(grouped)) - assert.Equal(t, 3, len(grouped["true"])) - assert.Equal(t, 3, len(grouped["false"])) - -} - -func TestReplace{4}(t *testing.T) { - - v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} - - rawArr := v.Must{4}Slice() - - replaced := v.Replace{4}(func(index int, val {1}) {1} { - if index < len(rawArr)-1 { - return rawArr[index+1] - } - return rawArr[0] - }) - - replacedArr := replaced.Must{4}Slice() - if assert.Equal(t, 6, len(replacedArr)) { - assert.Equal(t, replacedArr[0], rawArr[1]) - assert.Equal(t, replacedArr[1], rawArr[2]) - assert.Equal(t, replacedArr[2], rawArr[3]) - assert.Equal(t, replacedArr[3], rawArr[4]) - assert.Equal(t, replacedArr[4], rawArr[5]) - assert.Equal(t, replacedArr[5], rawArr[0]) - } - -} - -func TestCollect{4}(t *testing.T) { - - v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} - - collected := v.Collect{4}(func(index int, val {1}) interface{} { - return index - }) - - collectedArr := collected.MustInterSlice() - if assert.Equal(t, 6, len(collectedArr)) { - assert.Equal(t, collectedArr[0], 0) - assert.Equal(t, collectedArr[1], 1) - assert.Equal(t, collectedArr[2], 2) - assert.Equal(t, collectedArr[3], 3) - assert.Equal(t, collectedArr[4], 4) - assert.Equal(t, collectedArr[5], 5) - } - -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/types_list.txt b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/types_list.txt deleted file mode 100644 index 069d43d8ecf..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/codegen/types_list.txt +++ /dev/null @@ -1,20 +0,0 @@ -Interface,interface{},"something",nil,Inter -Map,map[string]interface{},map[string]interface{}{"name":"Tyler"},nil,MSI -ObjxMap,(Map),New(1),New(nil),ObjxMap -Bool,bool,true,false,Bool -String,string,"hello","",Str -Int,int,1,0,Int -Int8,int8,1,0,Int8 -Int16,int16,1,0,Int16 -Int32,int32,1,0,Int32 -Int64,int64,1,0,Int64 -Uint,uint,1,0,Uint -Uint8,uint8,1,0,Uint8 -Uint16,uint16,1,0,Uint16 -Uint32,uint32,1,0,Uint32 -Uint64,uint64,1,0,Uint64 -Uintptr,uintptr,1,0,Uintptr -Float32,float32,1,0,Float32 -Float64,float64,1,0,Float64 -Complex64,complex64,1,0,Complex64 -Complex128,complex128,1,0,Complex128 diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/constants.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/constants.go deleted file mode 100644 index f9eb42a25e0..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/constants.go +++ /dev/null @@ -1,13 +0,0 @@ -package objx - -const ( - // PathSeparator is the character used to separate the elements - // of the keypath. - // - // For example, `location.address.city` - PathSeparator string = "." - - // SignatureSeparator is the character that is used to - // separate the Base64 string from the security signature. - SignatureSeparator = "_" -) diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/conversions.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/conversions.go deleted file mode 100644 index 9cdfa9f9f61..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/conversions.go +++ /dev/null @@ -1,117 +0,0 @@ -package objx - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "net/url" -) - -// JSON converts the contained object to a JSON string -// representation -func (m Map) JSON() (string, error) { - - result, err := json.Marshal(m) - - if err != nil { - err = errors.New("objx: JSON encode failed with: " + err.Error()) - } - - return string(result), err - -} - -// MustJSON converts the contained object to a JSON string -// representation and panics if there is an error -func (m Map) MustJSON() string { - result, err := m.JSON() - if err != nil { - panic(err.Error()) - } - return result -} - -// Base64 converts the contained object to a Base64 string -// representation of the JSON string representation -func (m Map) Base64() (string, error) { - - var buf bytes.Buffer - - jsonData, err := m.JSON() - if err != nil { - return "", err - } - - encoder := base64.NewEncoder(base64.StdEncoding, &buf) - encoder.Write([]byte(jsonData)) - encoder.Close() - - return buf.String(), nil - -} - -// MustBase64 converts the contained object to a Base64 string -// representation of the JSON string representation and panics -// if there is an error -func (m Map) MustBase64() string { - result, err := m.Base64() - if err != nil { - panic(err.Error()) - } - return result -} - -// SignedBase64 converts the contained object to a Base64 string -// representation of the JSON string representation and signs it -// using the provided key. -func (m Map) SignedBase64(key string) (string, error) { - - base64, err := m.Base64() - if err != nil { - return "", err - } - - sig := HashWithKey(base64, key) - - return base64 + SignatureSeparator + sig, nil - -} - -// MustSignedBase64 converts the contained object to a Base64 string -// representation of the JSON string representation and signs it -// using the provided key and panics if there is an error -func (m Map) MustSignedBase64(key string) string { - result, err := m.SignedBase64(key) - if err != nil { - panic(err.Error()) - } - return result -} - -/* - URL Query - ------------------------------------------------ -*/ - -// URLValues creates a url.Values object from an Obj. This -// function requires that the wrapped object be a map[string]interface{} -func (m Map) URLValues() url.Values { - - vals := make(url.Values) - - for k, v := range m { - //TODO: can this be done without sprintf? - vals.Set(k, fmt.Sprintf("%v", v)) - } - - return vals -} - -// URLQuery gets an encoded URL query representing the given -// Obj. This function requires that the wrapped object be a -// map[string]interface{} -func (m Map) URLQuery() (string, error) { - return m.URLValues().Encode(), nil -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/doc.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/doc.go deleted file mode 100644 index 47bf85e4634..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/doc.go +++ /dev/null @@ -1,72 +0,0 @@ -// objx - Go package for dealing with maps, slices, JSON and other data. -// -// Overview -// -// Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes -// a powerful `Get` method (among others) that allows you to easily and quickly get -// access to data within the map, without having to worry too much about type assertions, -// missing data, default values etc. -// -// Pattern -// -// Objx uses a preditable pattern to make access data from within `map[string]interface{}'s -// easy. -// -// Call one of the `objx.` functions to create your `objx.Map` to get going: -// -// m, err := objx.FromJSON(json) -// -// NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, -// the rest will be optimistic and try to figure things out without panicking. -// -// Use `Get` to access the value you're interested in. You can use dot and array -// notation too: -// -// m.Get("places[0].latlng") -// -// Once you have saught the `Value` you're interested in, you can use the `Is*` methods -// to determine its type. -// -// if m.Get("code").IsStr() { /* ... */ } -// -// Or you can just assume the type, and use one of the strong type methods to -// extract the real value: -// -// m.Get("code").Int() -// -// If there's no value there (or if it's the wrong type) then a default value -// will be returned, or you can be explicit about the default value. -// -// Get("code").Int(-1) -// -// If you're dealing with a slice of data as a value, Objx provides many useful -// methods for iterating, manipulating and selecting that data. You can find out more -// by exploring the index below. -// -// Reading data -// -// A simple example of how to use Objx: -// -// // use MustFromJSON to make an objx.Map from some JSON -// m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) -// -// // get the details -// name := m.Get("name").Str() -// age := m.Get("age").Int() -// -// // get their nickname (or use their name if they -// // don't have one) -// nickname := m.Get("nickname").Str(name) -// -// Ranging -// -// Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For -// example, to `range` the data, do what you would expect: -// -// m := objx.MustFromJSON(json) -// for key, value := range m { -// -// /* ... do your magic ... */ -// -// } -package objx diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/map.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/map.go deleted file mode 100644 index eb6ed8e285c..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/map.go +++ /dev/null @@ -1,222 +0,0 @@ -package objx - -import ( - "encoding/base64" - "encoding/json" - "errors" - "io/ioutil" - "net/url" - "strings" -) - -// MSIConvertable is an interface that defines methods for converting your -// custom types to a map[string]interface{} representation. -type MSIConvertable interface { - // MSI gets a map[string]interface{} (msi) representing the - // object. - MSI() map[string]interface{} -} - -// Map provides extended functionality for working with -// untyped data, in particular map[string]interface (msi). -type Map map[string]interface{} - -// Value returns the internal value instance -func (m Map) Value() *Value { - return &Value{data: m} -} - -// Nil represents a nil Map. -var Nil Map = New(nil) - -// New creates a new Map containing the map[string]interface{} in the data argument. -// If the data argument is not a map[string]interface, New attempts to call the -// MSI() method on the MSIConvertable interface to create one. -func New(data interface{}) Map { - if _, ok := data.(map[string]interface{}); !ok { - if converter, ok := data.(MSIConvertable); ok { - data = converter.MSI() - } else { - return nil - } - } - return Map(data.(map[string]interface{})) -} - -// MSI creates a map[string]interface{} and puts it inside a new Map. -// -// The arguments follow a key, value pattern. -// -// Panics -// -// Panics if any key arugment is non-string or if there are an odd number of arguments. -// -// Example -// -// To easily create Maps: -// -// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) -// -// // creates an Map equivalent to -// m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}}) -func MSI(keyAndValuePairs ...interface{}) Map { - - newMap := make(map[string]interface{}) - keyAndValuePairsLen := len(keyAndValuePairs) - - if keyAndValuePairsLen%2 != 0 { - panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.") - } - - for i := 0; i < keyAndValuePairsLen; i = i + 2 { - - key := keyAndValuePairs[i] - value := keyAndValuePairs[i+1] - - // make sure the key is a string - keyString, keyStringOK := key.(string) - if !keyStringOK { - panic("objx: MSI must follow 'string, interface{}' pattern. " + keyString + " is not a valid key.") - } - - newMap[keyString] = value - - } - - return New(newMap) -} - -// ****** Conversion Constructors - -// MustFromJSON creates a new Map containing the data specified in the -// jsonString. -// -// Panics if the JSON is invalid. -func MustFromJSON(jsonString string) Map { - o, err := FromJSON(jsonString) - - if err != nil { - panic("objx: MustFromJSON failed with error: " + err.Error()) - } - - return o -} - -// FromJSON creates a new Map containing the data specified in the -// jsonString. -// -// Returns an error if the JSON is invalid. -func FromJSON(jsonString string) (Map, error) { - - var data interface{} - err := json.Unmarshal([]byte(jsonString), &data) - - if err != nil { - return Nil, err - } - - return New(data), nil - -} - -// FromBase64 creates a new Obj containing the data specified -// in the Base64 string. -// -// The string is an encoded JSON string returned by Base64 -func FromBase64(base64String string) (Map, error) { - - decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String)) - - decoded, err := ioutil.ReadAll(decoder) - if err != nil { - return nil, err - } - - return FromJSON(string(decoded)) -} - -// MustFromBase64 creates a new Obj containing the data specified -// in the Base64 string and panics if there is an error. -// -// The string is an encoded JSON string returned by Base64 -func MustFromBase64(base64String string) Map { - - result, err := FromBase64(base64String) - - if err != nil { - panic("objx: MustFromBase64 failed with error: " + err.Error()) - } - - return result -} - -// FromSignedBase64 creates a new Obj containing the data specified -// in the Base64 string. -// -// The string is an encoded JSON string returned by SignedBase64 -func FromSignedBase64(base64String, key string) (Map, error) { - parts := strings.Split(base64String, SignatureSeparator) - if len(parts) != 2 { - return nil, errors.New("objx: Signed base64 string is malformed.") - } - - sig := HashWithKey(parts[0], key) - if parts[1] != sig { - return nil, errors.New("objx: Signature for base64 data does not match.") - } - - return FromBase64(parts[0]) -} - -// MustFromSignedBase64 creates a new Obj containing the data specified -// in the Base64 string and panics if there is an error. -// -// The string is an encoded JSON string returned by Base64 -func MustFromSignedBase64(base64String, key string) Map { - - result, err := FromSignedBase64(base64String, key) - - if err != nil { - panic("objx: MustFromSignedBase64 failed with error: " + err.Error()) - } - - return result -} - -// FromURLQuery generates a new Obj by parsing the specified -// query. -// -// For queries with multiple values, the first value is selected. -func FromURLQuery(query string) (Map, error) { - - vals, err := url.ParseQuery(query) - - if err != nil { - return nil, err - } - - m := make(map[string]interface{}) - for k, vals := range vals { - m[k] = vals[0] - } - - return New(m), nil -} - -// MustFromURLQuery generates a new Obj by parsing the specified -// query. -// -// For queries with multiple values, the first value is selected. -// -// Panics if it encounters an error -func MustFromURLQuery(query string) Map { - - o, err := FromURLQuery(query) - - if err != nil { - panic("objx: MustFromURLQuery failed with error: " + err.Error()) - } - - return o - -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/mutations.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/mutations.go deleted file mode 100644 index b35c86392bf..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/mutations.go +++ /dev/null @@ -1,81 +0,0 @@ -package objx - -// Exclude returns a new Map with the keys in the specified []string -// excluded. -func (d Map) Exclude(exclude []string) Map { - - excluded := make(Map) - for k, v := range d { - var shouldInclude bool = true - for _, toExclude := range exclude { - if k == toExclude { - shouldInclude = false - break - } - } - if shouldInclude { - excluded[k] = v - } - } - - return excluded -} - -// Copy creates a shallow copy of the Obj. -func (m Map) Copy() Map { - copied := make(map[string]interface{}) - for k, v := range m { - copied[k] = v - } - return New(copied) -} - -// Merge blends the specified map with a copy of this map and returns the result. -// -// Keys that appear in both will be selected from the specified map. -// This method requires that the wrapped object be a map[string]interface{} -func (m Map) Merge(merge Map) Map { - return m.Copy().MergeHere(merge) -} - -// Merge blends the specified map with this map and returns the current map. -// -// Keys that appear in both will be selected from the specified map. The original map -// will be modified. This method requires that -// the wrapped object be a map[string]interface{} -func (m Map) MergeHere(merge Map) Map { - - for k, v := range merge { - m[k] = v - } - - return m - -} - -// Transform builds a new Obj giving the transformer a chance -// to change the keys and values as it goes. This method requires that -// the wrapped object be a map[string]interface{} -func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map { - newMap := make(map[string]interface{}) - for k, v := range m { - modifiedKey, modifiedVal := transformer(k, v) - newMap[modifiedKey] = modifiedVal - } - return New(newMap) -} - -// TransformKeys builds a new map using the specified key mapping. -// -// Unspecified keys will be unaltered. -// This method requires that the wrapped object be a map[string]interface{} -func (m Map) TransformKeys(mapping map[string]string) Map { - return m.Transform(func(key string, value interface{}) (string, interface{}) { - - if newKey, ok := mapping[key]; ok { - return newKey, value - } - - return key, value - }) -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/security.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/security.go deleted file mode 100644 index fdd6be9cfb3..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/security.go +++ /dev/null @@ -1,14 +0,0 @@ -package objx - -import ( - "crypto/sha1" - "encoding/hex" -) - -// HashWithKey hashes the specified string using the security -// key. -func HashWithKey(data, key string) string { - hash := sha1.New() - hash.Write([]byte(data + ":" + key)) - return hex.EncodeToString(hash.Sum(nil)) -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/tests.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/tests.go deleted file mode 100644 index d9e0b479a4c..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/tests.go +++ /dev/null @@ -1,17 +0,0 @@ -package objx - -// Has gets whether there is something at the specified selector -// or not. -// -// If m is nil, Has will always return false. -func (m Map) Has(selector string) bool { - if m == nil { - return false - } - return !m.Get(selector).IsNil() -} - -// IsNil gets whether the data is nil or not. -func (v *Value) IsNil() bool { - return v == nil || v.data == nil -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/type_specific_codegen.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/type_specific_codegen.go deleted file mode 100644 index f3ecb29b950..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/type_specific_codegen.go +++ /dev/null @@ -1,2881 +0,0 @@ -package objx - -/* - Inter (interface{} and []interface{}) - -------------------------------------------------- -*/ - -// Inter gets the value as a interface{}, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Inter(optionalDefault ...interface{}) interface{} { - if s, ok := v.data.(interface{}); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustInter gets the value as a interface{}. -// -// Panics if the object is not a interface{}. -func (v *Value) MustInter() interface{} { - return v.data.(interface{}) -} - -// InterSlice gets the value as a []interface{}, returns the optionalDefault -// value or nil if the value is not a []interface{}. -func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} { - if s, ok := v.data.([]interface{}); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustInterSlice gets the value as a []interface{}. -// -// Panics if the object is not a []interface{}. -func (v *Value) MustInterSlice() []interface{} { - return v.data.([]interface{}) -} - -// IsInter gets whether the object contained is a interface{} or not. -func (v *Value) IsInter() bool { - _, ok := v.data.(interface{}) - return ok -} - -// IsInterSlice gets whether the object contained is a []interface{} or not. -func (v *Value) IsInterSlice() bool { - _, ok := v.data.([]interface{}) - return ok -} - -// EachInter calls the specified callback for each object -// in the []interface{}. -// -// Panics if the object is the wrong type. -func (v *Value) EachInter(callback func(int, interface{}) bool) *Value { - - for index, val := range v.MustInterSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereInter uses the specified decider function to select items -// from the []interface{}. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value { - - var selected []interface{} - - v.EachInter(func(index int, val interface{}) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupInter uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]interface{}. -func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value { - - groups := make(map[string][]interface{}) - - v.EachInter(func(index int, val interface{}) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]interface{}, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceInter uses the specified function to replace each interface{}s -// by iterating each item. The data in the returned result will be a -// []interface{} containing the replaced items. -func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value { - - arr := v.MustInterSlice() - replaced := make([]interface{}, len(arr)) - - v.EachInter(func(index int, val interface{}) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectInter uses the specified collector function to collect a value -// for each of the interface{}s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value { - - arr := v.MustInterSlice() - collected := make([]interface{}, len(arr)) - - v.EachInter(func(index int, val interface{}) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - MSI (map[string]interface{} and []map[string]interface{}) - -------------------------------------------------- -*/ - -// MSI gets the value as a map[string]interface{}, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} { - if s, ok := v.data.(map[string]interface{}); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustMSI gets the value as a map[string]interface{}. -// -// Panics if the object is not a map[string]interface{}. -func (v *Value) MustMSI() map[string]interface{} { - return v.data.(map[string]interface{}) -} - -// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault -// value or nil if the value is not a []map[string]interface{}. -func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} { - if s, ok := v.data.([]map[string]interface{}); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustMSISlice gets the value as a []map[string]interface{}. -// -// Panics if the object is not a []map[string]interface{}. -func (v *Value) MustMSISlice() []map[string]interface{} { - return v.data.([]map[string]interface{}) -} - -// IsMSI gets whether the object contained is a map[string]interface{} or not. -func (v *Value) IsMSI() bool { - _, ok := v.data.(map[string]interface{}) - return ok -} - -// IsMSISlice gets whether the object contained is a []map[string]interface{} or not. -func (v *Value) IsMSISlice() bool { - _, ok := v.data.([]map[string]interface{}) - return ok -} - -// EachMSI calls the specified callback for each object -// in the []map[string]interface{}. -// -// Panics if the object is the wrong type. -func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value { - - for index, val := range v.MustMSISlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereMSI uses the specified decider function to select items -// from the []map[string]interface{}. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value { - - var selected []map[string]interface{} - - v.EachMSI(func(index int, val map[string]interface{}) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupMSI uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]map[string]interface{}. -func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value { - - groups := make(map[string][]map[string]interface{}) - - v.EachMSI(func(index int, val map[string]interface{}) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]map[string]interface{}, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceMSI uses the specified function to replace each map[string]interface{}s -// by iterating each item. The data in the returned result will be a -// []map[string]interface{} containing the replaced items. -func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value { - - arr := v.MustMSISlice() - replaced := make([]map[string]interface{}, len(arr)) - - v.EachMSI(func(index int, val map[string]interface{}) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectMSI uses the specified collector function to collect a value -// for each of the map[string]interface{}s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value { - - arr := v.MustMSISlice() - collected := make([]interface{}, len(arr)) - - v.EachMSI(func(index int, val map[string]interface{}) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - ObjxMap ((Map) and [](Map)) - -------------------------------------------------- -*/ - -// ObjxMap gets the value as a (Map), returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) ObjxMap(optionalDefault ...(Map)) Map { - if s, ok := v.data.((Map)); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return New(nil) -} - -// MustObjxMap gets the value as a (Map). -// -// Panics if the object is not a (Map). -func (v *Value) MustObjxMap() Map { - return v.data.((Map)) -} - -// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault -// value or nil if the value is not a [](Map). -func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) { - if s, ok := v.data.([](Map)); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustObjxMapSlice gets the value as a [](Map). -// -// Panics if the object is not a [](Map). -func (v *Value) MustObjxMapSlice() [](Map) { - return v.data.([](Map)) -} - -// IsObjxMap gets whether the object contained is a (Map) or not. -func (v *Value) IsObjxMap() bool { - _, ok := v.data.((Map)) - return ok -} - -// IsObjxMapSlice gets whether the object contained is a [](Map) or not. -func (v *Value) IsObjxMapSlice() bool { - _, ok := v.data.([](Map)) - return ok -} - -// EachObjxMap calls the specified callback for each object -// in the [](Map). -// -// Panics if the object is the wrong type. -func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value { - - for index, val := range v.MustObjxMapSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereObjxMap uses the specified decider function to select items -// from the [](Map). The object contained in the result will contain -// only the selected items. -func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value { - - var selected [](Map) - - v.EachObjxMap(func(index int, val Map) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupObjxMap uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][](Map). -func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value { - - groups := make(map[string][](Map)) - - v.EachObjxMap(func(index int, val Map) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([](Map), 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceObjxMap uses the specified function to replace each (Map)s -// by iterating each item. The data in the returned result will be a -// [](Map) containing the replaced items. -func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value { - - arr := v.MustObjxMapSlice() - replaced := make([](Map), len(arr)) - - v.EachObjxMap(func(index int, val Map) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectObjxMap uses the specified collector function to collect a value -// for each of the (Map)s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value { - - arr := v.MustObjxMapSlice() - collected := make([]interface{}, len(arr)) - - v.EachObjxMap(func(index int, val Map) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Bool (bool and []bool) - -------------------------------------------------- -*/ - -// Bool gets the value as a bool, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Bool(optionalDefault ...bool) bool { - if s, ok := v.data.(bool); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return false -} - -// MustBool gets the value as a bool. -// -// Panics if the object is not a bool. -func (v *Value) MustBool() bool { - return v.data.(bool) -} - -// BoolSlice gets the value as a []bool, returns the optionalDefault -// value or nil if the value is not a []bool. -func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool { - if s, ok := v.data.([]bool); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustBoolSlice gets the value as a []bool. -// -// Panics if the object is not a []bool. -func (v *Value) MustBoolSlice() []bool { - return v.data.([]bool) -} - -// IsBool gets whether the object contained is a bool or not. -func (v *Value) IsBool() bool { - _, ok := v.data.(bool) - return ok -} - -// IsBoolSlice gets whether the object contained is a []bool or not. -func (v *Value) IsBoolSlice() bool { - _, ok := v.data.([]bool) - return ok -} - -// EachBool calls the specified callback for each object -// in the []bool. -// -// Panics if the object is the wrong type. -func (v *Value) EachBool(callback func(int, bool) bool) *Value { - - for index, val := range v.MustBoolSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereBool uses the specified decider function to select items -// from the []bool. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereBool(decider func(int, bool) bool) *Value { - - var selected []bool - - v.EachBool(func(index int, val bool) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupBool uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]bool. -func (v *Value) GroupBool(grouper func(int, bool) string) *Value { - - groups := make(map[string][]bool) - - v.EachBool(func(index int, val bool) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]bool, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceBool uses the specified function to replace each bools -// by iterating each item. The data in the returned result will be a -// []bool containing the replaced items. -func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value { - - arr := v.MustBoolSlice() - replaced := make([]bool, len(arr)) - - v.EachBool(func(index int, val bool) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectBool uses the specified collector function to collect a value -// for each of the bools in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value { - - arr := v.MustBoolSlice() - collected := make([]interface{}, len(arr)) - - v.EachBool(func(index int, val bool) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Str (string and []string) - -------------------------------------------------- -*/ - -// Str gets the value as a string, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Str(optionalDefault ...string) string { - if s, ok := v.data.(string); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return "" -} - -// MustStr gets the value as a string. -// -// Panics if the object is not a string. -func (v *Value) MustStr() string { - return v.data.(string) -} - -// StrSlice gets the value as a []string, returns the optionalDefault -// value or nil if the value is not a []string. -func (v *Value) StrSlice(optionalDefault ...[]string) []string { - if s, ok := v.data.([]string); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustStrSlice gets the value as a []string. -// -// Panics if the object is not a []string. -func (v *Value) MustStrSlice() []string { - return v.data.([]string) -} - -// IsStr gets whether the object contained is a string or not. -func (v *Value) IsStr() bool { - _, ok := v.data.(string) - return ok -} - -// IsStrSlice gets whether the object contained is a []string or not. -func (v *Value) IsStrSlice() bool { - _, ok := v.data.([]string) - return ok -} - -// EachStr calls the specified callback for each object -// in the []string. -// -// Panics if the object is the wrong type. -func (v *Value) EachStr(callback func(int, string) bool) *Value { - - for index, val := range v.MustStrSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereStr uses the specified decider function to select items -// from the []string. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereStr(decider func(int, string) bool) *Value { - - var selected []string - - v.EachStr(func(index int, val string) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupStr uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]string. -func (v *Value) GroupStr(grouper func(int, string) string) *Value { - - groups := make(map[string][]string) - - v.EachStr(func(index int, val string) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]string, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceStr uses the specified function to replace each strings -// by iterating each item. The data in the returned result will be a -// []string containing the replaced items. -func (v *Value) ReplaceStr(replacer func(int, string) string) *Value { - - arr := v.MustStrSlice() - replaced := make([]string, len(arr)) - - v.EachStr(func(index int, val string) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectStr uses the specified collector function to collect a value -// for each of the strings in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectStr(collector func(int, string) interface{}) *Value { - - arr := v.MustStrSlice() - collected := make([]interface{}, len(arr)) - - v.EachStr(func(index int, val string) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Int (int and []int) - -------------------------------------------------- -*/ - -// Int gets the value as a int, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Int(optionalDefault ...int) int { - if s, ok := v.data.(int); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustInt gets the value as a int. -// -// Panics if the object is not a int. -func (v *Value) MustInt() int { - return v.data.(int) -} - -// IntSlice gets the value as a []int, returns the optionalDefault -// value or nil if the value is not a []int. -func (v *Value) IntSlice(optionalDefault ...[]int) []int { - if s, ok := v.data.([]int); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustIntSlice gets the value as a []int. -// -// Panics if the object is not a []int. -func (v *Value) MustIntSlice() []int { - return v.data.([]int) -} - -// IsInt gets whether the object contained is a int or not. -func (v *Value) IsInt() bool { - _, ok := v.data.(int) - return ok -} - -// IsIntSlice gets whether the object contained is a []int or not. -func (v *Value) IsIntSlice() bool { - _, ok := v.data.([]int) - return ok -} - -// EachInt calls the specified callback for each object -// in the []int. -// -// Panics if the object is the wrong type. -func (v *Value) EachInt(callback func(int, int) bool) *Value { - - for index, val := range v.MustIntSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereInt uses the specified decider function to select items -// from the []int. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereInt(decider func(int, int) bool) *Value { - - var selected []int - - v.EachInt(func(index int, val int) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupInt uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]int. -func (v *Value) GroupInt(grouper func(int, int) string) *Value { - - groups := make(map[string][]int) - - v.EachInt(func(index int, val int) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]int, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceInt uses the specified function to replace each ints -// by iterating each item. The data in the returned result will be a -// []int containing the replaced items. -func (v *Value) ReplaceInt(replacer func(int, int) int) *Value { - - arr := v.MustIntSlice() - replaced := make([]int, len(arr)) - - v.EachInt(func(index int, val int) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectInt uses the specified collector function to collect a value -// for each of the ints in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectInt(collector func(int, int) interface{}) *Value { - - arr := v.MustIntSlice() - collected := make([]interface{}, len(arr)) - - v.EachInt(func(index int, val int) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Int8 (int8 and []int8) - -------------------------------------------------- -*/ - -// Int8 gets the value as a int8, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Int8(optionalDefault ...int8) int8 { - if s, ok := v.data.(int8); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustInt8 gets the value as a int8. -// -// Panics if the object is not a int8. -func (v *Value) MustInt8() int8 { - return v.data.(int8) -} - -// Int8Slice gets the value as a []int8, returns the optionalDefault -// value or nil if the value is not a []int8. -func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 { - if s, ok := v.data.([]int8); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustInt8Slice gets the value as a []int8. -// -// Panics if the object is not a []int8. -func (v *Value) MustInt8Slice() []int8 { - return v.data.([]int8) -} - -// IsInt8 gets whether the object contained is a int8 or not. -func (v *Value) IsInt8() bool { - _, ok := v.data.(int8) - return ok -} - -// IsInt8Slice gets whether the object contained is a []int8 or not. -func (v *Value) IsInt8Slice() bool { - _, ok := v.data.([]int8) - return ok -} - -// EachInt8 calls the specified callback for each object -// in the []int8. -// -// Panics if the object is the wrong type. -func (v *Value) EachInt8(callback func(int, int8) bool) *Value { - - for index, val := range v.MustInt8Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereInt8 uses the specified decider function to select items -// from the []int8. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereInt8(decider func(int, int8) bool) *Value { - - var selected []int8 - - v.EachInt8(func(index int, val int8) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupInt8 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]int8. -func (v *Value) GroupInt8(grouper func(int, int8) string) *Value { - - groups := make(map[string][]int8) - - v.EachInt8(func(index int, val int8) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]int8, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceInt8 uses the specified function to replace each int8s -// by iterating each item. The data in the returned result will be a -// []int8 containing the replaced items. -func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value { - - arr := v.MustInt8Slice() - replaced := make([]int8, len(arr)) - - v.EachInt8(func(index int, val int8) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectInt8 uses the specified collector function to collect a value -// for each of the int8s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value { - - arr := v.MustInt8Slice() - collected := make([]interface{}, len(arr)) - - v.EachInt8(func(index int, val int8) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Int16 (int16 and []int16) - -------------------------------------------------- -*/ - -// Int16 gets the value as a int16, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Int16(optionalDefault ...int16) int16 { - if s, ok := v.data.(int16); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustInt16 gets the value as a int16. -// -// Panics if the object is not a int16. -func (v *Value) MustInt16() int16 { - return v.data.(int16) -} - -// Int16Slice gets the value as a []int16, returns the optionalDefault -// value or nil if the value is not a []int16. -func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 { - if s, ok := v.data.([]int16); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustInt16Slice gets the value as a []int16. -// -// Panics if the object is not a []int16. -func (v *Value) MustInt16Slice() []int16 { - return v.data.([]int16) -} - -// IsInt16 gets whether the object contained is a int16 or not. -func (v *Value) IsInt16() bool { - _, ok := v.data.(int16) - return ok -} - -// IsInt16Slice gets whether the object contained is a []int16 or not. -func (v *Value) IsInt16Slice() bool { - _, ok := v.data.([]int16) - return ok -} - -// EachInt16 calls the specified callback for each object -// in the []int16. -// -// Panics if the object is the wrong type. -func (v *Value) EachInt16(callback func(int, int16) bool) *Value { - - for index, val := range v.MustInt16Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereInt16 uses the specified decider function to select items -// from the []int16. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereInt16(decider func(int, int16) bool) *Value { - - var selected []int16 - - v.EachInt16(func(index int, val int16) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupInt16 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]int16. -func (v *Value) GroupInt16(grouper func(int, int16) string) *Value { - - groups := make(map[string][]int16) - - v.EachInt16(func(index int, val int16) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]int16, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceInt16 uses the specified function to replace each int16s -// by iterating each item. The data in the returned result will be a -// []int16 containing the replaced items. -func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value { - - arr := v.MustInt16Slice() - replaced := make([]int16, len(arr)) - - v.EachInt16(func(index int, val int16) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectInt16 uses the specified collector function to collect a value -// for each of the int16s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value { - - arr := v.MustInt16Slice() - collected := make([]interface{}, len(arr)) - - v.EachInt16(func(index int, val int16) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Int32 (int32 and []int32) - -------------------------------------------------- -*/ - -// Int32 gets the value as a int32, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Int32(optionalDefault ...int32) int32 { - if s, ok := v.data.(int32); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustInt32 gets the value as a int32. -// -// Panics if the object is not a int32. -func (v *Value) MustInt32() int32 { - return v.data.(int32) -} - -// Int32Slice gets the value as a []int32, returns the optionalDefault -// value or nil if the value is not a []int32. -func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 { - if s, ok := v.data.([]int32); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustInt32Slice gets the value as a []int32. -// -// Panics if the object is not a []int32. -func (v *Value) MustInt32Slice() []int32 { - return v.data.([]int32) -} - -// IsInt32 gets whether the object contained is a int32 or not. -func (v *Value) IsInt32() bool { - _, ok := v.data.(int32) - return ok -} - -// IsInt32Slice gets whether the object contained is a []int32 or not. -func (v *Value) IsInt32Slice() bool { - _, ok := v.data.([]int32) - return ok -} - -// EachInt32 calls the specified callback for each object -// in the []int32. -// -// Panics if the object is the wrong type. -func (v *Value) EachInt32(callback func(int, int32) bool) *Value { - - for index, val := range v.MustInt32Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereInt32 uses the specified decider function to select items -// from the []int32. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereInt32(decider func(int, int32) bool) *Value { - - var selected []int32 - - v.EachInt32(func(index int, val int32) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupInt32 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]int32. -func (v *Value) GroupInt32(grouper func(int, int32) string) *Value { - - groups := make(map[string][]int32) - - v.EachInt32(func(index int, val int32) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]int32, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceInt32 uses the specified function to replace each int32s -// by iterating each item. The data in the returned result will be a -// []int32 containing the replaced items. -func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value { - - arr := v.MustInt32Slice() - replaced := make([]int32, len(arr)) - - v.EachInt32(func(index int, val int32) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectInt32 uses the specified collector function to collect a value -// for each of the int32s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value { - - arr := v.MustInt32Slice() - collected := make([]interface{}, len(arr)) - - v.EachInt32(func(index int, val int32) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Int64 (int64 and []int64) - -------------------------------------------------- -*/ - -// Int64 gets the value as a int64, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Int64(optionalDefault ...int64) int64 { - if s, ok := v.data.(int64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustInt64 gets the value as a int64. -// -// Panics if the object is not a int64. -func (v *Value) MustInt64() int64 { - return v.data.(int64) -} - -// Int64Slice gets the value as a []int64, returns the optionalDefault -// value or nil if the value is not a []int64. -func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 { - if s, ok := v.data.([]int64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustInt64Slice gets the value as a []int64. -// -// Panics if the object is not a []int64. -func (v *Value) MustInt64Slice() []int64 { - return v.data.([]int64) -} - -// IsInt64 gets whether the object contained is a int64 or not. -func (v *Value) IsInt64() bool { - _, ok := v.data.(int64) - return ok -} - -// IsInt64Slice gets whether the object contained is a []int64 or not. -func (v *Value) IsInt64Slice() bool { - _, ok := v.data.([]int64) - return ok -} - -// EachInt64 calls the specified callback for each object -// in the []int64. -// -// Panics if the object is the wrong type. -func (v *Value) EachInt64(callback func(int, int64) bool) *Value { - - for index, val := range v.MustInt64Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereInt64 uses the specified decider function to select items -// from the []int64. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereInt64(decider func(int, int64) bool) *Value { - - var selected []int64 - - v.EachInt64(func(index int, val int64) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupInt64 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]int64. -func (v *Value) GroupInt64(grouper func(int, int64) string) *Value { - - groups := make(map[string][]int64) - - v.EachInt64(func(index int, val int64) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]int64, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceInt64 uses the specified function to replace each int64s -// by iterating each item. The data in the returned result will be a -// []int64 containing the replaced items. -func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value { - - arr := v.MustInt64Slice() - replaced := make([]int64, len(arr)) - - v.EachInt64(func(index int, val int64) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectInt64 uses the specified collector function to collect a value -// for each of the int64s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value { - - arr := v.MustInt64Slice() - collected := make([]interface{}, len(arr)) - - v.EachInt64(func(index int, val int64) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Uint (uint and []uint) - -------------------------------------------------- -*/ - -// Uint gets the value as a uint, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Uint(optionalDefault ...uint) uint { - if s, ok := v.data.(uint); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustUint gets the value as a uint. -// -// Panics if the object is not a uint. -func (v *Value) MustUint() uint { - return v.data.(uint) -} - -// UintSlice gets the value as a []uint, returns the optionalDefault -// value or nil if the value is not a []uint. -func (v *Value) UintSlice(optionalDefault ...[]uint) []uint { - if s, ok := v.data.([]uint); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustUintSlice gets the value as a []uint. -// -// Panics if the object is not a []uint. -func (v *Value) MustUintSlice() []uint { - return v.data.([]uint) -} - -// IsUint gets whether the object contained is a uint or not. -func (v *Value) IsUint() bool { - _, ok := v.data.(uint) - return ok -} - -// IsUintSlice gets whether the object contained is a []uint or not. -func (v *Value) IsUintSlice() bool { - _, ok := v.data.([]uint) - return ok -} - -// EachUint calls the specified callback for each object -// in the []uint. -// -// Panics if the object is the wrong type. -func (v *Value) EachUint(callback func(int, uint) bool) *Value { - - for index, val := range v.MustUintSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereUint uses the specified decider function to select items -// from the []uint. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereUint(decider func(int, uint) bool) *Value { - - var selected []uint - - v.EachUint(func(index int, val uint) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupUint uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]uint. -func (v *Value) GroupUint(grouper func(int, uint) string) *Value { - - groups := make(map[string][]uint) - - v.EachUint(func(index int, val uint) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]uint, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceUint uses the specified function to replace each uints -// by iterating each item. The data in the returned result will be a -// []uint containing the replaced items. -func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value { - - arr := v.MustUintSlice() - replaced := make([]uint, len(arr)) - - v.EachUint(func(index int, val uint) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectUint uses the specified collector function to collect a value -// for each of the uints in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value { - - arr := v.MustUintSlice() - collected := make([]interface{}, len(arr)) - - v.EachUint(func(index int, val uint) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Uint8 (uint8 and []uint8) - -------------------------------------------------- -*/ - -// Uint8 gets the value as a uint8, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Uint8(optionalDefault ...uint8) uint8 { - if s, ok := v.data.(uint8); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustUint8 gets the value as a uint8. -// -// Panics if the object is not a uint8. -func (v *Value) MustUint8() uint8 { - return v.data.(uint8) -} - -// Uint8Slice gets the value as a []uint8, returns the optionalDefault -// value or nil if the value is not a []uint8. -func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 { - if s, ok := v.data.([]uint8); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustUint8Slice gets the value as a []uint8. -// -// Panics if the object is not a []uint8. -func (v *Value) MustUint8Slice() []uint8 { - return v.data.([]uint8) -} - -// IsUint8 gets whether the object contained is a uint8 or not. -func (v *Value) IsUint8() bool { - _, ok := v.data.(uint8) - return ok -} - -// IsUint8Slice gets whether the object contained is a []uint8 or not. -func (v *Value) IsUint8Slice() bool { - _, ok := v.data.([]uint8) - return ok -} - -// EachUint8 calls the specified callback for each object -// in the []uint8. -// -// Panics if the object is the wrong type. -func (v *Value) EachUint8(callback func(int, uint8) bool) *Value { - - for index, val := range v.MustUint8Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereUint8 uses the specified decider function to select items -// from the []uint8. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value { - - var selected []uint8 - - v.EachUint8(func(index int, val uint8) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupUint8 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]uint8. -func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value { - - groups := make(map[string][]uint8) - - v.EachUint8(func(index int, val uint8) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]uint8, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceUint8 uses the specified function to replace each uint8s -// by iterating each item. The data in the returned result will be a -// []uint8 containing the replaced items. -func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value { - - arr := v.MustUint8Slice() - replaced := make([]uint8, len(arr)) - - v.EachUint8(func(index int, val uint8) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectUint8 uses the specified collector function to collect a value -// for each of the uint8s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value { - - arr := v.MustUint8Slice() - collected := make([]interface{}, len(arr)) - - v.EachUint8(func(index int, val uint8) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Uint16 (uint16 and []uint16) - -------------------------------------------------- -*/ - -// Uint16 gets the value as a uint16, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Uint16(optionalDefault ...uint16) uint16 { - if s, ok := v.data.(uint16); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustUint16 gets the value as a uint16. -// -// Panics if the object is not a uint16. -func (v *Value) MustUint16() uint16 { - return v.data.(uint16) -} - -// Uint16Slice gets the value as a []uint16, returns the optionalDefault -// value or nil if the value is not a []uint16. -func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 { - if s, ok := v.data.([]uint16); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustUint16Slice gets the value as a []uint16. -// -// Panics if the object is not a []uint16. -func (v *Value) MustUint16Slice() []uint16 { - return v.data.([]uint16) -} - -// IsUint16 gets whether the object contained is a uint16 or not. -func (v *Value) IsUint16() bool { - _, ok := v.data.(uint16) - return ok -} - -// IsUint16Slice gets whether the object contained is a []uint16 or not. -func (v *Value) IsUint16Slice() bool { - _, ok := v.data.([]uint16) - return ok -} - -// EachUint16 calls the specified callback for each object -// in the []uint16. -// -// Panics if the object is the wrong type. -func (v *Value) EachUint16(callback func(int, uint16) bool) *Value { - - for index, val := range v.MustUint16Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereUint16 uses the specified decider function to select items -// from the []uint16. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value { - - var selected []uint16 - - v.EachUint16(func(index int, val uint16) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupUint16 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]uint16. -func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value { - - groups := make(map[string][]uint16) - - v.EachUint16(func(index int, val uint16) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]uint16, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceUint16 uses the specified function to replace each uint16s -// by iterating each item. The data in the returned result will be a -// []uint16 containing the replaced items. -func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value { - - arr := v.MustUint16Slice() - replaced := make([]uint16, len(arr)) - - v.EachUint16(func(index int, val uint16) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectUint16 uses the specified collector function to collect a value -// for each of the uint16s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value { - - arr := v.MustUint16Slice() - collected := make([]interface{}, len(arr)) - - v.EachUint16(func(index int, val uint16) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Uint32 (uint32 and []uint32) - -------------------------------------------------- -*/ - -// Uint32 gets the value as a uint32, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Uint32(optionalDefault ...uint32) uint32 { - if s, ok := v.data.(uint32); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustUint32 gets the value as a uint32. -// -// Panics if the object is not a uint32. -func (v *Value) MustUint32() uint32 { - return v.data.(uint32) -} - -// Uint32Slice gets the value as a []uint32, returns the optionalDefault -// value or nil if the value is not a []uint32. -func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 { - if s, ok := v.data.([]uint32); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustUint32Slice gets the value as a []uint32. -// -// Panics if the object is not a []uint32. -func (v *Value) MustUint32Slice() []uint32 { - return v.data.([]uint32) -} - -// IsUint32 gets whether the object contained is a uint32 or not. -func (v *Value) IsUint32() bool { - _, ok := v.data.(uint32) - return ok -} - -// IsUint32Slice gets whether the object contained is a []uint32 or not. -func (v *Value) IsUint32Slice() bool { - _, ok := v.data.([]uint32) - return ok -} - -// EachUint32 calls the specified callback for each object -// in the []uint32. -// -// Panics if the object is the wrong type. -func (v *Value) EachUint32(callback func(int, uint32) bool) *Value { - - for index, val := range v.MustUint32Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereUint32 uses the specified decider function to select items -// from the []uint32. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value { - - var selected []uint32 - - v.EachUint32(func(index int, val uint32) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupUint32 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]uint32. -func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value { - - groups := make(map[string][]uint32) - - v.EachUint32(func(index int, val uint32) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]uint32, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceUint32 uses the specified function to replace each uint32s -// by iterating each item. The data in the returned result will be a -// []uint32 containing the replaced items. -func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value { - - arr := v.MustUint32Slice() - replaced := make([]uint32, len(arr)) - - v.EachUint32(func(index int, val uint32) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectUint32 uses the specified collector function to collect a value -// for each of the uint32s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value { - - arr := v.MustUint32Slice() - collected := make([]interface{}, len(arr)) - - v.EachUint32(func(index int, val uint32) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Uint64 (uint64 and []uint64) - -------------------------------------------------- -*/ - -// Uint64 gets the value as a uint64, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Uint64(optionalDefault ...uint64) uint64 { - if s, ok := v.data.(uint64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustUint64 gets the value as a uint64. -// -// Panics if the object is not a uint64. -func (v *Value) MustUint64() uint64 { - return v.data.(uint64) -} - -// Uint64Slice gets the value as a []uint64, returns the optionalDefault -// value or nil if the value is not a []uint64. -func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 { - if s, ok := v.data.([]uint64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustUint64Slice gets the value as a []uint64. -// -// Panics if the object is not a []uint64. -func (v *Value) MustUint64Slice() []uint64 { - return v.data.([]uint64) -} - -// IsUint64 gets whether the object contained is a uint64 or not. -func (v *Value) IsUint64() bool { - _, ok := v.data.(uint64) - return ok -} - -// IsUint64Slice gets whether the object contained is a []uint64 or not. -func (v *Value) IsUint64Slice() bool { - _, ok := v.data.([]uint64) - return ok -} - -// EachUint64 calls the specified callback for each object -// in the []uint64. -// -// Panics if the object is the wrong type. -func (v *Value) EachUint64(callback func(int, uint64) bool) *Value { - - for index, val := range v.MustUint64Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereUint64 uses the specified decider function to select items -// from the []uint64. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value { - - var selected []uint64 - - v.EachUint64(func(index int, val uint64) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupUint64 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]uint64. -func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value { - - groups := make(map[string][]uint64) - - v.EachUint64(func(index int, val uint64) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]uint64, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceUint64 uses the specified function to replace each uint64s -// by iterating each item. The data in the returned result will be a -// []uint64 containing the replaced items. -func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value { - - arr := v.MustUint64Slice() - replaced := make([]uint64, len(arr)) - - v.EachUint64(func(index int, val uint64) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectUint64 uses the specified collector function to collect a value -// for each of the uint64s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value { - - arr := v.MustUint64Slice() - collected := make([]interface{}, len(arr)) - - v.EachUint64(func(index int, val uint64) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Uintptr (uintptr and []uintptr) - -------------------------------------------------- -*/ - -// Uintptr gets the value as a uintptr, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr { - if s, ok := v.data.(uintptr); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustUintptr gets the value as a uintptr. -// -// Panics if the object is not a uintptr. -func (v *Value) MustUintptr() uintptr { - return v.data.(uintptr) -} - -// UintptrSlice gets the value as a []uintptr, returns the optionalDefault -// value or nil if the value is not a []uintptr. -func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr { - if s, ok := v.data.([]uintptr); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustUintptrSlice gets the value as a []uintptr. -// -// Panics if the object is not a []uintptr. -func (v *Value) MustUintptrSlice() []uintptr { - return v.data.([]uintptr) -} - -// IsUintptr gets whether the object contained is a uintptr or not. -func (v *Value) IsUintptr() bool { - _, ok := v.data.(uintptr) - return ok -} - -// IsUintptrSlice gets whether the object contained is a []uintptr or not. -func (v *Value) IsUintptrSlice() bool { - _, ok := v.data.([]uintptr) - return ok -} - -// EachUintptr calls the specified callback for each object -// in the []uintptr. -// -// Panics if the object is the wrong type. -func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value { - - for index, val := range v.MustUintptrSlice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereUintptr uses the specified decider function to select items -// from the []uintptr. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value { - - var selected []uintptr - - v.EachUintptr(func(index int, val uintptr) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupUintptr uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]uintptr. -func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value { - - groups := make(map[string][]uintptr) - - v.EachUintptr(func(index int, val uintptr) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]uintptr, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceUintptr uses the specified function to replace each uintptrs -// by iterating each item. The data in the returned result will be a -// []uintptr containing the replaced items. -func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value { - - arr := v.MustUintptrSlice() - replaced := make([]uintptr, len(arr)) - - v.EachUintptr(func(index int, val uintptr) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectUintptr uses the specified collector function to collect a value -// for each of the uintptrs in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value { - - arr := v.MustUintptrSlice() - collected := make([]interface{}, len(arr)) - - v.EachUintptr(func(index int, val uintptr) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Float32 (float32 and []float32) - -------------------------------------------------- -*/ - -// Float32 gets the value as a float32, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Float32(optionalDefault ...float32) float32 { - if s, ok := v.data.(float32); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustFloat32 gets the value as a float32. -// -// Panics if the object is not a float32. -func (v *Value) MustFloat32() float32 { - return v.data.(float32) -} - -// Float32Slice gets the value as a []float32, returns the optionalDefault -// value or nil if the value is not a []float32. -func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 { - if s, ok := v.data.([]float32); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustFloat32Slice gets the value as a []float32. -// -// Panics if the object is not a []float32. -func (v *Value) MustFloat32Slice() []float32 { - return v.data.([]float32) -} - -// IsFloat32 gets whether the object contained is a float32 or not. -func (v *Value) IsFloat32() bool { - _, ok := v.data.(float32) - return ok -} - -// IsFloat32Slice gets whether the object contained is a []float32 or not. -func (v *Value) IsFloat32Slice() bool { - _, ok := v.data.([]float32) - return ok -} - -// EachFloat32 calls the specified callback for each object -// in the []float32. -// -// Panics if the object is the wrong type. -func (v *Value) EachFloat32(callback func(int, float32) bool) *Value { - - for index, val := range v.MustFloat32Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereFloat32 uses the specified decider function to select items -// from the []float32. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value { - - var selected []float32 - - v.EachFloat32(func(index int, val float32) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupFloat32 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]float32. -func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value { - - groups := make(map[string][]float32) - - v.EachFloat32(func(index int, val float32) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]float32, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceFloat32 uses the specified function to replace each float32s -// by iterating each item. The data in the returned result will be a -// []float32 containing the replaced items. -func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value { - - arr := v.MustFloat32Slice() - replaced := make([]float32, len(arr)) - - v.EachFloat32(func(index int, val float32) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectFloat32 uses the specified collector function to collect a value -// for each of the float32s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value { - - arr := v.MustFloat32Slice() - collected := make([]interface{}, len(arr)) - - v.EachFloat32(func(index int, val float32) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Float64 (float64 and []float64) - -------------------------------------------------- -*/ - -// Float64 gets the value as a float64, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Float64(optionalDefault ...float64) float64 { - if s, ok := v.data.(float64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustFloat64 gets the value as a float64. -// -// Panics if the object is not a float64. -func (v *Value) MustFloat64() float64 { - return v.data.(float64) -} - -// Float64Slice gets the value as a []float64, returns the optionalDefault -// value or nil if the value is not a []float64. -func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 { - if s, ok := v.data.([]float64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustFloat64Slice gets the value as a []float64. -// -// Panics if the object is not a []float64. -func (v *Value) MustFloat64Slice() []float64 { - return v.data.([]float64) -} - -// IsFloat64 gets whether the object contained is a float64 or not. -func (v *Value) IsFloat64() bool { - _, ok := v.data.(float64) - return ok -} - -// IsFloat64Slice gets whether the object contained is a []float64 or not. -func (v *Value) IsFloat64Slice() bool { - _, ok := v.data.([]float64) - return ok -} - -// EachFloat64 calls the specified callback for each object -// in the []float64. -// -// Panics if the object is the wrong type. -func (v *Value) EachFloat64(callback func(int, float64) bool) *Value { - - for index, val := range v.MustFloat64Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereFloat64 uses the specified decider function to select items -// from the []float64. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value { - - var selected []float64 - - v.EachFloat64(func(index int, val float64) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupFloat64 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]float64. -func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value { - - groups := make(map[string][]float64) - - v.EachFloat64(func(index int, val float64) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]float64, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceFloat64 uses the specified function to replace each float64s -// by iterating each item. The data in the returned result will be a -// []float64 containing the replaced items. -func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value { - - arr := v.MustFloat64Slice() - replaced := make([]float64, len(arr)) - - v.EachFloat64(func(index int, val float64) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectFloat64 uses the specified collector function to collect a value -// for each of the float64s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value { - - arr := v.MustFloat64Slice() - collected := make([]interface{}, len(arr)) - - v.EachFloat64(func(index int, val float64) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Complex64 (complex64 and []complex64) - -------------------------------------------------- -*/ - -// Complex64 gets the value as a complex64, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Complex64(optionalDefault ...complex64) complex64 { - if s, ok := v.data.(complex64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustComplex64 gets the value as a complex64. -// -// Panics if the object is not a complex64. -func (v *Value) MustComplex64() complex64 { - return v.data.(complex64) -} - -// Complex64Slice gets the value as a []complex64, returns the optionalDefault -// value or nil if the value is not a []complex64. -func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 { - if s, ok := v.data.([]complex64); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustComplex64Slice gets the value as a []complex64. -// -// Panics if the object is not a []complex64. -func (v *Value) MustComplex64Slice() []complex64 { - return v.data.([]complex64) -} - -// IsComplex64 gets whether the object contained is a complex64 or not. -func (v *Value) IsComplex64() bool { - _, ok := v.data.(complex64) - return ok -} - -// IsComplex64Slice gets whether the object contained is a []complex64 or not. -func (v *Value) IsComplex64Slice() bool { - _, ok := v.data.([]complex64) - return ok -} - -// EachComplex64 calls the specified callback for each object -// in the []complex64. -// -// Panics if the object is the wrong type. -func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value { - - for index, val := range v.MustComplex64Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereComplex64 uses the specified decider function to select items -// from the []complex64. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value { - - var selected []complex64 - - v.EachComplex64(func(index int, val complex64) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupComplex64 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]complex64. -func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value { - - groups := make(map[string][]complex64) - - v.EachComplex64(func(index int, val complex64) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]complex64, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceComplex64 uses the specified function to replace each complex64s -// by iterating each item. The data in the returned result will be a -// []complex64 containing the replaced items. -func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value { - - arr := v.MustComplex64Slice() - replaced := make([]complex64, len(arr)) - - v.EachComplex64(func(index int, val complex64) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectComplex64 uses the specified collector function to collect a value -// for each of the complex64s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value { - - arr := v.MustComplex64Slice() - collected := make([]interface{}, len(arr)) - - v.EachComplex64(func(index int, val complex64) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} - -/* - Complex128 (complex128 and []complex128) - -------------------------------------------------- -*/ - -// Complex128 gets the value as a complex128, returns the optionalDefault -// value or a system default object if the value is the wrong type. -func (v *Value) Complex128(optionalDefault ...complex128) complex128 { - if s, ok := v.data.(complex128); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return 0 -} - -// MustComplex128 gets the value as a complex128. -// -// Panics if the object is not a complex128. -func (v *Value) MustComplex128() complex128 { - return v.data.(complex128) -} - -// Complex128Slice gets the value as a []complex128, returns the optionalDefault -// value or nil if the value is not a []complex128. -func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 { - if s, ok := v.data.([]complex128); ok { - return s - } - if len(optionalDefault) == 1 { - return optionalDefault[0] - } - return nil -} - -// MustComplex128Slice gets the value as a []complex128. -// -// Panics if the object is not a []complex128. -func (v *Value) MustComplex128Slice() []complex128 { - return v.data.([]complex128) -} - -// IsComplex128 gets whether the object contained is a complex128 or not. -func (v *Value) IsComplex128() bool { - _, ok := v.data.(complex128) - return ok -} - -// IsComplex128Slice gets whether the object contained is a []complex128 or not. -func (v *Value) IsComplex128Slice() bool { - _, ok := v.data.([]complex128) - return ok -} - -// EachComplex128 calls the specified callback for each object -// in the []complex128. -// -// Panics if the object is the wrong type. -func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value { - - for index, val := range v.MustComplex128Slice() { - carryon := callback(index, val) - if carryon == false { - break - } - } - - return v - -} - -// WhereComplex128 uses the specified decider function to select items -// from the []complex128. The object contained in the result will contain -// only the selected items. -func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value { - - var selected []complex128 - - v.EachComplex128(func(index int, val complex128) bool { - shouldSelect := decider(index, val) - if shouldSelect == false { - selected = append(selected, val) - } - return true - }) - - return &Value{data: selected} - -} - -// GroupComplex128 uses the specified grouper function to group the items -// keyed by the return of the grouper. The object contained in the -// result will contain a map[string][]complex128. -func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value { - - groups := make(map[string][]complex128) - - v.EachComplex128(func(index int, val complex128) bool { - group := grouper(index, val) - if _, ok := groups[group]; !ok { - groups[group] = make([]complex128, 0) - } - groups[group] = append(groups[group], val) - return true - }) - - return &Value{data: groups} - -} - -// ReplaceComplex128 uses the specified function to replace each complex128s -// by iterating each item. The data in the returned result will be a -// []complex128 containing the replaced items. -func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value { - - arr := v.MustComplex128Slice() - replaced := make([]complex128, len(arr)) - - v.EachComplex128(func(index int, val complex128) bool { - replaced[index] = replacer(index, val) - return true - }) - - return &Value{data: replaced} - -} - -// CollectComplex128 uses the specified collector function to collect a value -// for each of the complex128s in the slice. The data returned will be a -// []interface{}. -func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value { - - arr := v.MustComplex128Slice() - collected := make([]interface{}, len(arr)) - - v.EachComplex128(func(index int, val complex128) bool { - collected[index] = collector(index, val) - return true - }) - - return &Value{data: collected} -} diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/value.go b/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/value.go deleted file mode 100644 index 7aaef06b1ce..00000000000 --- a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/value.go +++ /dev/null @@ -1,13 +0,0 @@ -package objx - -// Value provides methods for extracting interface{} data in various -// types. -type Value struct { - // data contains the raw data being managed by this Value - data interface{} -} - -// Data returns the raw data contained by this Value -func (v *Value) Data() interface{} { - return v.data -} diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/batch.go b/vendor/github.com/syndtr/goleveldb/leveldb/batch.go index 501006717bf..225920002df 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/batch.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/batch.go @@ -9,13 +9,15 @@ package leveldb import ( "encoding/binary" "fmt" + "io" "github.com/syndtr/goleveldb/leveldb/errors" "github.com/syndtr/goleveldb/leveldb/memdb" "github.com/syndtr/goleveldb/leveldb/storage" ) -// ErrBatchCorrupted records reason of batch corruption. +// ErrBatchCorrupted records reason of batch corruption. This error will be +// wrapped with errors.ErrCorrupted. type ErrBatchCorrupted struct { Reason string } @@ -29,8 +31,9 @@ func newErrBatchCorrupted(reason string) error { } const ( - batchHdrLen = 8 + 4 - batchGrowRec = 3000 + batchHeaderLen = 8 + 4 + batchGrowRec = 3000 + batchBufioSize = 16 ) // BatchReplay wraps basic batch operations. @@ -39,34 +42,46 @@ type BatchReplay interface { Delete(key []byte) } +type batchIndex struct { + keyType keyType + keyPos, keyLen int + valuePos, valueLen int +} + +func (index batchIndex) k(data []byte) []byte { + return data[index.keyPos : index.keyPos+index.keyLen] +} + +func (index batchIndex) v(data []byte) []byte { + if index.valueLen != 0 { + return data[index.valuePos : index.valuePos+index.valueLen] + } + return nil +} + +func (index batchIndex) kv(data []byte) (key, value []byte) { + return index.k(data), index.v(data) +} + // Batch is a write batch. type Batch struct { - data []byte - rLen, bLen int - seq uint64 - sync bool + data []byte + index []batchIndex + + // internalLen is sums of key/value pair length plus 8-bytes internal key. + internalLen int } func (b *Batch) grow(n int) { - off := len(b.data) - if off == 0 { - off = batchHdrLen - if b.data != nil { - b.data = b.data[:off] - } - } - if cap(b.data)-off < n { - if b.data == nil { - b.data = make([]byte, off, off+n) - } else { - odata := b.data - div := 1 - if b.rLen > batchGrowRec { - div = b.rLen / batchGrowRec - } - b.data = make([]byte, off, off+n+(off-batchHdrLen)/div) - copy(b.data, odata) + o := len(b.data) + if cap(b.data)-o < n { + div := 1 + if len(b.index) > batchGrowRec { + div = len(b.index) / batchGrowRec } + ndata := make([]byte, o, o+n+o/div) + copy(ndata, b.data) + b.data = ndata } } @@ -76,32 +91,36 @@ func (b *Batch) appendRec(kt keyType, key, value []byte) { n += binary.MaxVarintLen32 + len(value) } b.grow(n) - off := len(b.data) - data := b.data[:off+n] - data[off] = byte(kt) - off++ - off += binary.PutUvarint(data[off:], uint64(len(key))) - copy(data[off:], key) - off += len(key) + index := batchIndex{keyType: kt} + o := len(b.data) + data := b.data[:o+n] + data[o] = byte(kt) + o++ + o += binary.PutUvarint(data[o:], uint64(len(key))) + index.keyPos = o + index.keyLen = len(key) + o += copy(data[o:], key) if kt == keyTypeVal { - off += binary.PutUvarint(data[off:], uint64(len(value))) - copy(data[off:], value) - off += len(value) + o += binary.PutUvarint(data[o:], uint64(len(value))) + index.valuePos = o + index.valueLen = len(value) + o += copy(data[o:], value) } - b.data = data[:off] - b.rLen++ - // Include 8-byte ikey header - b.bLen += len(key) + len(value) + 8 + b.data = data[:o] + b.index = append(b.index, index) + b.internalLen += index.keyLen + index.valueLen + 8 } // Put appends 'put operation' of the given key/value pair to the batch. -// It is safe to modify the contents of the argument after Put returns. +// It is safe to modify the contents of the argument after Put returns but not +// before. func (b *Batch) Put(key, value []byte) { b.appendRec(keyTypeVal, key, value) } // Delete appends 'delete operation' of the given key to the batch. -// It is safe to modify the contents of the argument after Delete returns. +// It is safe to modify the contents of the argument after Delete returns but +// not before. func (b *Batch) Delete(key []byte) { b.appendRec(keyTypeDel, key, nil) } @@ -111,7 +130,7 @@ func (b *Batch) Delete(key []byte) { // The returned slice is not its own copy, so the contents should not be // modified. func (b *Batch) Dump() []byte { - return b.encode() + return b.data } // Load loads given slice into the batch. Previous contents of the batch @@ -119,144 +138,212 @@ func (b *Batch) Dump() []byte { // The given slice will not be copied and will be used as batch buffer, so // it is not safe to modify the contents of the slice. func (b *Batch) Load(data []byte) error { - return b.decode(0, data) + return b.decode(data, -1) } // Replay replays batch contents. func (b *Batch) Replay(r BatchReplay) error { - return b.decodeRec(func(i int, kt keyType, key, value []byte) error { - switch kt { + for _, index := range b.index { + switch index.keyType { case keyTypeVal: - r.Put(key, value) + r.Put(index.k(b.data), index.v(b.data)) case keyTypeDel: - r.Delete(key) + r.Delete(index.k(b.data)) } - return nil - }) + } + return nil } // Len returns number of records in the batch. func (b *Batch) Len() int { - return b.rLen + return len(b.index) } // Reset resets the batch. func (b *Batch) Reset() { b.data = b.data[:0] - b.seq = 0 - b.rLen = 0 - b.bLen = 0 - b.sync = false + b.index = b.index[:0] + b.internalLen = 0 } -func (b *Batch) init(sync bool) { - b.sync = sync +func (b *Batch) replayInternal(fn func(i int, kt keyType, k, v []byte) error) error { + for i, index := range b.index { + if err := fn(i, index.keyType, index.k(b.data), index.v(b.data)); err != nil { + return err + } + } + return nil } func (b *Batch) append(p *Batch) { - if p.rLen > 0 { - b.grow(len(p.data) - batchHdrLen) - b.data = append(b.data, p.data[batchHdrLen:]...) - b.rLen += p.rLen - b.bLen += p.bLen - } - if p.sync { - b.sync = true + ob := len(b.data) + oi := len(b.index) + b.data = append(b.data, p.data...) + b.index = append(b.index, p.index...) + b.internalLen += p.internalLen + + // Updating index offset. + if ob != 0 { + for ; oi < len(b.index); oi++ { + index := &b.index[oi] + index.keyPos += ob + if index.valueLen != 0 { + index.valuePos += ob + } + } } } -// size returns sums of key/value pair length plus 8-bytes ikey. -func (b *Batch) size() int { - return b.bLen -} - -func (b *Batch) encode() []byte { - b.grow(0) - binary.LittleEndian.PutUint64(b.data, b.seq) - binary.LittleEndian.PutUint32(b.data[8:], uint32(b.rLen)) - - return b.data +func (b *Batch) decode(data []byte, expectedLen int) error { + b.data = data + b.index = b.index[:0] + b.internalLen = 0 + err := decodeBatch(data, func(i int, index batchIndex) error { + b.index = append(b.index, index) + b.internalLen += index.keyLen + index.valueLen + 8 + return nil + }) + if err != nil { + return err + } + if expectedLen >= 0 && len(b.index) != expectedLen { + return newErrBatchCorrupted(fmt.Sprintf("invalid records length: %d vs %d", expectedLen, len(b.index))) + } + return nil } -func (b *Batch) decode(prevSeq uint64, data []byte) error { - if len(data) < batchHdrLen { - return newErrBatchCorrupted("too short") +func (b *Batch) putMem(seq uint64, mdb *memdb.DB) error { + var ik []byte + for i, index := range b.index { + ik = makeInternalKey(ik, index.k(b.data), seq+uint64(i), index.keyType) + if err := mdb.Put(ik, index.v(b.data)); err != nil { + return err + } } + return nil +} - b.seq = binary.LittleEndian.Uint64(data) - if b.seq < prevSeq { - return newErrBatchCorrupted("invalid sequence number") - } - b.rLen = int(binary.LittleEndian.Uint32(data[8:])) - if b.rLen < 0 { - return newErrBatchCorrupted("invalid records length") +func (b *Batch) revertMem(seq uint64, mdb *memdb.DB) error { + var ik []byte + for i, index := range b.index { + ik = makeInternalKey(ik, index.k(b.data), seq+uint64(i), index.keyType) + if err := mdb.Delete(ik); err != nil { + return err + } } - // No need to be precise at this point, it won't be used anyway - b.bLen = len(data) - batchHdrLen - b.data = data - return nil } -func (b *Batch) decodeRec(f func(i int, kt keyType, key, value []byte) error) error { - off := batchHdrLen - for i := 0; i < b.rLen; i++ { - if off >= len(b.data) { - return newErrBatchCorrupted("invalid records length") - } +func newBatch() interface{} { + return &Batch{} +} - kt := keyType(b.data[off]) - if kt > keyTypeVal { - panic(kt) - return newErrBatchCorrupted("bad record: invalid type") +func decodeBatch(data []byte, fn func(i int, index batchIndex) error) error { + var index batchIndex + for i, o := 0, 0; o < len(data); i++ { + // Key type. + index.keyType = keyType(data[o]) + if index.keyType > keyTypeVal { + return newErrBatchCorrupted(fmt.Sprintf("bad record: invalid type %#x", uint(index.keyType))) } - off++ + o++ - x, n := binary.Uvarint(b.data[off:]) - off += n - if n <= 0 || off+int(x) > len(b.data) { + // Key. + x, n := binary.Uvarint(data[o:]) + o += n + if n <= 0 || o+int(x) > len(data) { return newErrBatchCorrupted("bad record: invalid key length") } - key := b.data[off : off+int(x)] - off += int(x) - var value []byte - if kt == keyTypeVal { - x, n := binary.Uvarint(b.data[off:]) - off += n - if n <= 0 || off+int(x) > len(b.data) { + index.keyPos = o + index.keyLen = int(x) + o += index.keyLen + + // Value. + if index.keyType == keyTypeVal { + x, n = binary.Uvarint(data[o:]) + o += n + if n <= 0 || o+int(x) > len(data) { return newErrBatchCorrupted("bad record: invalid value length") } - value = b.data[off : off+int(x)] - off += int(x) + index.valuePos = o + index.valueLen = int(x) + o += index.valueLen + } else { + index.valuePos = 0 + index.valueLen = 0 } - if err := f(i, kt, key, value); err != nil { + if err := fn(i, index); err != nil { return err } } - return nil } -func (b *Batch) memReplay(to *memdb.DB) error { - var ikScratch []byte - return b.decodeRec(func(i int, kt keyType, key, value []byte) error { - ikScratch = makeInternalKey(ikScratch, key, b.seq+uint64(i), kt) - return to.Put(ikScratch, value) +func decodeBatchToMem(data []byte, expectSeq uint64, mdb *memdb.DB) (seq uint64, batchLen int, err error) { + seq, batchLen, err = decodeBatchHeader(data) + if err != nil { + return 0, 0, err + } + if seq < expectSeq { + return 0, 0, newErrBatchCorrupted("invalid sequence number") + } + data = data[batchHeaderLen:] + var ik []byte + var decodedLen int + err = decodeBatch(data, func(i int, index batchIndex) error { + if i >= batchLen { + return newErrBatchCorrupted("invalid records length") + } + ik = makeInternalKey(ik, index.k(data), seq+uint64(i), index.keyType) + if err := mdb.Put(ik, index.v(data)); err != nil { + return err + } + decodedLen++ + return nil }) + if err == nil && decodedLen != batchLen { + err = newErrBatchCorrupted(fmt.Sprintf("invalid records length: %d vs %d", batchLen, decodedLen)) + } + return } -func (b *Batch) memDecodeAndReplay(prevSeq uint64, data []byte, to *memdb.DB) error { - if err := b.decode(prevSeq, data); err != nil { - return err +func encodeBatchHeader(dst []byte, seq uint64, batchLen int) []byte { + dst = ensureBuffer(dst, batchHeaderLen) + binary.LittleEndian.PutUint64(dst, seq) + binary.LittleEndian.PutUint32(dst[8:], uint32(batchLen)) + return dst +} + +func decodeBatchHeader(data []byte) (seq uint64, batchLen int, err error) { + if len(data) < batchHeaderLen { + return 0, 0, newErrBatchCorrupted("too short") + } + + seq = binary.LittleEndian.Uint64(data) + batchLen = int(binary.LittleEndian.Uint32(data[8:])) + if batchLen < 0 { + return 0, 0, newErrBatchCorrupted("invalid records length") } - return b.memReplay(to) + return } -func (b *Batch) revertMemReplay(to *memdb.DB) error { - var ikScratch []byte - return b.decodeRec(func(i int, kt keyType, key, value []byte) error { - ikScratch := makeInternalKey(ikScratch, key, b.seq+uint64(i), kt) - return to.Delete(ikScratch) - }) +func batchesLen(batches []*Batch) int { + batchLen := 0 + for _, batch := range batches { + batchLen += batch.Len() + } + return batchLen +} + +func writeBatchesWithHeader(wr io.Writer, batches []*Batch, seq uint64) error { + if _, err := wr.Write(encodeBatchHeader(nil, seq, batchesLen(batches))); err != nil { + return err + } + for _, batch := range batches { + if _, err := wr.Write(batch.data); err != nil { + return err + } + } + return nil } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/cache/cache.go b/vendor/github.com/syndtr/goleveldb/leveldb/cache/cache.go index a287d0e5e7e..c5940b232cd 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/cache/cache.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/cache/cache.go @@ -16,7 +16,7 @@ import ( ) // Cacher provides interface to implements a caching functionality. -// An implementation must be goroutine-safe. +// An implementation must be safe for concurrent use. type Cacher interface { // Capacity returns cache capacity. Capacity() int @@ -511,18 +511,12 @@ func (r *Cache) EvictAll() { } } -// Close closes the 'cache map' and releases all 'cache node'. +// Close closes the 'cache map' and forcefully releases all 'cache node'. func (r *Cache) Close() error { r.mu.Lock() if !r.closed { r.closed = true - if r.cacher != nil { - if err := r.cacher.Close(); err != nil { - return err - } - } - h := (*mNode)(r.mHead) h.initBuckets() @@ -541,10 +535,37 @@ func (r *Cache) Close() error { for _, f := range n.onDel { f() } + n.onDel = nil } } } r.mu.Unlock() + + // Avoid deadlock. + if r.cacher != nil { + if err := r.cacher.Close(); err != nil { + return err + } + } + return nil +} + +// CloseWeak closes the 'cache map' and evict all 'cache node' from cacher, but +// unlike Close it doesn't forcefully releases 'cache node'. +func (r *Cache) CloseWeak() error { + r.mu.Lock() + if !r.closed { + r.closed = true + } + r.mu.Unlock() + + // Avoid deadlock. + if r.cacher != nil { + r.cacher.EvictAll() + if err := r.cacher.Close(); err != nil { + return err + } + } return nil } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/comparer.go b/vendor/github.com/syndtr/goleveldb/leveldb/comparer.go index 248bf7c213d..448402b8269 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/comparer.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/comparer.go @@ -6,7 +6,9 @@ package leveldb -import "github.com/syndtr/goleveldb/leveldb/comparer" +import ( + "github.com/syndtr/goleveldb/leveldb/comparer" +) type iComparer struct { ucmp comparer.Comparer @@ -33,12 +35,12 @@ func (icmp *iComparer) Name() string { } func (icmp *iComparer) Compare(a, b []byte) int { - x := icmp.ucmp.Compare(internalKey(a).ukey(), internalKey(b).ukey()) + x := icmp.uCompare(internalKey(a).ukey(), internalKey(b).ukey()) if x == 0 { if m, n := internalKey(a).num(), internalKey(b).num(); m > n { - x = -1 + return -1 } else if m < n { - x = 1 + return 1 } } return x @@ -46,30 +48,20 @@ func (icmp *iComparer) Compare(a, b []byte) int { func (icmp *iComparer) Separator(dst, a, b []byte) []byte { ua, ub := internalKey(a).ukey(), internalKey(b).ukey() - dst = icmp.ucmp.Separator(dst, ua, ub) - if dst == nil { - return nil + dst = icmp.uSeparator(dst, ua, ub) + if dst != nil && len(dst) < len(ua) && icmp.uCompare(ua, dst) < 0 { + // Append earliest possible number. + return append(dst, keyMaxNumBytes...) } - if len(dst) < len(ua) && icmp.uCompare(ua, dst) < 0 { - dst = append(dst, keyMaxNumBytes...) - } else { - // Did not close possibilities that n maybe longer than len(ub). - dst = append(dst, a[len(a)-8:]...) - } - return dst + return nil } func (icmp *iComparer) Successor(dst, b []byte) []byte { ub := internalKey(b).ukey() - dst = icmp.ucmp.Successor(dst, ub) - if dst == nil { - return nil - } - if len(dst) < len(ub) && icmp.uCompare(ub, dst) < 0 { - dst = append(dst, keyMaxNumBytes...) - } else { - // Did not close possibilities that n maybe longer than len(ub). - dst = append(dst, b[len(b)-8:]...) + dst = icmp.uSuccessor(dst, ub) + if dst != nil && len(dst) < len(ub) && icmp.uCompare(ub, dst) < 0 { + // Append earliest possible number. + return append(dst, keyMaxNumBytes...) } - return dst + return nil } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db.go b/vendor/github.com/syndtr/goleveldb/leveldb/db.go index eb6abd0fb18..b0cdcb3d0ab 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db.go @@ -53,14 +53,13 @@ type DB struct { aliveSnaps, aliveIters int32 // Write. - writeC chan *Batch + batchPool sync.Pool + writeMergeC chan writeMerge writeMergedC chan bool writeLockC chan struct{} writeAckC chan error writeDelay time.Duration writeDelayN int - journalC chan *Batch - journalAckC chan error tr *Transaction // Compaction. @@ -94,12 +93,11 @@ func openDB(s *session) (*DB, error) { // Snapshot snapsList: list.New(), // Write - writeC: make(chan *Batch), + batchPool: sync.Pool{New: newBatch}, + writeMergeC: make(chan writeMerge), writeMergedC: make(chan bool), writeLockC: make(chan struct{}, 1), writeAckC: make(chan error), - journalC: make(chan *Batch), - journalAckC: make(chan error), // Compaction tcompCmdC: make(chan cCmd), tcompPauseC: make(chan chan<- struct{}), @@ -144,10 +142,10 @@ func openDB(s *session) (*DB, error) { if readOnly { db.SetReadOnly() } else { - db.closeW.Add(3) + db.closeW.Add(2) go db.tCompaction() go db.mCompaction() - go db.jWriter() + // go db.jWriter() } s.logf("db@open done T·%v", time.Since(start)) @@ -162,10 +160,10 @@ func openDB(s *session) (*DB, error) { // os.ErrExist error. // // Open will return an error with type of ErrCorrupted if corruption -// detected in the DB. Corrupted DB can be recovered with Recover -// function. +// detected in the DB. Use errors.IsCorrupted to test whether an error is +// due to corruption. Corrupted DB can be recovered with Recover function. // -// The returned DB instance is goroutine-safe. +// The returned DB instance is safe for concurrent use. // The DB must be closed after use, by calling Close method. func Open(stor storage.Storage, o *opt.Options) (db *DB, err error) { s, err := newSession(stor, o) @@ -202,13 +200,13 @@ func Open(stor storage.Storage, o *opt.Options) (db *DB, err error) { // os.ErrExist error. // // OpenFile uses standard file-system backed storage implementation as -// desribed in the leveldb/storage package. +// described in the leveldb/storage package. // // OpenFile will return an error with type of ErrCorrupted if corruption -// detected in the DB. Corrupted DB can be recovered with Recover -// function. +// detected in the DB. Use errors.IsCorrupted to test whether an error is +// due to corruption. Corrupted DB can be recovered with Recover function. // -// The returned DB instance is goroutine-safe. +// The returned DB instance is safe for concurrent use. // The DB must be closed after use, by calling Close method. func OpenFile(path string, o *opt.Options) (db *DB, err error) { stor, err := storage.OpenFile(path, o.GetReadOnly()) @@ -229,7 +227,7 @@ func OpenFile(path string, o *opt.Options) (db *DB, err error) { // The DB must already exist or it will returns an error. // Also, Recover will ignore ErrorIfMissing and ErrorIfExist options. // -// The returned DB instance is goroutine-safe. +// The returned DB instance is safe for concurrent use. // The DB must be closed after use, by calling Close method. func Recover(stor storage.Storage, o *opt.Options) (db *DB, err error) { s, err := newSession(stor, o) @@ -255,10 +253,10 @@ func Recover(stor storage.Storage, o *opt.Options) (db *DB, err error) { // The DB must already exist or it will returns an error. // Also, Recover will ignore ErrorIfMissing and ErrorIfExist options. // -// RecoverFile uses standard file-system backed storage implementation as desribed +// RecoverFile uses standard file-system backed storage implementation as described // in the leveldb/storage package. // -// The returned DB instance is goroutine-safe. +// The returned DB instance is safe for concurrent use. // The DB must be closed after use, by calling Close method. func RecoverFile(path string, o *opt.Options) (db *DB, err error) { stor, err := storage.OpenFile(path, false) @@ -504,10 +502,11 @@ func (db *DB) recoverJournal() error { checksum = db.s.o.GetStrict(opt.StrictJournalChecksum) writeBuffer = db.s.o.GetWriteBuffer() - jr *journal.Reader - mdb = memdb.New(db.s.icmp, writeBuffer) - buf = &util.Buffer{} - batch = &Batch{} + jr *journal.Reader + mdb = memdb.New(db.s.icmp, writeBuffer) + buf = &util.Buffer{} + batchSeq uint64 + batchLen int ) for _, fd := range fds { @@ -526,7 +525,7 @@ func (db *DB) recoverJournal() error { } // Flush memdb and remove obsolete journal file. - if !ofd.Nil() { + if !ofd.Zero() { if mdb.Len() > 0 { if _, err := db.s.flushMemdb(rec, mdb, 0); err != nil { fr.Close() @@ -569,7 +568,8 @@ func (db *DB) recoverJournal() error { fr.Close() return errors.SetFd(err, fd) } - if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mdb); err != nil { + batchSeq, batchLen, err = decodeBatchToMem(buf.Bytes(), db.seq, mdb) + if err != nil { if !strict && errors.IsCorrupted(err) { db.s.logf("journal error: %v (skipped)", err) // We won't apply sequence number as it might be corrupted. @@ -581,7 +581,7 @@ func (db *DB) recoverJournal() error { } // Save sequence number. - db.seq = batch.seq + uint64(batch.Len()) + db.seq = batchSeq + uint64(batchLen) // Flush it if large enough. if mdb.Size() >= writeBuffer { @@ -624,7 +624,7 @@ func (db *DB) recoverJournal() error { } // Remove the last obsolete journal file. - if !ofd.Nil() { + if !ofd.Zero() { db.s.stor.Remove(ofd) } @@ -661,9 +661,10 @@ func (db *DB) recoverJournalRO() error { db.logf("journal@recovery RO·Mode F·%d", len(fds)) var ( - jr *journal.Reader - buf = &util.Buffer{} - batch = &Batch{} + jr *journal.Reader + buf = &util.Buffer{} + batchSeq uint64 + batchLen int ) for _, fd := range fds { @@ -703,7 +704,8 @@ func (db *DB) recoverJournalRO() error { fr.Close() return errors.SetFd(err, fd) } - if err := batch.memDecodeAndReplay(db.seq, buf.Bytes(), mdb); err != nil { + batchSeq, batchLen, err = decodeBatchToMem(buf.Bytes(), db.seq, mdb) + if err != nil { if !strict && errors.IsCorrupted(err) { db.s.logf("journal error: %v (skipped)", err) // We won't apply sequence number as it might be corrupted. @@ -715,7 +717,7 @@ func (db *DB) recoverJournalRO() error { } // Save sequence number. - db.seq = batch.seq + uint64(batch.Len()) + db.seq = batchSeq + uint64(batchLen) } fr.Close() @@ -842,7 +844,7 @@ func (db *DB) Get(key []byte, ro *opt.ReadOptions) (value []byte, err error) { // Has returns true if the DB does contains the given key. // -// It is safe to modify the contents of the argument after Get returns. +// It is safe to modify the contents of the argument after Has returns. func (db *DB) Has(key []byte, ro *opt.ReadOptions) (ret bool, err error) { err = db.ok() if err != nil { @@ -856,7 +858,7 @@ func (db *DB) Has(key []byte, ro *opt.ReadOptions) (ret bool, err error) { // NewIterator returns an iterator for the latest snapshot of the // underlying DB. -// The returned iterator is not goroutine-safe, but it is safe to use +// The returned iterator is not safe for concurrent use, but it is safe to use // multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently with modifying its // underlying DB. The resultant key/value pairs are guaranteed to be @@ -1062,6 +1064,8 @@ func (db *DB) Close() error { if db.journal != nil { db.journal.Close() db.journalWriter.Close() + db.journal = nil + db.journalWriter = nil } if db.writeDelayN > 0 { @@ -1077,15 +1081,11 @@ func (db *DB) Close() error { if err1 := db.closer.Close(); err == nil { err = err1 } + db.closer = nil } - // NIL'ing pointers. - db.s = nil - db.mem = nil - db.frozenMem = nil - db.journal = nil - db.journalWriter = nil - db.closer = nil + // Clear memdbs. + db.clearMems() return err } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go index 5553202d5df..b6563e87e47 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_compaction.go @@ -96,7 +96,7 @@ noerr: default: goto haserr } - case _, _ = <-db.closeC: + case <-db.closeC: return } } @@ -113,7 +113,7 @@ haserr: goto hasperr default: } - case _, _ = <-db.closeC: + case <-db.closeC: return } } @@ -126,7 +126,7 @@ hasperr: case db.writeLockC <- struct{}{}: // Hold write lock, so that write won't pass-through. db.compWriteLocking = true - case _, _ = <-db.closeC: + case <-db.closeC: if db.compWriteLocking { // We should release the lock or Close will hang. <-db.writeLockC @@ -195,7 +195,7 @@ func (db *DB) compactionTransact(name string, t compactionTransactInterface) { db.logf("%s exiting (persistent error %q)", name, perr) db.compactionExitTransact() } - case _, _ = <-db.closeC: + case <-db.closeC: db.logf("%s exiting", name) db.compactionExitTransact() } @@ -224,7 +224,7 @@ func (db *DB) compactionTransact(name string, t compactionTransactInterface) { } select { case <-backoffT.C: - case _, _ = <-db.closeC: + case <-db.closeC: db.logf("%s exiting", name) db.compactionExitTransact() } @@ -288,8 +288,8 @@ func (db *DB) memCompaction() { case <-db.compPerErrC: close(resumeC) resumeC = nil - case _, _ = <-db.closeC: - return + case <-db.closeC: + db.compactionExitTransact() } var ( @@ -337,8 +337,8 @@ func (db *DB) memCompaction() { select { case <-resumeC: close(resumeC) - case _, _ = <-db.closeC: - return + case <-db.closeC: + db.compactionExitTransact() } } @@ -378,7 +378,7 @@ func (b *tableCompactionBuilder) appendKV(key, value []byte) error { select { case ch := <-b.db.tcompPauseC: b.db.pauseCompaction(ch) - case _, _ = <-b.db.closeC: + case <-b.db.closeC: b.db.compactionExitTransact() default: } @@ -643,7 +643,7 @@ func (db *DB) tableNeedCompaction() bool { func (db *DB) pauseCompaction(ch chan<- struct{}) { select { case ch <- struct{}{}: - case _, _ = <-db.closeC: + case <-db.closeC: db.compactionExitTransact() } } @@ -688,7 +688,7 @@ func (db *DB) compTrigger(compC chan<- cCmd) { } } -// This will trigger auto compation and/or wait for all compaction to be done. +// This will trigger auto compaction and/or wait for all compaction to be done. func (db *DB) compTriggerWait(compC chan<- cCmd) (err error) { ch := make(chan error) defer close(ch) @@ -697,14 +697,14 @@ func (db *DB) compTriggerWait(compC chan<- cCmd) (err error) { case compC <- cAuto{ch}: case err = <-db.compErrC: return - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } // Wait cmd. select { case err = <-ch: case err = <-db.compErrC: - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } return err @@ -719,14 +719,14 @@ func (db *DB) compTriggerRange(compC chan<- cCmd, level int, min, max []byte) (e case compC <- cRange{level, min, max, ch}: case err := <-db.compErrC: return err - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } // Wait cmd. select { case err = <-ch: case err = <-db.compErrC: - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } return err @@ -758,7 +758,7 @@ func (db *DB) mCompaction() { default: panic("leveldb: unknown command") } - case _, _ = <-db.closeC: + case <-db.closeC: return } } @@ -791,7 +791,7 @@ func (db *DB) tCompaction() { case ch := <-db.tcompPauseC: db.pauseCompaction(ch) continue - case _, _ = <-db.closeC: + case <-db.closeC: return default: } @@ -806,7 +806,7 @@ func (db *DB) tCompaction() { case ch := <-db.tcompPauseC: db.pauseCompaction(ch) continue - case _, _ = <-db.closeC: + case <-db.closeC: return } } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_snapshot.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_snapshot.go index 977f65ba50c..2c69d2e531d 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_snapshot.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_snapshot.go @@ -59,7 +59,7 @@ func (db *DB) releaseSnapshot(se *snapshotElement) { } } -// Gets minimum sequence that not being snapshoted. +// Gets minimum sequence that not being snapshotted. func (db *DB) minSeq() uint64 { db.snapsMu.Lock() defer db.snapsMu.Unlock() @@ -131,7 +131,7 @@ func (snap *Snapshot) Has(key []byte, ro *opt.ReadOptions) (ret bool, err error) } // NewIterator returns an iterator for the snapshot of the underlying DB. -// The returned iterator is not goroutine-safe, but it is safe to use +// The returned iterator is not safe for concurrent use, but it is safe to use // multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently with modifying its // underlying DB. The resultant key/value pairs are guaranteed to be diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_state.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_state.go index 40f454da1e4..65e1c54bb41 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_state.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_state.go @@ -7,6 +7,7 @@ package leveldb import ( + "errors" "sync/atomic" "time" @@ -15,6 +16,10 @@ import ( "github.com/syndtr/goleveldb/leveldb/storage" ) +var ( + errHasFrozenMem = errors.New("has frozen mem") +) + type memDB struct { db *DB *memdb.DB @@ -67,12 +72,11 @@ func (db *DB) sampleSeek(ikey internalKey) { } func (db *DB) mpoolPut(mem *memdb.DB) { - defer func() { - recover() - }() - select { - case db.memPool <- mem: - default: + if !db.isClosed() { + select { + case db.memPool <- mem: + default: + } } } @@ -100,7 +104,13 @@ func (db *DB) mpoolDrain() { case <-db.memPool: default: } - case _, _ = <-db.closeC: + case <-db.closeC: + ticker.Stop() + // Make sure the pool is drained. + select { + case <-db.memPool: + case <-time.After(time.Second): + } close(db.memPool) return } @@ -121,7 +131,7 @@ func (db *DB) newMem(n int) (mem *memDB, err error) { defer db.memMu.Unlock() if db.frozenMem != nil { - panic("still has frozen mem") + return nil, errHasFrozenMem } if db.journal == nil { @@ -148,24 +158,26 @@ func (db *DB) newMem(n int) (mem *memDB, err error) { func (db *DB) getMems() (e, f *memDB) { db.memMu.RLock() defer db.memMu.RUnlock() - if db.mem == nil { + if db.mem != nil { + db.mem.incref() + } else if !db.isClosed() { panic("nil effective mem") } - db.mem.incref() if db.frozenMem != nil { db.frozenMem.incref() } return db.mem, db.frozenMem } -// Get frozen memdb. +// Get effective memdb. func (db *DB) getEffectiveMem() *memDB { db.memMu.RLock() defer db.memMu.RUnlock() - if db.mem == nil { + if db.mem != nil { + db.mem.incref() + } else if !db.isClosed() { panic("nil effective mem") } - db.mem.incref() return db.mem } @@ -200,6 +212,14 @@ func (db *DB) dropFrozenMem() { db.memMu.Unlock() } +// Clear mems ptr; used by DB.Close(). +func (db *DB) clearMems() { + db.memMu.Lock() + db.mem = nil + db.frozenMem = nil + db.memMu.Unlock() +} + // Set closed flag; return true if not already closed. func (db *DB) setClosed() bool { return atomic.CompareAndSwapUint32(&db.closed, 0, 1) diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go index fca88037b81..b8f7e7d21df 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_transaction.go @@ -59,8 +59,8 @@ func (tr *Transaction) Has(key []byte, ro *opt.ReadOptions) (bool, error) { } // NewIterator returns an iterator for the latest snapshot of the transaction. -// The returned iterator is not goroutine-safe, but it is safe to use multiple -// iterators concurrently, with each in a dedicated goroutine. +// The returned iterator is not safe for concurrent use, but it is safe to use +// multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently while writes to the // transaction. The resultant key/value pairs are guaranteed to be consistent. // @@ -167,8 +167,8 @@ func (tr *Transaction) Write(b *Batch, wo *opt.WriteOptions) error { if tr.closed { return errTransactionDone } - return b.decodeRec(func(i int, kt keyType, key, value []byte) error { - return tr.put(kt, key, value) + return b.replayInternal(func(i int, kt keyType, k, v []byte) error { + return tr.put(kt, k, v) }) } @@ -179,7 +179,8 @@ func (tr *Transaction) setDone() { <-tr.db.writeLockC } -// Commit commits the transaction. +// Commit commits the transaction. If error is not nil, then the transaction is +// not committed, it can then either be retried or discarded. // // Other methods should not be called after transaction has been committed. func (tr *Transaction) Commit() error { @@ -192,24 +193,27 @@ func (tr *Transaction) Commit() error { if tr.closed { return errTransactionDone } - defer tr.setDone() if err := tr.flush(); err != nil { - tr.discard() + // Return error, lets user decide either to retry or discard + // transaction. return err } if len(tr.tables) != 0 { // Committing transaction. tr.rec.setSeqNum(tr.seq) tr.db.compCommitLk.Lock() - defer tr.db.compCommitLk.Unlock() + tr.stats.startTimer() + var cerr error for retry := 0; retry < 3; retry++ { - if err := tr.db.s.commit(&tr.rec); err != nil { - tr.db.logf("transaction@commit error R·%d %q", retry, err) + cerr = tr.db.s.commit(&tr.rec) + if cerr != nil { + tr.db.logf("transaction@commit error R·%d %q", retry, cerr) select { case <-time.After(time.Second): - case _, _ = <-tr.db.closeC: + case <-tr.db.closeC: tr.db.logf("transaction@commit exiting") - return err + tr.db.compCommitLk.Unlock() + return cerr } } else { // Success. Set db.seq. @@ -217,9 +221,26 @@ func (tr *Transaction) Commit() error { break } } + tr.stats.stopTimer() + if cerr != nil { + // Return error, lets user decide either to retry or discard + // transaction. + return cerr + } + + // Update compaction stats. This is safe as long as we hold compCommitLk. + tr.db.compStats.addStat(0, &tr.stats) + // Trigger table auto-compaction. tr.db.compTrigger(tr.db.tcompCmdC) + tr.db.compCommitLk.Unlock() + + // Additionally, wait compaction when certain threshold reached. + // Ignore error, returns error only if transaction can't be committed. + tr.db.waitCompaction() } + // Only mark as done if transaction committed successfully. + tr.setDone() return nil } @@ -245,10 +266,20 @@ func (tr *Transaction) Discard() { tr.lk.Unlock() } +func (db *DB) waitCompaction() error { + if db.s.tLen(0) >= db.s.o.GetWriteL0PauseTrigger() { + return db.compTriggerWait(db.tcompCmdC) + } + return nil +} + // OpenTransaction opens an atomic DB transaction. Only one transaction can be -// opened at a time. Write will be blocked until the transaction is committed or -// discarded. -// The returned transaction handle is goroutine-safe. +// opened at a time. Subsequent call to Write and OpenTransaction will be blocked +// until in-flight transaction is committed or discarded. +// The returned transaction handle is safe for concurrent use. +// +// Transaction is expensive and can overwhelm compaction, especially if +// transaction size is small. Use with caution. // // The transaction must be closed once done, either by committing or discarding // the transaction. @@ -263,7 +294,7 @@ func (db *DB) OpenTransaction() (*Transaction, error) { case db.writeLockC <- struct{}{}: case err := <-db.compPerErrC: return nil, err - case _, _ = <-db.closeC: + case <-db.closeC: return nil, ErrClosed } @@ -278,6 +309,11 @@ func (db *DB) OpenTransaction() (*Transaction, error) { } } + // Wait compaction when certain threshold reached. + if err := db.waitCompaction(); err != nil { + return nil, err + } + tr := &Transaction{ db: db, seq: db.seq, diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_util.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_util.go index 7fd386ca43c..7ecd960d2ce 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_util.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_util.go @@ -62,7 +62,7 @@ func (db *DB) checkAndCleanFiles() error { case storage.TypeManifest: keep = fd.Num >= db.s.manifestFd.Num case storage.TypeJournal: - if !db.frozenJournalFd.Nil() { + if !db.frozenJournalFd.Zero() { keep = fd.Num >= db.frozenJournalFd.Num } else { keep = fd.Num >= db.journalFd.Num diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go b/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go index 5576761fedb..5b6cb487dc3 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/db_write.go @@ -14,47 +14,42 @@ import ( "github.com/syndtr/goleveldb/leveldb/util" ) -func (db *DB) writeJournal(b *Batch) error { - w, err := db.journal.Next() +func (db *DB) writeJournal(batches []*Batch, seq uint64, sync bool) error { + wr, err := db.journal.Next() if err != nil { return err } - if _, err := w.Write(b.encode()); err != nil { + if err := writeBatchesWithHeader(wr, batches, seq); err != nil { return err } if err := db.journal.Flush(); err != nil { return err } - if b.sync { + if sync { return db.journalWriter.Sync() } return nil } -func (db *DB) jWriter() { - defer db.closeW.Done() - for { - select { - case b := <-db.journalC: - if b != nil { - db.journalAckC <- db.writeJournal(b) - } - case _, _ = <-db.closeC: - return - } - } -} - func (db *DB) rotateMem(n int, wait bool) (mem *memDB, err error) { + retryLimit := 3 +retry: // Wait for pending memdb compaction. err = db.compTriggerWait(db.mcompCmdC) if err != nil { return } + retryLimit-- // Create new memdb and journal. mem, err = db.newMem(n) if err != nil { + if err == errHasFrozenMem { + if retryLimit <= 0 { + panic("BUG: still has frozen memdb") + } + goto retry + } return } @@ -69,24 +64,29 @@ func (db *DB) rotateMem(n int, wait bool) (mem *memDB, err error) { func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) { delayed := false + slowdownTrigger := db.s.o.GetWriteL0SlowdownTrigger() + pauseTrigger := db.s.o.GetWriteL0PauseTrigger() flush := func() (retry bool) { - v := db.s.version() - defer v.release() mdb = db.getEffectiveMem() + if mdb == nil { + err = ErrClosed + return false + } defer func() { if retry { mdb.decref() mdb = nil } }() + tLen := db.s.tLen(0) mdbFree = mdb.Free() switch { - case v.tLen(0) >= db.s.o.GetWriteL0SlowdownTrigger() && !delayed: + case tLen >= slowdownTrigger && !delayed: delayed = true time.Sleep(time.Millisecond) case mdbFree >= n: return false - case v.tLen(0) >= db.s.o.GetWriteL0PauseTrigger(): + case tLen >= pauseTrigger: delayed = true err = db.compTriggerWait(db.tcompCmdC) if err != nil { @@ -123,159 +123,250 @@ func (db *DB) flush(n int) (mdb *memDB, mdbFree int, err error) { return } -// Write apply the given batch to the DB. The batch will be applied -// sequentially. -// -// It is safe to modify the contents of the arguments after Write returns. -func (db *DB) Write(b *Batch, wo *opt.WriteOptions) (err error) { - err = db.ok() - if err != nil || b == nil || b.Len() == 0 { - return +type writeMerge struct { + sync bool + batch *Batch + keyType keyType + key, value []byte +} + +func (db *DB) unlockWrite(overflow bool, merged int, err error) { + for i := 0; i < merged; i++ { + db.writeAckC <- err + } + if overflow { + // Pass lock to the next write (that failed to merge). + db.writeMergedC <- false + } else { + // Release lock. + <-db.writeLockC } +} - b.init(wo.GetSync() && !db.s.o.GetNoSync()) +// ourBatch if defined should equal with batch. +func (db *DB) writeLocked(batch, ourBatch *Batch, merge, sync bool) error { + // Try to flush memdb. This method would also trying to throttle writes + // if it is too fast and compaction cannot catch-up. + mdb, mdbFree, err := db.flush(batch.internalLen) + if err != nil { + db.unlockWrite(false, 0, err) + return err + } + defer mdb.decref() - if b.size() > db.s.o.GetWriteBuffer() && !db.s.o.GetDisableLargeBatchTransaction() { - // Writes using transaction. - tr, err1 := db.OpenTransaction() - if err1 != nil { - return err1 + var ( + overflow bool + merged int + batches = []*Batch{batch} + ) + + if merge { + // Merge limit. + var mergeLimit int + if batch.internalLen > 128<<10 { + mergeLimit = (1 << 20) - batch.internalLen + } else { + mergeLimit = 128 << 10 } - if err1 := tr.Write(b, wo); err1 != nil { - tr.Discard() - return err1 + mergeCap := mdbFree - batch.internalLen + if mergeLimit > mergeCap { + mergeLimit = mergeCap } - return tr.Commit() - } - // The write happen synchronously. - select { - case db.writeC <- b: - if <-db.writeMergedC { - return <-db.writeAckC + merge: + for mergeLimit > 0 { + select { + case incoming := <-db.writeMergeC: + if incoming.batch != nil { + // Merge batch. + if incoming.batch.internalLen > mergeLimit { + overflow = true + break merge + } + batches = append(batches, incoming.batch) + mergeLimit -= incoming.batch.internalLen + } else { + // Merge put. + internalLen := len(incoming.key) + len(incoming.value) + 8 + if internalLen > mergeLimit { + overflow = true + break merge + } + if ourBatch == nil { + ourBatch = db.batchPool.Get().(*Batch) + ourBatch.Reset() + batches = append(batches, ourBatch) + } + // We can use same batch since concurrent write doesn't + // guarantee write order. + ourBatch.appendRec(incoming.keyType, incoming.key, incoming.value) + mergeLimit -= internalLen + } + sync = sync || incoming.sync + merged++ + db.writeMergedC <- true + + default: + break merge + } } - // Continue, the write lock already acquired by previous writer - // and handed out to us. - case db.writeLockC <- struct{}{}: - case err = <-db.compPerErrC: - return - case _, _ = <-db.closeC: - return ErrClosed } - merged := 0 - danglingMerge := false - defer func() { - for i := 0; i < merged; i++ { - db.writeAckC <- err - } - if danglingMerge { - // Only one dangling merge at most, so this is safe. - db.writeMergedC <- false - } else { - <-db.writeLockC + // Seq number. + seq := db.seq + 1 + + // Write journal. + if err := db.writeJournal(batches, seq, sync); err != nil { + db.unlockWrite(overflow, merged, err) + return err + } + + // Put batches. + for _, batch := range batches { + if err := batch.putMem(seq, mdb.DB); err != nil { + panic(err) } - }() + seq += uint64(batch.Len()) + } - mdb, mdbFree, err := db.flush(b.size()) - if err != nil { - return + // Incr seq number. + db.addSeq(uint64(batchesLen(batches))) + + // Rotate memdb if it's reach the threshold. + if batch.internalLen >= mdbFree { + db.rotateMem(0, false) } - defer mdb.decref() - // Calculate maximum size of the batch. - m := 1 << 20 - if x := b.size(); x <= 128<<10 { - m = x + (128 << 10) + db.unlockWrite(overflow, merged, nil) + return nil +} + +// Write apply the given batch to the DB. The batch records will be applied +// sequentially. Write might be used concurrently, when used concurrently and +// batch is small enough, write will try to merge the batches. Set NoWriteMerge +// option to true to disable write merge. +// +// It is safe to modify the contents of the arguments after Write returns but +// not before. Write will not modify content of the batch. +func (db *DB) Write(batch *Batch, wo *opt.WriteOptions) error { + if err := db.ok(); err != nil || batch == nil || batch.Len() == 0 { + return err } - m = minInt(m, mdbFree) - // Merge with other batch. -drain: - for b.size() < m && !b.sync { - select { - case nb := <-db.writeC: - if b.size()+nb.size() <= m { - b.append(nb) - db.writeMergedC <- true - merged++ - } else { - danglingMerge = true - break drain - } - default: - break drain + // If the batch size is larger than write buffer, it may justified to write + // using transaction instead. Using transaction the batch will be written + // into tables directly, skipping the journaling. + if batch.internalLen > db.s.o.GetWriteBuffer() && !db.s.o.GetDisableLargeBatchTransaction() { + tr, err := db.OpenTransaction() + if err != nil { + return err + } + if err := tr.Write(batch, wo); err != nil { + tr.Discard() + return err } + return tr.Commit() } - // Set batch first seq number relative from last seq. - b.seq = db.seq + 1 + merge := !wo.GetNoWriteMerge() && !db.s.o.GetNoWriteMerge() + sync := wo.GetSync() && !db.s.o.GetNoSync() - // Write journal concurrently if it is large enough. - if b.size() >= (128 << 10) { - // Push the write batch to the journal writer + // Acquire write lock. + if merge { select { - case db.journalC <- b: - // Write into memdb - if berr := b.memReplay(mdb.DB); berr != nil { - panic(berr) + case db.writeMergeC <- writeMerge{sync: sync, batch: batch}: + if <-db.writeMergedC { + // Write is merged. + return <-db.writeAckC } - case err = <-db.compPerErrC: - return - case _, _ = <-db.closeC: - err = ErrClosed - return + // Write is not merged, the write lock is handed to us. Continue. + case db.writeLockC <- struct{}{}: + // Write lock acquired. + case err := <-db.compPerErrC: + // Compaction error. + return err + case <-db.closeC: + // Closed + return ErrClosed } - // Wait for journal writer + } else { select { - case err = <-db.journalAckC: - if err != nil { - // Revert memdb if error detected - if berr := b.revertMemReplay(mdb.DB); berr != nil { - panic(berr) - } - return + case db.writeLockC <- struct{}{}: + // Write lock acquired. + case err := <-db.compPerErrC: + // Compaction error. + return err + case <-db.closeC: + // Closed + return ErrClosed + } + } + + return db.writeLocked(batch, nil, merge, sync) +} + +func (db *DB) putRec(kt keyType, key, value []byte, wo *opt.WriteOptions) error { + if err := db.ok(); err != nil { + return err + } + + merge := !wo.GetNoWriteMerge() && !db.s.o.GetNoWriteMerge() + sync := wo.GetSync() && !db.s.o.GetNoSync() + + // Acquire write lock. + if merge { + select { + case db.writeMergeC <- writeMerge{sync: sync, keyType: kt, key: key, value: value}: + if <-db.writeMergedC { + // Write is merged. + return <-db.writeAckC } - case _, _ = <-db.closeC: - err = ErrClosed - return + // Write is not merged, the write lock is handed to us. Continue. + case db.writeLockC <- struct{}{}: + // Write lock acquired. + case err := <-db.compPerErrC: + // Compaction error. + return err + case <-db.closeC: + // Closed + return ErrClosed } } else { - err = db.writeJournal(b) - if err != nil { - return - } - if berr := b.memReplay(mdb.DB); berr != nil { - panic(berr) + select { + case db.writeLockC <- struct{}{}: + // Write lock acquired. + case err := <-db.compPerErrC: + // Compaction error. + return err + case <-db.closeC: + // Closed + return ErrClosed } } - // Set last seq number. - db.addSeq(uint64(b.Len())) - - if b.size() >= mdbFree { - db.rotateMem(0, false) - } - return + batch := db.batchPool.Get().(*Batch) + batch.Reset() + batch.appendRec(kt, key, value) + return db.writeLocked(batch, batch, merge, sync) } // Put sets the value for the given key. It overwrites any previous value -// for that key; a DB is not a multi-map. +// for that key; a DB is not a multi-map. Write merge also applies for Put, see +// Write. // -// It is safe to modify the contents of the arguments after Put returns. +// It is safe to modify the contents of the arguments after Put returns but not +// before. func (db *DB) Put(key, value []byte, wo *opt.WriteOptions) error { - b := new(Batch) - b.Put(key, value) - return db.Write(b, wo) + return db.putRec(keyTypeVal, key, value, wo) } -// Delete deletes the value for the given key. +// Delete deletes the value for the given key. Delete will not returns error if +// key doesn't exist. Write merge also applies for Delete, see Write. // -// It is safe to modify the contents of the arguments after Delete returns. +// It is safe to modify the contents of the arguments after Delete returns but +// not before. func (db *DB) Delete(key []byte, wo *opt.WriteOptions) error { - b := new(Batch) - b.Delete(key) - return db.Write(b, wo) + return db.putRec(keyTypeDel, key, nil, wo) } func isMemOverlaps(icmp *iComparer, mem *memdb.DB, min, max []byte) bool { @@ -304,12 +395,15 @@ func (db *DB) CompactRange(r util.Range) error { case db.writeLockC <- struct{}{}: case err := <-db.compPerErrC: return err - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } // Check for overlaps in memdb. mdb := db.getEffectiveMem() + if mdb == nil { + return ErrClosed + } defer mdb.decref() if isMemOverlaps(db.s.icmp, mdb.DB, r.Start, r.Limit) { // Memdb compaction. @@ -341,7 +435,7 @@ func (db *DB) SetReadOnly() error { db.compWriteLocking = true case err := <-db.compPerErrC: return err - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } @@ -350,7 +444,7 @@ func (db *DB) SetReadOnly() error { case db.compErrSetC <- ErrReadOnly: case perr := <-db.compPerErrC: return perr - case _, _ = <-db.closeC: + case <-db.closeC: return ErrClosed } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/doc.go b/vendor/github.com/syndtr/goleveldb/leveldb/doc.go index 53f13bb24cc..be768e5739f 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/doc.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/doc.go @@ -8,6 +8,8 @@ // // Create or open a database: // +// // The returned DB instance is safe for concurrent use. Which mean that all +// // DB's methods may be called concurrently from multiple goroutine. // db, err := leveldb.OpenFile("path/to/db", nil) // ... // defer db.Close() diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/errors.go b/vendor/github.com/syndtr/goleveldb/leveldb/errors.go index c8bd66a5aa9..de2649812c2 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/errors.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/errors.go @@ -10,6 +10,7 @@ import ( "github.com/syndtr/goleveldb/leveldb/errors" ) +// Common errors. var ( ErrNotFound = errors.ErrNotFound ErrReadOnly = errors.New("leveldb: read-only mode") diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/errors/errors.go b/vendor/github.com/syndtr/goleveldb/leveldb/errors/errors.go index 9a0f6e2c151..8d6146b6f5c 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/errors/errors.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/errors/errors.go @@ -15,6 +15,7 @@ import ( "github.com/syndtr/goleveldb/leveldb/util" ) +// Common errors. var ( ErrNotFound = New("leveldb: not found") ErrReleased = util.ErrReleased @@ -34,11 +35,10 @@ type ErrCorrupted struct { } func (e *ErrCorrupted) Error() string { - if !e.Fd.Nil() { + if !e.Fd.Zero() { return fmt.Sprintf("%v [file=%v]", e.Err, e.Fd) - } else { - return e.Err.Error() } + return e.Err.Error() } // NewErrCorrupted creates new ErrCorrupted error. diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go b/vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go index c2522860b0b..3b55532746e 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go @@ -21,13 +21,13 @@ var ( // IteratorSeeker is the interface that wraps the 'seeks method'. type IteratorSeeker interface { // First moves the iterator to the first key/value pair. If the iterator - // only contains one key/value pair then First and Last whould moves + // only contains one key/value pair then First and Last would moves // to the same key/value pair. // It returns whether such pair exist. First() bool // Last moves the iterator to the last key/value pair. If the iterator - // only contains one key/value pair then First and Last whould moves + // only contains one key/value pair then First and Last would moves // to the same key/value pair. // It returns whether such pair exist. Last() bool @@ -48,7 +48,7 @@ type IteratorSeeker interface { Prev() bool } -// CommonIterator is the interface that wraps common interator methods. +// CommonIterator is the interface that wraps common iterator methods. type CommonIterator interface { IteratorSeeker @@ -71,14 +71,15 @@ type CommonIterator interface { // Iterator iterates over a DB's key/value pairs in key order. // -// When encouter an error any 'seeks method' will return false and will +// When encounter an error any 'seeks method' will return false and will // yield no key/value pairs. The error can be queried by calling the Error // method. Calling Release is still necessary. // // An iterator must be released after use, but it is not necessary to read // an iterator until exhaustion. -// Also, an iterator is not necessarily goroutine-safe, but it is safe to use -// multiple iterators concurrently, with each in a dedicated goroutine. +// Also, an iterator is not necessarily safe for concurrent use, but it is +// safe to use multiple iterators concurrently, with each in a dedicated +// goroutine. type Iterator interface { CommonIterator @@ -98,7 +99,7 @@ type Iterator interface { // // ErrorCallbackSetter implemented by indexed and merged iterator. type ErrorCallbackSetter interface { - // SetErrorCallback allows set an error callback of the coresponding + // SetErrorCallback allows set an error callback of the corresponding // iterator. Use nil to clear the callback. SetErrorCallback(f func(err error)) } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/journal/journal.go b/vendor/github.com/syndtr/goleveldb/leveldb/journal/journal.go index 891098bb77a..d094c3d0f8a 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/journal/journal.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/journal/journal.go @@ -180,34 +180,37 @@ func (r *Reader) nextChunk(first bool) error { checksum := binary.LittleEndian.Uint32(r.buf[r.j+0 : r.j+4]) length := binary.LittleEndian.Uint16(r.buf[r.j+4 : r.j+6]) chunkType := r.buf[r.j+6] - + unprocBlock := r.n - r.j if checksum == 0 && length == 0 && chunkType == 0 { // Drop entire block. - m := r.n - r.j r.i = r.n r.j = r.n - return r.corrupt(m, "zero header", false) - } else { - m := r.n - r.j - r.i = r.j + headerSize - r.j = r.j + headerSize + int(length) - if r.j > r.n { - // Drop entire block. - r.i = r.n - r.j = r.n - return r.corrupt(m, "chunk length overflows block", false) - } else if r.checksum && checksum != util.NewCRC(r.buf[r.i-1:r.j]).Value() { - // Drop entire block. - r.i = r.n - r.j = r.n - return r.corrupt(m, "checksum mismatch", false) - } + return r.corrupt(unprocBlock, "zero header", false) + } + if chunkType < fullChunkType || chunkType > lastChunkType { + // Drop entire block. + r.i = r.n + r.j = r.n + return r.corrupt(unprocBlock, fmt.Sprintf("invalid chunk type %#x", chunkType), false) + } + r.i = r.j + headerSize + r.j = r.j + headerSize + int(length) + if r.j > r.n { + // Drop entire block. + r.i = r.n + r.j = r.n + return r.corrupt(unprocBlock, "chunk length overflows block", false) + } else if r.checksum && checksum != util.NewCRC(r.buf[r.i-1:r.j]).Value() { + // Drop entire block. + r.i = r.n + r.j = r.n + return r.corrupt(unprocBlock, "checksum mismatch", false) } if first && chunkType != fullChunkType && chunkType != firstChunkType { - m := r.j - r.i + chunkLength := (r.j - r.i) + headerSize r.i = r.j // Report the error, but skip it. - return r.corrupt(m+headerSize, "orphan chunk", true) + return r.corrupt(chunkLength, "orphan chunk", true) } r.last = chunkType == fullChunkType || chunkType == lastChunkType return nil diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/key.go b/vendor/github.com/syndtr/goleveldb/leveldb/key.go index d0b80aaf979..ad8f51ec85d 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/key.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/key.go @@ -37,14 +37,14 @@ func (kt keyType) String() string { case keyTypeVal: return "v" } - return "x" + return fmt.Sprintf("", uint(kt)) } // Value types encoded as the last component of internal keys. // Don't modify; this value are saved to disk. const ( - keyTypeDel keyType = iota - keyTypeVal + keyTypeDel = keyType(0) + keyTypeVal = keyType(1) ) // keyTypeSeek defines the keyType that should be passed when constructing an @@ -79,11 +79,7 @@ func makeInternalKey(dst, ukey []byte, seq uint64, kt keyType) internalKey { panic("leveldb: invalid type") } - if n := len(ukey) + 8; cap(dst) < n { - dst = make([]byte, n) - } else { - dst = dst[:n] - } + dst = ensureBuffer(dst, len(ukey)+8) copy(dst, ukey) binary.LittleEndian.PutUint64(dst[len(ukey):], (seq<<8)|uint64(kt)) return internalKey(dst) @@ -143,5 +139,5 @@ func (ik internalKey) String() string { if ukey, seq, kt, err := parseInternalKey(ik); err == nil { return fmt.Sprintf("%s,%s%d", shorten(string(ukey)), kt, seq) } - return "" + return fmt.Sprintf("", []byte(ik)) } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go b/vendor/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go index 1395bd92808..18a19ed4240 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/memdb/memdb.go @@ -17,6 +17,7 @@ import ( "github.com/syndtr/goleveldb/leveldb/util" ) +// Common errors. var ( ErrNotFound = errors.ErrNotFound ErrIterReleased = errors.New("leveldb/memdb: iterator released") @@ -385,7 +386,7 @@ func (p *DB) Find(key []byte) (rkey, value []byte, err error) { } // NewIterator returns an iterator of the DB. -// The returned iterator is not goroutine-safe, but it is safe to use +// The returned iterator is not safe for concurrent use, but it is safe to use // multiple iterators concurrently, with each in a dedicated goroutine. // It is also safe to use an iterator concurrently with modifying its // underlying DB. However, the resultant key/value pairs are not guaranteed @@ -411,7 +412,7 @@ func (p *DB) Capacity() int { } // Size returns sum of keys and values length. Note that deleted -// key/value will not be accouted for, but it will still consume +// key/value will not be accounted for, but it will still consume // the buffer, since the buffer is append only. func (p *DB) Size() int { p.mu.RLock() @@ -453,11 +454,14 @@ func (p *DB) Reset() { p.mu.Unlock() } -// New creates a new initalized in-memory key/value DB. The capacity +// New creates a new initialized in-memory key/value DB. The capacity // is the initial key/value buffer capacity. The capacity is advisory, // not enforced. // -// The returned DB instance is goroutine-safe. +// This DB is append-only, deleting an entry would remove entry node but not +// reclaim KV buffer. +// +// The returned DB instance is safe for concurrent use. func New(cmp comparer.BasicComparer, capacity int) *DB { p := &DB{ cmp: cmp, diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go b/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go index 3d2bf1c02a0..44e7d9adce4 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/opt/options.go @@ -312,6 +312,11 @@ type Options struct { // The default is false. NoSync bool + // NoWriteMerge allows disabling write merge. + // + // The default is false. + NoWriteMerge bool + // OpenFilesCacher provides cache algorithm for open files caching. // Specify NoCacher to disable caching algorithm. // @@ -543,6 +548,13 @@ func (o *Options) GetNoSync() bool { return o.NoSync } +func (o *Options) GetNoWriteMerge() bool { + if o == nil { + return false + } + return o.NoWriteMerge +} + func (o *Options) GetOpenFilesCacher() Cacher { if o == nil || o.OpenFilesCacher == nil { return DefaultOpenFilesCacher @@ -629,6 +641,11 @@ func (ro *ReadOptions) GetStrict(strict Strict) bool { // WriteOptions holds the optional parameters for 'write operation'. The // 'write operation' includes Write, Put and Delete. type WriteOptions struct { + // NoWriteMerge allows disabling write merge. + // + // The default is false. + NoWriteMerge bool + // Sync is whether to sync underlying writes from the OS buffer cache // through to actual disk, if applicable. Setting Sync can result in // slower writes. @@ -644,6 +661,13 @@ type WriteOptions struct { Sync bool } +func (wo *WriteOptions) GetNoWriteMerge() bool { + if wo == nil { + return false + } + return wo.NoWriteMerge +} + func (wo *WriteOptions) GetSync() bool { if wo == nil { return false diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/session.go b/vendor/github.com/syndtr/goleveldb/leveldb/session.go index b0d3fef1d8b..ad68a870390 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/session.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/session.go @@ -18,7 +18,8 @@ import ( "github.com/syndtr/goleveldb/leveldb/storage" ) -// ErrManifestCorrupted records manifest corruption. +// ErrManifestCorrupted records manifest corruption. This error will be +// wrapped with errors.ErrCorrupted. type ErrManifestCorrupted struct { Field string Reason string @@ -42,10 +43,11 @@ type session struct { stSeqNum uint64 // last mem compacted seq; need external synchronization stor storage.Storage - storLock storage.Lock + storLock storage.Locker o *cachedOptions icmp *iComparer tops *tOps + fileRef map[int64]int manifest *journal.Writer manifestWriter storage.Writer @@ -68,6 +70,7 @@ func newSession(stor storage.Storage, o *opt.Options) (s *session, err error) { s = &session{ stor: stor, storLock: storLock, + fileRef: make(map[int64]int), } s.setOptions(o) s.tops = newTableOps(s) @@ -87,12 +90,12 @@ func (s *session) close() { } s.manifest = nil s.manifestWriter = nil - s.stVersion = nil + s.setVersion(&version{s: s, closing: true}) } // Release session lock. func (s *session) release() { - s.storLock.Release() + s.storLock.Unlock() } // Create a new database session; need external synchronization. diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go b/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go index 674182fb265..92328933cc6 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go @@ -39,6 +39,18 @@ func (s *session) newTemp() storage.FileDesc { return storage.FileDesc{storage.TypeTemp, num} } +func (s *session) addFileRef(fd storage.FileDesc, ref int) int { + ref += s.fileRef[fd.Num] + if ref > 0 { + s.fileRef[fd.Num] = ref + } else if ref == 0 { + delete(s.fileRef, fd.Num) + } else { + panic(fmt.Sprintf("negative ref: %v", fd)) + } + return ref +} + // Session state. // Get current version. This will incr version ref, must call @@ -46,21 +58,28 @@ func (s *session) newTemp() storage.FileDesc { func (s *session) version() *version { s.vmu.Lock() defer s.vmu.Unlock() - s.stVersion.ref++ + s.stVersion.incref() return s.stVersion } +func (s *session) tLen(level int) int { + s.vmu.Lock() + defer s.vmu.Unlock() + return s.stVersion.tLen(level) +} + // Set current version to v. func (s *session) setVersion(v *version) { s.vmu.Lock() - v.ref = 1 // Holds by session. - if old := s.stVersion; old != nil { - v.ref++ // Holds by old version. - old.next = v - old.releaseNB() + defer s.vmu.Unlock() + // Hold by session. It is important to call this first before releasing + // current version, otherwise the still used files might get released. + v.incref() + if s.stVersion != nil { + // Release current version. + s.stVersion.releaseNB() } s.stVersion = v - s.vmu.Unlock() } // Get current unused file number. @@ -197,7 +216,7 @@ func (s *session) newManifest(rec *sessionRecord, v *version) (err error) { if s.manifestWriter != nil { s.manifestWriter.Close() } - if !s.manifestFd.Nil() { + if !s.manifestFd.Zero() { s.stor.Remove(s.manifestFd) } s.manifestFd = fd diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go b/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go index cbe1dc10312..1189decac61 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go @@ -32,7 +32,7 @@ type fileStorageLock struct { fs *fileStorage } -func (lock *fileStorageLock) Release() { +func (lock *fileStorageLock) Unlock() { if lock.fs != nil { lock.fs.mu.Lock() defer lock.fs.mu.Unlock() @@ -116,7 +116,7 @@ func OpenFile(path string, readOnly bool) (Storage, error) { return fs, nil } -func (fs *fileStorage) Lock() (Lock, error) { +func (fs *fileStorage) Lock() (Locker, error) { fs.mu.Lock() defer fs.mu.Unlock() if fs.open < 0 { @@ -234,14 +234,30 @@ func (fs *fileStorage) SetMeta(fd FileDesc) (err error) { return } _, err = fmt.Fprintln(w, fsGenName(fd)) - // Close the file first. - if cerr := w.Close(); cerr != nil { - fs.log(fmt.Sprintf("close CURRENT.%d: %v", fd.Num, cerr)) + if err != nil { + fs.log(fmt.Sprintf("write CURRENT.%d: %v", fd.Num, err)) + return + } + if err = w.Sync(); err != nil { + fs.log(fmt.Sprintf("flush CURRENT.%d: %v", fd.Num, err)) + return + } + if err = w.Close(); err != nil { + fs.log(fmt.Sprintf("close CURRENT.%d: %v", fd.Num, err)) + return } if err != nil { return } - return rename(path, filepath.Join(fs.path, "CURRENT")) + if err = rename(path, filepath.Join(fs.path, "CURRENT")); err != nil { + fs.log(fmt.Sprintf("rename CURRENT.%d: %v", fd.Num, err)) + return + } + // Sync root directory. + if err = syncDir(fs.path); err != nil { + fs.log(fmt.Sprintf("syncDir: %v", err)) + } + return } func (fs *fileStorage) GetMeta() (fd FileDesc, err error) { @@ -323,7 +339,7 @@ func (fs *fileStorage) GetMeta() (fd FileDesc, err error) { } } // Don't remove any files if there is no valid CURRENT file. - if fd.Nil() { + if fd.Zero() { if cerr != nil { err = cerr } else { diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go b/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go new file mode 100644 index 00000000000..5545aeef2a8 --- /dev/null +++ b/vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go @@ -0,0 +1,34 @@ +// Copyright (c) 2012, Suryandaru Triandana +// All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// +build nacl + +package storage + +import ( + "os" + "syscall" +) + +func newFileLock(path string, readOnly bool) (fl fileLock, err error) { + return nil, syscall.ENOTSUP +} + +func setFileLock(f *os.File, readOnly, lock bool) error { + return syscall.ENOTSUP +} + +func rename(oldpath, newpath string) error { + return syscall.ENOTSUP +} + +func isErrInvalid(err error) bool { + return false +} + +func syncDir(name string) error { + return syscall.ENOTSUP +} diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go b/vendor/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go index 9b70e151369..9b0421f0355 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/storage/mem_storage.go @@ -18,7 +18,7 @@ type memStorageLock struct { ms *memStorage } -func (lock *memStorageLock) Release() { +func (lock *memStorageLock) Unlock() { ms := lock.ms ms.mu.Lock() defer ms.mu.Unlock() @@ -43,7 +43,7 @@ func NewMemStorage() Storage { } } -func (ms *memStorage) Lock() (Lock, error) { +func (ms *memStorage) Lock() (Locker, error) { ms.mu.Lock() defer ms.mu.Unlock() if ms.slock != nil { @@ -69,7 +69,7 @@ func (ms *memStorage) SetMeta(fd FileDesc) error { func (ms *memStorage) GetMeta() (FileDesc, error) { ms.mu.Lock() defer ms.mu.Unlock() - if ms.meta.Nil() { + if ms.meta.Zero() { return FileDesc{}, os.ErrNotExist } return ms.meta, nil @@ -78,7 +78,7 @@ func (ms *memStorage) GetMeta() (FileDesc, error) { func (ms *memStorage) List(ft FileType) ([]FileDesc, error) { ms.mu.Lock() var fds []FileDesc - for x, _ := range ms.files { + for x := range ms.files { fd := unpackFile(x) if fd.Type&ft != 0 { fds = append(fds, fd) diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/storage/storage.go b/vendor/github.com/syndtr/goleveldb/leveldb/storage/storage.go index 9b30b6727fc..c16bce6b665 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/storage/storage.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/storage/storage.go @@ -11,12 +11,12 @@ import ( "errors" "fmt" "io" - - "github.com/syndtr/goleveldb/leveldb/util" ) +// FileType represent a file type. type FileType int +// File types. const ( TypeManifest FileType = 1 << iota TypeJournal @@ -40,6 +40,7 @@ func (t FileType) String() string { return fmt.Sprintf("", t) } +// Common error. var ( ErrInvalidFile = errors.New("leveldb/storage: invalid file for argument") ErrLocked = errors.New("leveldb/storage: already locked") @@ -55,11 +56,10 @@ type ErrCorrupted struct { } func (e *ErrCorrupted) Error() string { - if !e.Fd.Nil() { + if !e.Fd.Zero() { return fmt.Sprintf("%v [file=%v]", e.Err, e.Fd) - } else { - return e.Err.Error() } + return e.Err.Error() } // Syncer is the interface that wraps basic Sync method. @@ -83,11 +83,12 @@ type Writer interface { Syncer } -type Lock interface { - util.Releaser +// Locker is the interface that wraps Unlock method. +type Locker interface { + Unlock() } -// FileDesc is a file descriptor. +// FileDesc is a 'file descriptor'. type FileDesc struct { Type FileType Num int64 @@ -108,12 +109,12 @@ func (fd FileDesc) String() string { } } -// Nil returns true if fd == (FileDesc{}). -func (fd FileDesc) Nil() bool { +// Zero returns true if fd == (FileDesc{}). +func (fd FileDesc) Zero() bool { return fd == (FileDesc{}) } -// FileDescOk returns true if fd is a valid file descriptor. +// FileDescOk returns true if fd is a valid 'file descriptor'. func FileDescOk(fd FileDesc) bool { switch fd.Type { case TypeManifest: @@ -126,43 +127,44 @@ func FileDescOk(fd FileDesc) bool { return fd.Num >= 0 } -// Storage is the storage. A storage instance must be goroutine-safe. +// Storage is the storage. A storage instance must be safe for concurrent use. type Storage interface { // Lock locks the storage. Any subsequent attempt to call Lock will fail // until the last lock released. - // After use the caller should call the Release method. - Lock() (Lock, error) + // Caller should call Unlock method after use. + Lock() (Locker, error) // Log logs a string. This is used for logging. // An implementation may write to a file, stdout or simply do nothing. Log(str string) - // SetMeta sets to point to the given fd, which then can be acquired using - // GetMeta method. - // SetMeta should be implemented in such way that changes should happened + // SetMeta store 'file descriptor' that can later be acquired using GetMeta + // method. The 'file descriptor' should point to a valid file. + // SetMeta should be implemented in such way that changes should happen // atomically. SetMeta(fd FileDesc) error - // GetManifest returns a manifest file. - // Returns os.ErrNotExist if meta doesn't point to any fd, or point to fd - // that doesn't exist. + // GetMeta returns 'file descriptor' stored in meta. The 'file descriptor' + // can be updated using SetMeta method. + // Returns os.ErrNotExist if meta doesn't store any 'file descriptor', or + // 'file descriptor' point to nonexistent file. GetMeta() (FileDesc, error) - // List returns fds that match the given file types. + // List returns file descriptors that match the given file types. // The file types may be OR'ed together. List(ft FileType) ([]FileDesc, error) - // Open opens file with the given fd read-only. + // Open opens file with the given 'file descriptor' read-only. // Returns os.ErrNotExist error if the file does not exist. // Returns ErrClosed if the underlying storage is closed. Open(fd FileDesc) (Reader, error) - // Create creates file with the given fd, truncate if already exist and - // opens write-only. + // Create creates file with the given 'file descriptor', truncate if already + // exist and opens write-only. // Returns ErrClosed if the underlying storage is closed. Create(fd FileDesc) (Writer, error) - // Remove removes file with the given fd. + // Remove removes file with the given 'file descriptor'. // Returns ErrClosed if the underlying storage is closed. Remove(fd FileDesc) error diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/table.go b/vendor/github.com/syndtr/goleveldb/leveldb/table.go index 310ba6c2299..81d18a531e0 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/table.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/table.go @@ -434,7 +434,7 @@ func (t *tOps) close() { t.bpool.Close() t.cache.Close() if t.bcache != nil { - t.bcache.Close() + t.bcache.CloseWeak() } } diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/table/reader.go b/vendor/github.com/syndtr/goleveldb/leveldb/table/reader.go index ae61bece937..16cfbaa0068 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/table/reader.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/table/reader.go @@ -26,12 +26,15 @@ import ( "github.com/syndtr/goleveldb/leveldb/util" ) +// Reader errors. var ( ErrNotFound = errors.ErrNotFound ErrReaderReleased = errors.New("leveldb/table: reader released") ErrIterReleased = errors.New("leveldb/table: iterator released") ) +// ErrCorrupted describes error due to corruption. This error will be wrapped +// with errors.ErrCorrupted. type ErrCorrupted struct { Pos int64 Size int64 @@ -61,7 +64,7 @@ type block struct { func (b *block) seek(cmp comparer.Comparer, rstart, rlimit int, key []byte) (index, offset int, err error) { index = sort.Search(b.restartsLen-rstart-(b.restartsLen-rlimit), func(i int) bool { offset := int(binary.LittleEndian.Uint32(b.data[b.restartsOffset+4*(rstart+i):])) - offset += 1 // shared always zero, since this is a restart point + offset++ // shared always zero, since this is a restart point v1, n1 := binary.Uvarint(b.data[offset:]) // key length _, n2 := binary.Uvarint(b.data[offset+n1:]) // value length m := offset + n1 + n2 @@ -356,7 +359,7 @@ func (i *blockIter) Prev() bool { i.value = nil offset := i.block.restartOffset(ri) if offset == i.offset { - ri -= 1 + ri-- if ri < 0 { i.dir = dirSOI return false @@ -578,6 +581,7 @@ func (r *Reader) readRawBlock(bh blockHandle, verifyChecksum bool) ([]byte, erro case blockTypeSnappyCompression: decLen, err := snappy.DecodedLen(data[:bh.length]) if err != nil { + r.bpool.Put(data) return nil, r.newErrCorruptedBH(bh, err.Error()) } decData := r.bpool.Get(decLen) @@ -783,8 +787,8 @@ func (r *Reader) getDataIterErr(dataBH blockHandle, slice *util.Range, verifyChe // table. And a nil Range.Limit is treated as a key after all keys in // the table. // -// The returned iterator is not goroutine-safe and should be released -// when not used. +// The returned iterator is not safe for concurrent use and should be released +// after use. // // Also read Iterator documentation of the leveldb/iterator package. func (r *Reader) NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator { @@ -826,18 +830,21 @@ func (r *Reader) find(key []byte, filtered bool, ro *opt.ReadOptions, noValue bo index := r.newBlockIter(indexBlock, nil, nil, true) defer index.Release() + if !index.Seek(key) { - err = index.Error() - if err == nil { + if err = index.Error(); err == nil { err = ErrNotFound } return } + dataBH, n := decodeBlockHandle(index.Value()) if n == 0 { r.err = r.newErrCorruptedBH(r.indexBH, "bad data block handle") - return + return nil, nil, r.err } + + // The filter should only used for exact match. if filtered && r.filter != nil { filterBlock, frel, ferr := r.getFilterBlock(true) if ferr == nil { @@ -847,30 +854,53 @@ func (r *Reader) find(key []byte, filtered bool, ro *opt.ReadOptions, noValue bo } frel.Release() } else if !errors.IsCorrupted(ferr) { - err = ferr - return + return nil, nil, ferr } } + data := r.getDataIter(dataBH, nil, r.verifyChecksum, !ro.GetDontFillCache()) - defer data.Release() if !data.Seek(key) { - err = data.Error() - if err == nil { - err = ErrNotFound + data.Release() + if err = data.Error(); err != nil { + return + } + + // The nearest greater-than key is the first key of the next block. + if !index.Next() { + if err = index.Error(); err == nil { + err = ErrNotFound + } + return + } + + dataBH, n = decodeBlockHandle(index.Value()) + if n == 0 { + r.err = r.newErrCorruptedBH(r.indexBH, "bad data block handle") + return nil, nil, r.err + } + + data = r.getDataIter(dataBH, nil, r.verifyChecksum, !ro.GetDontFillCache()) + if !data.Next() { + data.Release() + if err = data.Error(); err == nil { + err = ErrNotFound + } + return } - return } - // Don't use block buffer, no need to copy the buffer. + + // Key doesn't use block buffer, no need to copy the buffer. rkey = data.Key() if !noValue { if r.bpool == nil { value = data.Value() } else { - // Use block buffer, and since the buffer will be recycled, the buffer - // need to be copied. + // Value does use block buffer, and since the buffer will be + // recycled, it need to be copied. value = append([]byte{}, data.Value()...) } } + data.Release() return } @@ -888,7 +918,7 @@ func (r *Reader) Find(key []byte, filtered bool, ro *opt.ReadOptions) (rkey, val return r.find(key, filtered, ro, false) } -// Find finds key that is greater than or equal to the given key. +// FindKey finds key that is greater than or equal to the given key. // It returns ErrNotFound if the table doesn't contain such key. // If filtered is true then the nearest 'block' will be checked against // 'filter data' (if present) and will immediately return ErrNotFound if @@ -987,7 +1017,7 @@ func (r *Reader) Release() { // NewReader creates a new initialized table reader for the file. // The fi, cache and bpool is optional and can be nil. // -// The returned table reader instance is goroutine-safe. +// The returned table reader instance is safe for concurrent use. func NewReader(f io.ReaderAt, size int64, fd storage.FileDesc, cache *cache.NamespaceGetter, bpool *util.BufferPool, o *opt.Options) (*Reader, error) { if f == nil { return nil, errors.New("leveldb/table: nil file") @@ -1039,9 +1069,8 @@ func NewReader(f io.ReaderAt, size int64, fd storage.FileDesc, cache *cache.Name if errors.IsCorrupted(err) { r.err = err return r, nil - } else { - return nil, err } + return nil, err } // Set data end. @@ -1086,9 +1115,8 @@ func NewReader(f io.ReaderAt, size int64, fd storage.FileDesc, cache *cache.Name if errors.IsCorrupted(err) { r.err = err return r, nil - } else { - return nil, err } + return nil, err } if r.filter != nil { r.filterBlock, err = r.readFilterBlock(r.filterBH) diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/table/writer.go b/vendor/github.com/syndtr/goleveldb/leveldb/table/writer.go index 274dee6da85..b96b271d8dd 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/table/writer.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/table/writer.go @@ -349,7 +349,7 @@ func (w *Writer) Close() error { // NewWriter creates a new initialized table writer for the file. // -// Table writer is not goroutine-safe. +// Table writer is not safe for concurrent use. func NewWriter(f io.Writer, o *opt.Options) *Writer { w := &Writer{ writer: f, diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/util.go b/vendor/github.com/syndtr/goleveldb/leveldb/util.go index 3b663d1cca3..e572a329e94 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/util.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/util.go @@ -89,3 +89,10 @@ func (p fdSorter) Swap(i, j int) { func sortFds(fds []storage.FileDesc) { sort.Sort(fdSorter(fds)) } + +func ensureBuffer(b []byte, n int) []byte { + if cap(b) < n { + return make([]byte, n) + } + return b[:n] +} diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/version.go b/vendor/github.com/syndtr/goleveldb/leveldb/version.go index d274eeff211..73f272af5ff 100644 --- a/vendor/github.com/syndtr/goleveldb/leveldb/version.go +++ b/vendor/github.com/syndtr/goleveldb/leveldb/version.go @@ -34,43 +34,48 @@ type version struct { cSeek unsafe.Pointer - ref int - // Succeeding version. - next *version + closing bool + ref int + released bool } func newVersion(s *session) *version { return &version{s: s} } +func (v *version) incref() { + if v.released { + panic("already released") + } + + v.ref++ + if v.ref == 1 { + // Incr file ref. + for _, tt := range v.levels { + for _, t := range tt { + v.s.addFileRef(t.fd, 1) + } + } + } +} + func (v *version) releaseNB() { v.ref-- if v.ref > 0 { return - } - if v.ref < 0 { + } else if v.ref < 0 { panic("negative version ref") } - nextTables := make(map[int64]bool) - for _, tt := range v.next.levels { - for _, t := range tt { - num := t.fd.Num - nextTables[num] = true - } - } - for _, tt := range v.levels { for _, t := range tt { - num := t.fd.Num - if _, ok := nextTables[num]; !ok { + if v.s.addFileRef(t.fd, -1) == 0 { v.s.tops.remove(t) } } } - v.next.releaseNB() - v.next = nil + v.released = true } func (v *version) release() { @@ -131,6 +136,10 @@ func (v *version) walkOverlapping(aux tFiles, ikey internalKey, f func(level int } func (v *version) get(aux tFiles, ikey internalKey, ro *opt.ReadOptions, noValue bool) (value []byte, tcomp bool, err error) { + if v.closing { + return nil, false, ErrClosed + } + ukey := ikey.ukey() var ( diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS new file mode 100644 index 00000000000..2b00ddba0df --- /dev/null +++ b/vendor/golang.org/x/crypto/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS new file mode 100644 index 00000000000..1fbd3e976fa --- /dev/null +++ b/vendor/golang.org/x/crypto/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go index c02b4d5a70e..593f6530084 100644 --- a/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go +++ b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go @@ -16,7 +16,7 @@ Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To choose, you can pass the `New` functions from the different SHA packages to pbkdf2.Key. */ -package pbkdf2 +package pbkdf2 // import "golang.org/x/crypto/pbkdf2" import ( "crypto/hmac" diff --git a/vendor/golang.org/x/crypto/ripemd160/ripemd160.go b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go index da690f0b92f..6c6e84236ab 100644 --- a/vendor/golang.org/x/crypto/ripemd160/ripemd160.go +++ b/vendor/golang.org/x/crypto/ripemd160/ripemd160.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package ripemd160 implements the RIPEMD-160 hash algorithm. -package ripemd160 +package ripemd160 // import "golang.org/x/crypto/ripemd160" // RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart // Preneel with specifications available at: diff --git a/vendor/golang.org/x/crypto/scrypt/scrypt.go b/vendor/golang.org/x/crypto/scrypt/scrypt.go index 30737b0a626..ff28aaef6ff 100644 --- a/vendor/golang.org/x/crypto/scrypt/scrypt.go +++ b/vendor/golang.org/x/crypto/scrypt/scrypt.go @@ -4,8 +4,8 @@ // Package scrypt implements the scrypt key derivation function as defined in // Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard -// Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf). -package scrypt +// Functions" (https://www.tarsnap.com/scrypt/scrypt.pdf). +package scrypt // import "golang.org/x/crypto/scrypt" import ( "crypto/sha256" @@ -218,11 +218,12 @@ func smix(b []byte, r, N int, v, xy []uint32) { // For example, you can get a derived key for e.g. AES-256 (which needs a // 32-byte key) by doing: // -// dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) +// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) // -// The recommended parameters for interactive logins as of 2009 are N=16384, -// r=8, p=1. They should be increased as memory latency and CPU parallelism -// increases. Remember to get a good random salt. +// The recommended parameters for interactive logins as of 2017 are N=32768, r=8 +// and p=1. The parameters N, r, and p should be increased as memory latency and +// CPU parallelism increases; consider setting N to the highest power of 2 you +// can derive within 100 milliseconds. Remember to get a good random salt. func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { if N <= 1 || N&(N-1) != 0 { return nil, errors.New("scrypt: N must be > 1 and a power of 2") diff --git a/vendor/golang.org/x/net/.gitattributes b/vendor/golang.org/x/net/.gitattributes deleted file mode 100644 index d2f212e5da8..00000000000 --- a/vendor/golang.org/x/net/.gitattributes +++ /dev/null @@ -1,10 +0,0 @@ -# Treat all files in this repo as binary, with no git magic updating -# line endings. Windows users contributing to Go will need to use a -# modern version of git and editors capable of LF line endings. -# -# We'll prevent accidental CRLF line endings from entering the repo -# via the git-review gofmt checks. -# -# See golang.org/issue/9281 - -* -text diff --git a/vendor/golang.org/x/net/.gitignore b/vendor/golang.org/x/net/.gitignore deleted file mode 100644 index 8339fd61d3f..00000000000 --- a/vendor/golang.org/x/net/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Add no patterns to .hgignore except for files generated by the build. -last-change diff --git a/vendor/golang.org/x/net/CONTRIBUTING.md b/vendor/golang.org/x/net/CONTRIBUTING.md deleted file mode 100644 index 88dff59bc7d..00000000000 --- a/vendor/golang.org/x/net/CONTRIBUTING.md +++ /dev/null @@ -1,31 +0,0 @@ -# Contributing to Go - -Go is an open source project. - -It is the work of hundreds of contributors. We appreciate your help! - - -## Filing issues - -When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: - -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? - -General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. -The gophers there will answer or ask you to file an issue if you've tripped over a bug. - -## Contributing code - -Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) -before sending patches. - -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - -Unless otherwise noted, the Go source files are distributed under -the BSD-style license found in the LICENSE file. - diff --git a/vendor/golang.org/x/net/README b/vendor/golang.org/x/net/README deleted file mode 100644 index 6b13d8e5050..00000000000 --- a/vendor/golang.org/x/net/README +++ /dev/null @@ -1,3 +0,0 @@ -This repository holds supplementary Go networking libraries. - -To submit changes to this repository, see http://golang.org/doc/contribute.html. diff --git a/vendor/golang.org/x/net/bpf/asm.go b/vendor/golang.org/x/net/bpf/asm.go deleted file mode 100644 index 15e21b18122..00000000000 --- a/vendor/golang.org/x/net/bpf/asm.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 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 bpf - -import "fmt" - -// Assemble converts insts into raw instructions suitable for loading -// into a BPF virtual machine. -// -// Currently, no optimization is attempted, the assembled program flow -// is exactly as provided. -func Assemble(insts []Instruction) ([]RawInstruction, error) { - ret := make([]RawInstruction, len(insts)) - var err error - for i, inst := range insts { - ret[i], err = inst.Assemble() - if err != nil { - return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err) - } - } - return ret, nil -} - -// Disassemble attempts to parse raw back into -// Instructions. Unrecognized RawInstructions are assumed to be an -// extension not implemented by this package, and are passed through -// unchanged to the output. The allDecoded value reports whether insts -// contains no RawInstructions. -func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) { - insts = make([]Instruction, len(raw)) - allDecoded = true - for i, r := range raw { - insts[i] = r.Disassemble() - if _, ok := insts[i].(RawInstruction); ok { - allDecoded = false - } - } - return insts, allDecoded -} diff --git a/vendor/golang.org/x/net/bpf/constants.go b/vendor/golang.org/x/net/bpf/constants.go deleted file mode 100644 index ccf6adafbf7..00000000000 --- a/vendor/golang.org/x/net/bpf/constants.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2016 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 bpf - -// A Register is a register of the BPF virtual machine. -type Register uint16 - -const ( - // RegA is the accumulator register. RegA is always the - // destination register of ALU operations. - RegA Register = iota - // RegX is the indirection register, used by LoadIndirect - // operations. - RegX -) - -// An ALUOp is an arithmetic or logic operation. -type ALUOp uint16 - -// ALU binary operation types. -const ( - ALUOpAdd ALUOp = iota << 4 - ALUOpSub - ALUOpMul - ALUOpDiv - ALUOpOr - ALUOpAnd - ALUOpShiftLeft - ALUOpShiftRight - aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type. - ALUOpMod - ALUOpXor -) - -// A JumpTest is a comparison operator used in conditional jumps. -type JumpTest uint16 - -// Supported operators for conditional jumps. -const ( - // K == A - JumpEqual JumpTest = iota - // K != A - JumpNotEqual - // K > A - JumpGreaterThan - // K < A - JumpLessThan - // K >= A - JumpGreaterOrEqual - // K <= A - JumpLessOrEqual - // K & A != 0 - JumpBitsSet - // K & A == 0 - JumpBitsNotSet -) - -// An Extension is a function call provided by the kernel that -// performs advanced operations that are expensive or impossible -// within the BPF virtual machine. -// -// Extensions are only implemented by the Linux kernel. -// -// TODO: should we prune this list? Some of these extensions seem -// either broken or near-impossible to use correctly, whereas other -// (len, random, ifindex) are quite useful. -type Extension int - -// Extension functions available in the Linux kernel. -const ( - // extOffset is the negative maximum number of instructions used - // to load instructions by overloading the K argument. - extOffset = -0x1000 - // ExtLen returns the length of the packet. - ExtLen Extension = 1 - // ExtProto returns the packet's L3 protocol type. - ExtProto = 0 - // ExtType returns the packet's type (skb->pkt_type in the kernel) - // - // TODO: better documentation. How nice an API do we want to - // provide for these esoteric extensions? - ExtType = 4 - // ExtPayloadOffset returns the offset of the packet payload, or - // the first protocol header that the kernel does not know how to - // parse. - ExtPayloadOffset = 52 - // ExtInterfaceIndex returns the index of the interface on which - // the packet was received. - ExtInterfaceIndex = 8 - // ExtNetlinkAttr returns the netlink attribute of type X at - // offset A. - ExtNetlinkAttr = 12 - // ExtNetlinkAttrNested returns the nested netlink attribute of - // type X at offset A. - ExtNetlinkAttrNested = 16 - // ExtMark returns the packet's mark value. - ExtMark = 20 - // ExtQueue returns the packet's assigned hardware queue. - ExtQueue = 24 - // ExtLinkLayerType returns the packet's hardware address type - // (e.g. Ethernet, Infiniband). - ExtLinkLayerType = 28 - // ExtRXHash returns the packets receive hash. - // - // TODO: figure out what this rxhash actually is. - ExtRXHash = 32 - // ExtCPUID returns the ID of the CPU processing the current - // packet. - ExtCPUID = 36 - // ExtVLANTag returns the packet's VLAN tag. - ExtVLANTag = 44 - // ExtVLANTagPresent returns non-zero if the packet has a VLAN - // tag. - // - // TODO: I think this might be a lie: it reads bit 0x1000 of the - // VLAN header, which changed meaning in recent revisions of the - // spec - this extension may now return meaningless information. - ExtVLANTagPresent = 48 - // ExtVLANProto returns 0x8100 if the frame has a VLAN header, - // 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some - // other value if no VLAN information is present. - ExtVLANProto = 60 - // ExtRand returns a uniformly random uint32. - ExtRand = 56 -) - -// The following gives names to various bit patterns used in opcode construction. - -const ( - opMaskCls uint16 = 0x7 - // opClsLoad masks - opMaskLoadDest = 0x01 - opMaskLoadWidth = 0x18 - opMaskLoadMode = 0xe0 - // opClsALU - opMaskOperandSrc = 0x08 - opMaskOperator = 0xf0 - // opClsJump - opMaskJumpConst = 0x0f - opMaskJumpCond = 0xf0 -) - -const ( - // +---------------+-----------------+---+---+---+ - // | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 | - // +---------------+-----------------+---+---+---+ - opClsLoadA uint16 = iota - // +---------------+-----------------+---+---+---+ - // | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 | - // +---------------+-----------------+---+---+---+ - opClsLoadX - // +---+---+---+---+---+---+---+---+ - // | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | - // +---+---+---+---+---+---+---+---+ - opClsStoreA - // +---+---+---+---+---+---+---+---+ - // | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | - // +---+---+---+---+---+---+---+---+ - opClsStoreX - // +---------------+-----------------+---+---+---+ - // | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 | - // +---------------+-----------------+---+---+---+ - opClsALU - // +-----------------------------+---+---+---+---+ - // | TestOperator (4b) | 0 | 1 | 0 | 1 | - // +-----------------------------+---+---+---+---+ - opClsJump - // +---+-------------------------+---+---+---+---+ - // | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 | - // +---+-------------------------+---+---+---+---+ - opClsReturn - // +---+-------------------------+---+---+---+---+ - // | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 | - // +---+-------------------------+---+---+---+---+ - opClsMisc -) - -const ( - opAddrModeImmediate uint16 = iota << 5 - opAddrModeAbsolute - opAddrModeIndirect - opAddrModeScratch - opAddrModePacketLen // actually an extension, not an addressing mode. - opAddrModeMemShift -) - -const ( - opLoadWidth4 uint16 = iota << 3 - opLoadWidth2 - opLoadWidth1 -) - -// Operator defined by ALUOp* - -const ( - opALUSrcConstant uint16 = iota << 3 - opALUSrcX -) - -const ( - opJumpAlways = iota << 4 - opJumpEqual - opJumpGT - opJumpGE - opJumpSet -) - -const ( - opRetSrcConstant uint16 = iota << 4 - opRetSrcA -) - -const ( - opMiscTAX = 0x00 - opMiscTXA = 0x80 -) diff --git a/vendor/golang.org/x/net/bpf/doc.go b/vendor/golang.org/x/net/bpf/doc.go deleted file mode 100644 index ae62feb5341..00000000000 --- a/vendor/golang.org/x/net/bpf/doc.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2016 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 bpf implements marshaling and unmarshaling of programs for the -Berkeley Packet Filter virtual machine, and provides a Go implementation -of the virtual machine. - -BPF's main use is to specify a packet filter for network taps, so that -the kernel doesn't have to expensively copy every packet it sees to -userspace. However, it's been repurposed to other areas where running -user code in-kernel is needed. For example, Linux's seccomp uses BPF -to apply security policies to system calls. For simplicity, this -documentation refers only to packets, but other uses of BPF have their -own data payloads. - -BPF programs run in a restricted virtual machine. It has almost no -access to kernel functions, and while conditional branches are -allowed, they can only jump forwards, to guarantee that there are no -infinite loops. - -The virtual machine - -The BPF VM is an accumulator machine. Its main register, called -register A, is an implicit source and destination in all arithmetic -and logic operations. The machine also has 16 scratch registers for -temporary storage, and an indirection register (register X) for -indirect memory access. All registers are 32 bits wide. - -Each run of a BPF program is given one packet, which is placed in the -VM's read-only "main memory". LoadAbsolute and LoadIndirect -instructions can fetch up to 32 bits at a time into register A for -examination. - -The goal of a BPF program is to produce and return a verdict (uint32), -which tells the kernel what to do with the packet. In the context of -packet filtering, the returned value is the number of bytes of the -packet to forward to userspace, or 0 to ignore the packet. Other -contexts like seccomp define their own return values. - -In order to simplify programs, attempts to read past the end of the -packet terminate the program execution with a verdict of 0 (ignore -packet). This means that the vast majority of BPF programs don't need -to do any explicit bounds checking. - -In addition to the bytes of the packet, some BPF programs have access -to extensions, which are essentially calls to kernel utility -functions. Currently, the only extensions supported by this package -are the Linux packet filter extensions. - -Examples - -This packet filter selects all ARP packets. - - bpf.Assemble([]bpf.Instruction{ - // Load "EtherType" field from the ethernet header. - bpf.LoadAbsolute{Off: 12, Size: 2}, - // Skip over the next instruction if EtherType is not ARP. - bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1}, - // Verdict is "send up to 4k of the packet to userspace." - bpf.RetConstant{Val: 4096}, - // Verdict is "ignore packet." - bpf.RetConstant{Val: 0}, - }) - -This packet filter captures a random 1% sample of traffic. - - bpf.Assemble([]bpf.Instruction{ - // Get a 32-bit random number from the Linux kernel. - bpf.LoadExtension{Num: bpf.ExtRand}, - // 1% dice roll? - bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1}, - // Capture. - bpf.RetConstant{Val: 4096}, - // Ignore. - bpf.RetConstant{Val: 0}, - }) - -*/ -package bpf // import "golang.org/x/net/bpf" diff --git a/vendor/golang.org/x/net/bpf/instructions.go b/vendor/golang.org/x/net/bpf/instructions.go deleted file mode 100644 index 3b4fd089166..00000000000 --- a/vendor/golang.org/x/net/bpf/instructions.go +++ /dev/null @@ -1,704 +0,0 @@ -// Copyright 2016 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 bpf - -import "fmt" - -// An Instruction is one instruction executed by the BPF virtual -// machine. -type Instruction interface { - // Assemble assembles the Instruction into a RawInstruction. - Assemble() (RawInstruction, error) -} - -// A RawInstruction is a raw BPF virtual machine instruction. -type RawInstruction struct { - // Operation to execute. - Op uint16 - // For conditional jump instructions, the number of instructions - // to skip if the condition is true/false. - Jt uint8 - Jf uint8 - // Constant parameter. The meaning depends on the Op. - K uint32 -} - -// Assemble implements the Instruction Assemble method. -func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil } - -// Disassemble parses ri into an Instruction and returns it. If ri is -// not recognized by this package, ri itself is returned. -func (ri RawInstruction) Disassemble() Instruction { - switch ri.Op & opMaskCls { - case opClsLoadA, opClsLoadX: - reg := Register(ri.Op & opMaskLoadDest) - sz := 0 - switch ri.Op & opMaskLoadWidth { - case opLoadWidth4: - sz = 4 - case opLoadWidth2: - sz = 2 - case opLoadWidth1: - sz = 1 - default: - return ri - } - switch ri.Op & opMaskLoadMode { - case opAddrModeImmediate: - if sz != 4 { - return ri - } - return LoadConstant{Dst: reg, Val: ri.K} - case opAddrModeScratch: - if sz != 4 || ri.K > 15 { - return ri - } - return LoadScratch{Dst: reg, N: int(ri.K)} - case opAddrModeAbsolute: - if ri.K > extOffset+0xffffffff { - return LoadExtension{Num: Extension(-extOffset + ri.K)} - } - return LoadAbsolute{Size: sz, Off: ri.K} - case opAddrModeIndirect: - return LoadIndirect{Size: sz, Off: ri.K} - case opAddrModePacketLen: - if sz != 4 { - return ri - } - return LoadExtension{Num: ExtLen} - case opAddrModeMemShift: - return LoadMemShift{Off: ri.K} - default: - return ri - } - - case opClsStoreA: - if ri.Op != opClsStoreA || ri.K > 15 { - return ri - } - return StoreScratch{Src: RegA, N: int(ri.K)} - - case opClsStoreX: - if ri.Op != opClsStoreX || ri.K > 15 { - return ri - } - return StoreScratch{Src: RegX, N: int(ri.K)} - - case opClsALU: - switch op := ALUOp(ri.Op & opMaskOperator); op { - case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor: - if ri.Op&opMaskOperandSrc != 0 { - return ALUOpX{Op: op} - } - return ALUOpConstant{Op: op, Val: ri.K} - case aluOpNeg: - return NegateA{} - default: - return ri - } - - case opClsJump: - if ri.Op&opMaskJumpConst != opClsJump { - return ri - } - switch ri.Op & opMaskJumpCond { - case opJumpAlways: - return Jump{Skip: ri.K} - case opJumpEqual: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpNotEqual, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpEqual, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpGT: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpLessOrEqual, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpGreaterThan, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpGE: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpLessThan, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpGreaterOrEqual, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpSet: - return JumpIf{ - Cond: JumpBitsSet, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - default: - return ri - } - - case opClsReturn: - switch ri.Op { - case opClsReturn | opRetSrcA: - return RetA{} - case opClsReturn | opRetSrcConstant: - return RetConstant{Val: ri.K} - default: - return ri - } - - case opClsMisc: - switch ri.Op { - case opClsMisc | opMiscTAX: - return TAX{} - case opClsMisc | opMiscTXA: - return TXA{} - default: - return ri - } - - default: - panic("unreachable") // switch is exhaustive on the bit pattern - } -} - -// LoadConstant loads Val into register Dst. -type LoadConstant struct { - Dst Register - Val uint32 -} - -// Assemble implements the Instruction Assemble method. -func (a LoadConstant) Assemble() (RawInstruction, error) { - return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val) -} - -// String returns the the instruction in assembler notation. -func (a LoadConstant) String() string { - switch a.Dst { - case RegA: - return fmt.Sprintf("ld #%d", a.Val) - case RegX: - return fmt.Sprintf("ldx #%d", a.Val) - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// LoadScratch loads scratch[N] into register Dst. -type LoadScratch struct { - Dst Register - N int // 0-15 -} - -// Assemble implements the Instruction Assemble method. -func (a LoadScratch) Assemble() (RawInstruction, error) { - if a.N < 0 || a.N > 15 { - return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N) - } - return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N)) -} - -// String returns the the instruction in assembler notation. -func (a LoadScratch) String() string { - switch a.Dst { - case RegA: - return fmt.Sprintf("ld M[%d]", a.N) - case RegX: - return fmt.Sprintf("ldx M[%d]", a.N) - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// LoadAbsolute loads packet[Off:Off+Size] as an integer value into -// register A. -type LoadAbsolute struct { - Off uint32 - Size int // 1, 2 or 4 -} - -// Assemble implements the Instruction Assemble method. -func (a LoadAbsolute) Assemble() (RawInstruction, error) { - return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off) -} - -// String returns the the instruction in assembler notation. -func (a LoadAbsolute) String() string { - switch a.Size { - case 1: // byte - return fmt.Sprintf("ldb [%d]", a.Off) - case 2: // half word - return fmt.Sprintf("ldh [%d]", a.Off) - case 4: // word - if a.Off > extOffset+0xffffffff { - return LoadExtension{Num: Extension(a.Off + 0x1000)}.String() - } - return fmt.Sprintf("ld [%d]", a.Off) - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value -// into register A. -type LoadIndirect struct { - Off uint32 - Size int // 1, 2 or 4 -} - -// Assemble implements the Instruction Assemble method. -func (a LoadIndirect) Assemble() (RawInstruction, error) { - return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off) -} - -// String returns the the instruction in assembler notation. -func (a LoadIndirect) String() string { - switch a.Size { - case 1: // byte - return fmt.Sprintf("ldb [x + %d]", a.Off) - case 2: // half word - return fmt.Sprintf("ldh [x + %d]", a.Off) - case 4: // word - return fmt.Sprintf("ld [x + %d]", a.Off) - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// LoadMemShift multiplies the first 4 bits of the byte at packet[Off] -// by 4 and stores the result in register X. -// -// This instruction is mainly useful to load into X the length of an -// IPv4 packet header in a single instruction, rather than have to do -// the arithmetic on the header's first byte by hand. -type LoadMemShift struct { - Off uint32 -} - -// Assemble implements the Instruction Assemble method. -func (a LoadMemShift) Assemble() (RawInstruction, error) { - return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off) -} - -// String returns the the instruction in assembler notation. -func (a LoadMemShift) String() string { - return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off) -} - -// LoadExtension invokes a linux-specific extension and stores the -// result in register A. -type LoadExtension struct { - Num Extension -} - -// Assemble implements the Instruction Assemble method. -func (a LoadExtension) Assemble() (RawInstruction, error) { - if a.Num == ExtLen { - return assembleLoad(RegA, 4, opAddrModePacketLen, 0) - } - return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num)) -} - -// String returns the the instruction in assembler notation. -func (a LoadExtension) String() string { - switch a.Num { - case ExtLen: - return "ld #len" - case ExtProto: - return "ld #proto" - case ExtType: - return "ld #type" - case ExtPayloadOffset: - return "ld #poff" - case ExtInterfaceIndex: - return "ld #ifidx" - case ExtNetlinkAttr: - return "ld #nla" - case ExtNetlinkAttrNested: - return "ld #nlan" - case ExtMark: - return "ld #mark" - case ExtQueue: - return "ld #queue" - case ExtLinkLayerType: - return "ld #hatype" - case ExtRXHash: - return "ld #rxhash" - case ExtCPUID: - return "ld #cpu" - case ExtVLANTag: - return "ld #vlan_tci" - case ExtVLANTagPresent: - return "ld #vlan_avail" - case ExtVLANProto: - return "ld #vlan_tpid" - case ExtRand: - return "ld #rand" - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// StoreScratch stores register Src into scratch[N]. -type StoreScratch struct { - Src Register - N int // 0-15 -} - -// Assemble implements the Instruction Assemble method. -func (a StoreScratch) Assemble() (RawInstruction, error) { - if a.N < 0 || a.N > 15 { - return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N) - } - var op uint16 - switch a.Src { - case RegA: - op = opClsStoreA - case RegX: - op = opClsStoreX - default: - return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src) - } - - return RawInstruction{ - Op: op, - K: uint32(a.N), - }, nil -} - -// String returns the the instruction in assembler notation. -func (a StoreScratch) String() string { - switch a.Src { - case RegA: - return fmt.Sprintf("st M[%d]", a.N) - case RegX: - return fmt.Sprintf("stx M[%d]", a.N) - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// ALUOpConstant executes A = A Val. -type ALUOpConstant struct { - Op ALUOp - Val uint32 -} - -// Assemble implements the Instruction Assemble method. -func (a ALUOpConstant) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsALU | opALUSrcConstant | uint16(a.Op), - K: a.Val, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a ALUOpConstant) String() string { - switch a.Op { - case ALUOpAdd: - return fmt.Sprintf("add #%d", a.Val) - case ALUOpSub: - return fmt.Sprintf("sub #%d", a.Val) - case ALUOpMul: - return fmt.Sprintf("mul #%d", a.Val) - case ALUOpDiv: - return fmt.Sprintf("div #%d", a.Val) - case ALUOpMod: - return fmt.Sprintf("mod #%d", a.Val) - case ALUOpAnd: - return fmt.Sprintf("and #%d", a.Val) - case ALUOpOr: - return fmt.Sprintf("or #%d", a.Val) - case ALUOpXor: - return fmt.Sprintf("xor #%d", a.Val) - case ALUOpShiftLeft: - return fmt.Sprintf("lsh #%d", a.Val) - case ALUOpShiftRight: - return fmt.Sprintf("rsh #%d", a.Val) - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// ALUOpX executes A = A X -type ALUOpX struct { - Op ALUOp -} - -// Assemble implements the Instruction Assemble method. -func (a ALUOpX) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsALU | opALUSrcX | uint16(a.Op), - }, nil -} - -// String returns the the instruction in assembler notation. -func (a ALUOpX) String() string { - switch a.Op { - case ALUOpAdd: - return "add x" - case ALUOpSub: - return "sub x" - case ALUOpMul: - return "mul x" - case ALUOpDiv: - return "div x" - case ALUOpMod: - return "mod x" - case ALUOpAnd: - return "and x" - case ALUOpOr: - return "or x" - case ALUOpXor: - return "xor x" - case ALUOpShiftLeft: - return "lsh x" - case ALUOpShiftRight: - return "rsh x" - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -// NegateA executes A = -A. -type NegateA struct{} - -// Assemble implements the Instruction Assemble method. -func (a NegateA) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsALU | uint16(aluOpNeg), - }, nil -} - -// String returns the the instruction in assembler notation. -func (a NegateA) String() string { - return fmt.Sprintf("neg") -} - -// Jump skips the following Skip instructions in the program. -type Jump struct { - Skip uint32 -} - -// Assemble implements the Instruction Assemble method. -func (a Jump) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsJump | opJumpAlways, - K: a.Skip, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a Jump) String() string { - return fmt.Sprintf("ja %d", a.Skip) -} - -// JumpIf skips the following Skip instructions in the program if A -// Val is true. -type JumpIf struct { - Cond JumpTest - Val uint32 - SkipTrue uint8 - SkipFalse uint8 -} - -// Assemble implements the Instruction Assemble method. -func (a JumpIf) Assemble() (RawInstruction, error) { - var ( - cond uint16 - flip bool - ) - switch a.Cond { - case JumpEqual: - cond = opJumpEqual - case JumpNotEqual: - cond, flip = opJumpEqual, true - case JumpGreaterThan: - cond = opJumpGT - case JumpLessThan: - cond, flip = opJumpGE, true - case JumpGreaterOrEqual: - cond = opJumpGE - case JumpLessOrEqual: - cond, flip = opJumpGT, true - case JumpBitsSet: - cond = opJumpSet - case JumpBitsNotSet: - cond, flip = opJumpSet, true - default: - return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond) - } - jt, jf := a.SkipTrue, a.SkipFalse - if flip { - jt, jf = jf, jt - } - return RawInstruction{ - Op: opClsJump | cond, - Jt: jt, - Jf: jf, - K: a.Val, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a JumpIf) String() string { - switch a.Cond { - // K == A - case JumpEqual: - return conditionalJump(a, "jeq", "jneq") - // K != A - case JumpNotEqual: - return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue) - // K > A - case JumpGreaterThan: - return conditionalJump(a, "jgt", "jle") - // K < A - case JumpLessThan: - return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue) - // K >= A - case JumpGreaterOrEqual: - return conditionalJump(a, "jge", "jlt") - // K <= A - case JumpLessOrEqual: - return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue) - // K & A != 0 - case JumpBitsSet: - if a.SkipFalse > 0 { - return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse) - } - return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue) - // K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips - case JumpBitsNotSet: - return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String() - default: - return fmt.Sprintf("unknown instruction: %#v", a) - } -} - -func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string { - if inst.SkipTrue > 0 { - if inst.SkipFalse > 0 { - return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse) - } - return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue) - } - return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse) -} - -// RetA exits the BPF program, returning the value of register A. -type RetA struct{} - -// Assemble implements the Instruction Assemble method. -func (a RetA) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsReturn | opRetSrcA, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a RetA) String() string { - return fmt.Sprintf("ret a") -} - -// RetConstant exits the BPF program, returning a constant value. -type RetConstant struct { - Val uint32 -} - -// Assemble implements the Instruction Assemble method. -func (a RetConstant) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsReturn | opRetSrcConstant, - K: a.Val, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a RetConstant) String() string { - return fmt.Sprintf("ret #%d", a.Val) -} - -// TXA copies the value of register X to register A. -type TXA struct{} - -// Assemble implements the Instruction Assemble method. -func (a TXA) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsMisc | opMiscTXA, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a TXA) String() string { - return fmt.Sprintf("txa") -} - -// TAX copies the value of register A to register X. -type TAX struct{} - -// Assemble implements the Instruction Assemble method. -func (a TAX) Assemble() (RawInstruction, error) { - return RawInstruction{ - Op: opClsMisc | opMiscTAX, - }, nil -} - -// String returns the the instruction in assembler notation. -func (a TAX) String() string { - return fmt.Sprintf("tax") -} - -func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) { - var ( - cls uint16 - sz uint16 - ) - switch dst { - case RegA: - cls = opClsLoadA - case RegX: - cls = opClsLoadX - default: - return RawInstruction{}, fmt.Errorf("invalid target register %v", dst) - } - switch loadSize { - case 1: - sz = opLoadWidth1 - case 2: - sz = opLoadWidth2 - case 4: - sz = opLoadWidth4 - default: - return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz) - } - return RawInstruction{ - Op: cls | sz | mode, - K: k, - }, nil -} diff --git a/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf b/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf deleted file mode 100644 index f87144064b9..00000000000 --- a/vendor/golang.org/x/net/bpf/testdata/all_instructions.bpf +++ /dev/null @@ -1 +0,0 @@ -50,0 0 0 42,1 0 0 42,96 0 0 3,97 0 0 3,48 0 0 42,40 0 0 42,32 0 0 42,80 0 0 42,72 0 0 42,64 0 0 42,177 0 0 42,128 0 0 0,32 0 0 4294963200,32 0 0 4294963204,32 0 0 4294963256,2 0 0 3,3 0 0 3,4 0 0 42,20 0 0 42,36 0 0 42,52 0 0 42,68 0 0 42,84 0 0 42,100 0 0 42,116 0 0 42,148 0 0 42,164 0 0 42,12 0 0 0,28 0 0 0,44 0 0 0,60 0 0 0,76 0 0 0,92 0 0 0,108 0 0 0,124 0 0 0,156 0 0 0,172 0 0 0,132 0 0 0,5 0 0 10,21 8 9 42,21 0 8 42,53 0 7 42,37 0 6 42,37 4 5 42,53 3 4 42,69 2 3 42,7 0 0 0,135 0 0 0,22 0 0 0,6 0 0 0, diff --git a/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt b/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt deleted file mode 100644 index 30455015536..00000000000 --- a/vendor/golang.org/x/net/bpf/testdata/all_instructions.txt +++ /dev/null @@ -1,79 +0,0 @@ -# This filter is compiled to all_instructions.bpf by the `bpf_asm` -# tool, which can be found in the linux kernel source tree under -# tools/net. - -# Load immediate -ld #42 -ldx #42 - -# Load scratch -ld M[3] -ldx M[3] - -# Load absolute -ldb [42] -ldh [42] -ld [42] - -# Load indirect -ldb [x + 42] -ldh [x + 42] -ld [x + 42] - -# Load IPv4 header length -ldx 4*([42]&0xf) - -# Run extension function -ld #len -ld #proto -ld #type -ld #rand - -# Store scratch -st M[3] -stx M[3] - -# A constant -add #42 -sub #42 -mul #42 -div #42 -or #42 -and #42 -lsh #42 -rsh #42 -mod #42 -xor #42 - -# A X -add x -sub x -mul x -div x -or x -and x -lsh x -rsh x -mod x -xor x - -# !A -neg - -# Jumps -ja end -jeq #42,prev,end -jne #42,end -jlt #42,end -jle #42,end -jgt #42,prev,end -jge #42,prev,end -jset #42,prev,end - -# Register transfers -tax -txa - -# Returns -prev: ret a -end: ret #42 diff --git a/vendor/golang.org/x/net/bpf/vm.go b/vendor/golang.org/x/net/bpf/vm.go deleted file mode 100644 index 4c656f1e12a..00000000000 --- a/vendor/golang.org/x/net/bpf/vm.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2016 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 bpf - -import ( - "errors" - "fmt" -) - -// A VM is an emulated BPF virtual machine. -type VM struct { - filter []Instruction -} - -// NewVM returns a new VM using the input BPF program. -func NewVM(filter []Instruction) (*VM, error) { - if len(filter) == 0 { - return nil, errors.New("one or more Instructions must be specified") - } - - for i, ins := range filter { - check := len(filter) - (i + 1) - switch ins := ins.(type) { - // Check for out-of-bounds jumps in instructions - case Jump: - if check <= int(ins.Skip) { - return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip) - } - case JumpIf: - if check <= int(ins.SkipTrue) { - return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue) - } - if check <= int(ins.SkipFalse) { - return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) - } - // Check for division or modulus by zero - case ALUOpConstant: - if ins.Val != 0 { - break - } - - switch ins.Op { - case ALUOpDiv, ALUOpMod: - return nil, errors.New("cannot divide by zero using ALUOpConstant") - } - // Check for unknown extensions - case LoadExtension: - switch ins.Num { - case ExtLen: - default: - return nil, fmt.Errorf("extension %d not implemented", ins.Num) - } - } - } - - // Make sure last instruction is a return instruction - switch filter[len(filter)-1].(type) { - case RetA, RetConstant: - default: - return nil, errors.New("BPF program must end with RetA or RetConstant") - } - - // Though our VM works using disassembled instructions, we - // attempt to assemble the input filter anyway to ensure it is compatible - // with an operating system VM. - _, err := Assemble(filter) - - return &VM{ - filter: filter, - }, err -} - -// Run runs the VM's BPF program against the input bytes. -// Run returns the number of bytes accepted by the BPF program, and any errors -// which occurred while processing the program. -func (v *VM) Run(in []byte) (int, error) { - var ( - // Registers of the virtual machine - regA uint32 - regX uint32 - regScratch [16]uint32 - - // OK is true if the program should continue processing the next - // instruction, or false if not, causing the loop to break - ok = true - ) - - // TODO(mdlayher): implement: - // - NegateA: - // - would require a change from uint32 registers to int32 - // registers - - // TODO(mdlayher): add interop tests that check signedness of ALU - // operations against kernel implementation, and make sure Go - // implementation matches behavior - - for i := 0; i < len(v.filter) && ok; i++ { - ins := v.filter[i] - - switch ins := ins.(type) { - case ALUOpConstant: - regA = aluOpConstant(ins, regA) - case ALUOpX: - regA, ok = aluOpX(ins, regA, regX) - case Jump: - i += int(ins.Skip) - case JumpIf: - jump := jumpIf(ins, regA) - i += jump - case LoadAbsolute: - regA, ok = loadAbsolute(ins, in) - case LoadConstant: - regA, regX = loadConstant(ins, regA, regX) - case LoadExtension: - regA = loadExtension(ins, in) - case LoadIndirect: - regA, ok = loadIndirect(ins, in, regX) - case LoadMemShift: - regX, ok = loadMemShift(ins, in) - case LoadScratch: - regA, regX = loadScratch(ins, regScratch, regA, regX) - case RetA: - return int(regA), nil - case RetConstant: - return int(ins.Val), nil - case StoreScratch: - regScratch = storeScratch(ins, regScratch, regA, regX) - case TAX: - regX = regA - case TXA: - regA = regX - default: - return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins) - } - } - - return 0, nil -} diff --git a/vendor/golang.org/x/net/bpf/vm_instructions.go b/vendor/golang.org/x/net/bpf/vm_instructions.go deleted file mode 100644 index 516f9462b9f..00000000000 --- a/vendor/golang.org/x/net/bpf/vm_instructions.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2016 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 bpf - -import ( - "encoding/binary" - "fmt" -) - -func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 { - return aluOpCommon(ins.Op, regA, ins.Val) -} - -func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) { - // Guard against division or modulus by zero by terminating - // the program, as the OS BPF VM does - if regX == 0 { - switch ins.Op { - case ALUOpDiv, ALUOpMod: - return 0, false - } - } - - return aluOpCommon(ins.Op, regA, regX), true -} - -func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 { - switch op { - case ALUOpAdd: - return regA + value - case ALUOpSub: - return regA - value - case ALUOpMul: - return regA * value - case ALUOpDiv: - // Division by zero not permitted by NewVM and aluOpX checks - return regA / value - case ALUOpOr: - return regA | value - case ALUOpAnd: - return regA & value - case ALUOpShiftLeft: - return regA << value - case ALUOpShiftRight: - return regA >> value - case ALUOpMod: - // Modulus by zero not permitted by NewVM and aluOpX checks - return regA % value - case ALUOpXor: - return regA ^ value - default: - return regA - } -} - -func jumpIf(ins JumpIf, value uint32) int { - var ok bool - inV := uint32(ins.Val) - - switch ins.Cond { - case JumpEqual: - ok = value == inV - case JumpNotEqual: - ok = value != inV - case JumpGreaterThan: - ok = value > inV - case JumpLessThan: - ok = value < inV - case JumpGreaterOrEqual: - ok = value >= inV - case JumpLessOrEqual: - ok = value <= inV - case JumpBitsSet: - ok = (value & inV) != 0 - case JumpBitsNotSet: - ok = (value & inV) == 0 - } - - if ok { - return int(ins.SkipTrue) - } - - return int(ins.SkipFalse) -} - -func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) { - offset := int(ins.Off) - size := int(ins.Size) - - return loadCommon(in, offset, size) -} - -func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) { - switch ins.Dst { - case RegA: - regA = ins.Val - case RegX: - regX = ins.Val - } - - return regA, regX -} - -func loadExtension(ins LoadExtension, in []byte) uint32 { - switch ins.Num { - case ExtLen: - return uint32(len(in)) - default: - panic(fmt.Sprintf("unimplemented extension: %d", ins.Num)) - } -} - -func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) { - offset := int(ins.Off) + int(regX) - size := int(ins.Size) - - return loadCommon(in, offset, size) -} - -func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) { - offset := int(ins.Off) - - if !inBounds(len(in), offset, 0) { - return 0, false - } - - // Mask off high 4 bits and multiply low 4 bits by 4 - return uint32(in[offset]&0x0f) * 4, true -} - -func inBounds(inLen int, offset int, size int) bool { - return offset+size <= inLen -} - -func loadCommon(in []byte, offset int, size int) (uint32, bool) { - if !inBounds(len(in), offset, size) { - return 0, false - } - - switch size { - case 1: - return uint32(in[offset]), true - case 2: - return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true - case 4: - return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true - default: - panic(fmt.Sprintf("invalid load size: %d", size)) - } -} - -func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) { - switch ins.Dst { - case RegA: - regA = regScratch[ins.N] - case RegX: - regX = regScratch[ins.N] - } - - return regA, regX -} - -func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 { - switch ins.Src { - case RegA: - regScratch[ins.N] = regA - case RegX: - regScratch[ins.N] = regX - } - - return regScratch -} diff --git a/vendor/golang.org/x/net/codereview.cfg b/vendor/golang.org/x/net/codereview.cfg deleted file mode 100644 index 3f8b14b64e8..00000000000 --- a/vendor/golang.org/x/net/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go index f143ed6a1eb..a3c021d3f88 100644 --- a/vendor/golang.org/x/net/context/context.go +++ b/vendor/golang.org/x/net/context/context.go @@ -5,6 +5,8 @@ // Package context defines the Context type, which carries deadlines, // cancelation signals, and other request-scoped values across API boundaries // and between processes. +// As of Go 1.7 this package is available in the standard library under the +// name context. https://golang.org/pkg/context. // // Incoming requests to a server should create a Context, and outgoing calls to // servers should accept a Context. The chain of function calls between must @@ -36,103 +38,6 @@ // Contexts. package context // import "golang.org/x/net/context" -import "time" - -// A Context carries a deadline, a cancelation signal, and other values across -// API boundaries. -// -// Context's methods may be called by multiple goroutines simultaneously. -type Context interface { - // Deadline returns the time when work done on behalf of this context - // should be canceled. Deadline returns ok==false when no deadline is - // set. Successive calls to Deadline return the same results. - Deadline() (deadline time.Time, ok bool) - - // Done returns a channel that's closed when work done on behalf of this - // context should be canceled. Done may return nil if this context can - // never be canceled. Successive calls to Done return the same value. - // - // WithCancel arranges for Done to be closed when cancel is called; - // WithDeadline arranges for Done to be closed when the deadline - // expires; WithTimeout arranges for Done to be closed when the timeout - // elapses. - // - // Done is provided for use in select statements: - // - // // Stream generates values with DoSomething and sends them to out - // // until DoSomething returns an error or ctx.Done is closed. - // func Stream(ctx context.Context, out chan<- Value) error { - // for { - // v, err := DoSomething(ctx) - // if err != nil { - // return err - // } - // select { - // case <-ctx.Done(): - // return ctx.Err() - // case out <- v: - // } - // } - // } - // - // See http://blog.golang.org/pipelines for more examples of how to use - // a Done channel for cancelation. - Done() <-chan struct{} - - // Err returns a non-nil error value after Done is closed. Err returns - // Canceled if the context was canceled or DeadlineExceeded if the - // context's deadline passed. No other values for Err are defined. - // After Done is closed, successive calls to Err return the same value. - Err() error - - // Value returns the value associated with this context for key, or nil - // if no value is associated with key. Successive calls to Value with - // the same key returns the same result. - // - // Use context values only for request-scoped data that transits - // processes and API boundaries, not for passing optional parameters to - // functions. - // - // A key identifies a specific value in a Context. Functions that wish - // to store values in Context typically allocate a key in a global - // variable then use that key as the argument to context.WithValue and - // Context.Value. A key can be any type that supports equality; - // packages should define keys as an unexported type to avoid - // collisions. - // - // Packages that define a Context key should provide type-safe accessors - // for the values stores using that key: - // - // // Package user defines a User type that's stored in Contexts. - // package user - // - // import "golang.org/x/net/context" - // - // // User is the type of value stored in the Contexts. - // type User struct {...} - // - // // key is an unexported type for keys defined in this package. - // // This prevents collisions with keys defined in other packages. - // type key int - // - // // userKey is the key for user.User values in Contexts. It is - // // unexported; clients use user.NewContext and user.FromContext - // // instead of using this key directly. - // var userKey key = 0 - // - // // NewContext returns a new Context that carries value u. - // func NewContext(ctx context.Context, u *User) context.Context { - // return context.WithValue(ctx, userKey, u) - // } - // - // // FromContext returns the User value stored in ctx, if any. - // func FromContext(ctx context.Context) (*User, bool) { - // u, ok := ctx.Value(userKey).(*User) - // return u, ok - // } - Value(key interface{}) interface{} -} - // Background returns a non-nil, empty Context. It is never canceled, has no // values, and has no deadline. It is typically used by the main function, // initialization, and tests, and as the top-level Context for incoming @@ -149,8 +54,3 @@ func Background() Context { func TODO() Context { return todo } - -// A CancelFunc tells an operation to abandon its work. -// A CancelFunc does not wait for the work to stop. -// After the first call, subsequent calls to a CancelFunc do nothing. -type CancelFunc func() diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go deleted file mode 100644 index 606cf1f9726..00000000000 --- a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016 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 go1.7 - -// Package ctxhttp provides helper functions for performing context-aware HTTP requests. -package ctxhttp // import "golang.org/x/net/context/ctxhttp" - -import ( - "io" - "net/http" - "net/url" - "strings" - - "golang.org/x/net/context" -) - -// Do sends an HTTP request with the provided http.Client and returns -// an HTTP response. -// -// If the client is nil, http.DefaultClient is used. -// -// The provided ctx must be non-nil. If it is canceled or times out, -// ctx.Err() will be returned. -func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { - if client == nil { - client = http.DefaultClient - } - resp, err := client.Do(req.WithContext(ctx)) - // If we got an error, and the context has been canceled, - // the context's error is probably more useful. - if err != nil { - select { - case <-ctx.Done(): - err = ctx.Err() - default: - } - } - return resp, err -} - -// Get issues a GET request via the Do function. -func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Head issues a HEAD request via the Do function. -func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("HEAD", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Post issues a POST request via the Do function. -func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", url, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", bodyType) - return Do(ctx, client, req) -} - -// PostForm issues a POST request via the Do function. -func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { - return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go deleted file mode 100644 index 926870cc23f..00000000000 --- a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2015 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 !go1.7 - -package ctxhttp // import "golang.org/x/net/context/ctxhttp" - -import ( - "io" - "net/http" - "net/url" - "strings" - - "golang.org/x/net/context" -) - -func nop() {} - -var ( - testHookContextDoneBeforeHeaders = nop - testHookDoReturned = nop - testHookDidBodyClose = nop -) - -// Do sends an HTTP request with the provided http.Client and returns an HTTP response. -// If the client is nil, http.DefaultClient is used. -// If the context is canceled or times out, ctx.Err() will be returned. -func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { - if client == nil { - client = http.DefaultClient - } - - // TODO(djd): Respect any existing value of req.Cancel. - cancel := make(chan struct{}) - req.Cancel = cancel - - type responseAndError struct { - resp *http.Response - err error - } - result := make(chan responseAndError, 1) - - // Make local copies of test hooks closed over by goroutines below. - // Prevents data races in tests. - testHookDoReturned := testHookDoReturned - testHookDidBodyClose := testHookDidBodyClose - - go func() { - resp, err := client.Do(req) - testHookDoReturned() - result <- responseAndError{resp, err} - }() - - var resp *http.Response - - select { - case <-ctx.Done(): - testHookContextDoneBeforeHeaders() - close(cancel) - // Clean up after the goroutine calling client.Do: - go func() { - if r := <-result; r.resp != nil { - testHookDidBodyClose() - r.resp.Body.Close() - } - }() - return nil, ctx.Err() - case r := <-result: - var err error - resp, err = r.resp, r.err - if err != nil { - return resp, err - } - } - - c := make(chan struct{}) - go func() { - select { - case <-ctx.Done(): - close(cancel) - case <-c: - // The response's Body is closed. - } - }() - resp.Body = ¬ifyingReader{resp.Body, c} - - return resp, nil -} - -// Get issues a GET request via the Do function. -func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Head issues a HEAD request via the Do function. -func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("HEAD", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Post issues a POST request via the Do function. -func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", url, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", bodyType) - return Do(ctx, client, req) -} - -// PostForm issues a POST request via the Do function. -func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { - return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} - -// notifyingReader is an io.ReadCloser that closes the notify channel after -// Close is called or a Read fails on the underlying ReadCloser. -type notifyingReader struct { - io.ReadCloser - notify chan<- struct{} -} - -func (r *notifyingReader) Read(p []byte) (int, error) { - n, err := r.ReadCloser.Read(p) - if err != nil && r.notify != nil { - close(r.notify) - r.notify = nil - } - return n, err -} - -func (r *notifyingReader) Close() error { - err := r.ReadCloser.Close() - if r.notify != nil { - close(r.notify) - r.notify = nil - } - return err -} diff --git a/vendor/golang.org/x/net/context/go19.go b/vendor/golang.org/x/net/context/go19.go new file mode 100644 index 00000000000..d88bd1db127 --- /dev/null +++ b/vendor/golang.org/x/net/context/go19.go @@ -0,0 +1,20 @@ +// 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 file. + +// +build go1.9 + +package context + +import "context" // standard library's context, as of Go 1.7 + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context = context.Context + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc = context.CancelFunc diff --git a/vendor/golang.org/x/net/context/pre_go19.go b/vendor/golang.org/x/net/context/pre_go19.go new file mode 100644 index 00000000000..b105f80be4f --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go19.go @@ -0,0 +1,109 @@ +// Copyright 2014 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 !go1.9 + +package context + +import "time" + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context interface { + // Deadline returns the time when work done on behalf of this context + // should be canceled. Deadline returns ok==false when no deadline is + // set. Successive calls to Deadline return the same results. + Deadline() (deadline time.Time, ok bool) + + // Done returns a channel that's closed when work done on behalf of this + // context should be canceled. Done may return nil if this context can + // never be canceled. Successive calls to Done return the same value. + // + // WithCancel arranges for Done to be closed when cancel is called; + // WithDeadline arranges for Done to be closed when the deadline + // expires; WithTimeout arranges for Done to be closed when the timeout + // elapses. + // + // Done is provided for use in select statements: + // + // // Stream generates values with DoSomething and sends them to out + // // until DoSomething returns an error or ctx.Done is closed. + // func Stream(ctx context.Context, out chan<- Value) error { + // for { + // v, err := DoSomething(ctx) + // if err != nil { + // return err + // } + // select { + // case <-ctx.Done(): + // return ctx.Err() + // case out <- v: + // } + // } + // } + // + // See http://blog.golang.org/pipelines for more examples of how to use + // a Done channel for cancelation. + Done() <-chan struct{} + + // Err returns a non-nil error value after Done is closed. Err returns + // Canceled if the context was canceled or DeadlineExceeded if the + // context's deadline passed. No other values for Err are defined. + // After Done is closed, successive calls to Err return the same value. + Err() error + + // Value returns the value associated with this context for key, or nil + // if no value is associated with key. Successive calls to Value with + // the same key returns the same result. + // + // Use context values only for request-scoped data that transits + // processes and API boundaries, not for passing optional parameters to + // functions. + // + // A key identifies a specific value in a Context. Functions that wish + // to store values in Context typically allocate a key in a global + // variable then use that key as the argument to context.WithValue and + // Context.Value. A key can be any type that supports equality; + // packages should define keys as an unexported type to avoid + // collisions. + // + // Packages that define a Context key should provide type-safe accessors + // for the values stores using that key: + // + // // Package user defines a User type that's stored in Contexts. + // package user + // + // import "golang.org/x/net/context" + // + // // User is the type of value stored in the Contexts. + // type User struct {...} + // + // // key is an unexported type for keys defined in this package. + // // This prevents collisions with keys defined in other packages. + // type key int + // + // // userKey is the key for user.User values in Contexts. It is + // // unexported; clients use user.NewContext and user.FromContext + // // instead of using this key directly. + // var userKey key = 0 + // + // // NewContext returns a new Context that carries value u. + // func NewContext(ctx context.Context, u *User) context.Context { + // return context.WithValue(ctx, userKey, u) + // } + // + // // FromContext returns the User value stored in ctx, if any. + // func FromContext(ctx context.Context) (*User, bool) { + // u, ok := ctx.Value(userKey).(*User) + // return u, ok + // } + Value(key interface{}) interface{} +} + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc func() diff --git a/vendor/golang.org/x/net/dict/dict.go b/vendor/golang.org/x/net/dict/dict.go deleted file mode 100644 index 93e65c03cfd..00000000000 --- a/vendor/golang.org/x/net/dict/dict.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2010 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 dict implements the Dictionary Server Protocol -// as defined in RFC 2229. -package dict // import "golang.org/x/net/dict" - -import ( - "net/textproto" - "strconv" - "strings" -) - -// A Client represents a client connection to a dictionary server. -type Client struct { - text *textproto.Conn -} - -// Dial returns a new client connected to a dictionary server at -// addr on the given network. -func Dial(network, addr string) (*Client, error) { - text, err := textproto.Dial(network, addr) - if err != nil { - return nil, err - } - _, _, err = text.ReadCodeLine(220) - if err != nil { - text.Close() - return nil, err - } - return &Client{text: text}, nil -} - -// Close closes the connection to the dictionary server. -func (c *Client) Close() error { - return c.text.Close() -} - -// A Dict represents a dictionary available on the server. -type Dict struct { - Name string // short name of dictionary - Desc string // long description -} - -// Dicts returns a list of the dictionaries available on the server. -func (c *Client) Dicts() ([]Dict, error) { - id, err := c.text.Cmd("SHOW DB") - if err != nil { - return nil, err - } - - c.text.StartResponse(id) - defer c.text.EndResponse(id) - - _, _, err = c.text.ReadCodeLine(110) - if err != nil { - return nil, err - } - lines, err := c.text.ReadDotLines() - if err != nil { - return nil, err - } - _, _, err = c.text.ReadCodeLine(250) - - dicts := make([]Dict, len(lines)) - for i := range dicts { - d := &dicts[i] - a, _ := fields(lines[i]) - if len(a) < 2 { - return nil, textproto.ProtocolError("invalid dictionary: " + lines[i]) - } - d.Name = a[0] - d.Desc = a[1] - } - return dicts, err -} - -// A Defn represents a definition. -type Defn struct { - Dict Dict // Dict where definition was found - Word string // Word being defined - Text []byte // Definition text, typically multiple lines -} - -// Define requests the definition of the given word. -// The argument dict names the dictionary to use, -// the Name field of a Dict returned by Dicts. -// -// The special dictionary name "*" means to look in all the -// server's dictionaries. -// The special dictionary name "!" means to look in all the -// server's dictionaries in turn, stopping after finding the word -// in one of them. -func (c *Client) Define(dict, word string) ([]*Defn, error) { - id, err := c.text.Cmd("DEFINE %s %q", dict, word) - if err != nil { - return nil, err - } - - c.text.StartResponse(id) - defer c.text.EndResponse(id) - - _, line, err := c.text.ReadCodeLine(150) - if err != nil { - return nil, err - } - a, _ := fields(line) - if len(a) < 1 { - return nil, textproto.ProtocolError("malformed response: " + line) - } - n, err := strconv.Atoi(a[0]) - if err != nil { - return nil, textproto.ProtocolError("invalid definition count: " + a[0]) - } - def := make([]*Defn, n) - for i := 0; i < n; i++ { - _, line, err = c.text.ReadCodeLine(151) - if err != nil { - return nil, err - } - a, _ := fields(line) - if len(a) < 3 { - // skip it, to keep protocol in sync - i-- - n-- - def = def[0:n] - continue - } - d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}} - d.Text, err = c.text.ReadDotBytes() - if err != nil { - return nil, err - } - def[i] = d - } - _, _, err = c.text.ReadCodeLine(250) - return def, err -} - -// Fields returns the fields in s. -// Fields are space separated unquoted words -// or quoted with single or double quote. -func fields(s string) ([]string, error) { - var v []string - i := 0 - for { - for i < len(s) && (s[i] == ' ' || s[i] == '\t') { - i++ - } - if i >= len(s) { - break - } - if s[i] == '"' || s[i] == '\'' { - q := s[i] - // quoted string - var j int - for j = i + 1; ; j++ { - if j >= len(s) { - return nil, textproto.ProtocolError("malformed quoted string") - } - if s[j] == '\\' { - j++ - continue - } - if s[j] == q { - j++ - break - } - } - v = append(v, unquote(s[i+1:j-1])) - i = j - } else { - // atom - var j int - for j = i; j < len(s); j++ { - if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' { - break - } - } - v = append(v, s[i:j]) - i = j - } - if i < len(s) { - c := s[i] - if c != ' ' && c != '\t' { - return nil, textproto.ProtocolError("quotes not on word boundaries") - } - } - } - return v, nil -} - -func unquote(s string) string { - if strings.Index(s, "\\") < 0 { - return s - } - b := []byte(s) - w := 0 - for r := 0; r < len(b); r++ { - c := b[r] - if c == '\\' { - r++ - c = b[r] - } - b[w] = c - w++ - } - return string(b[0:w]) -} diff --git a/vendor/golang.org/x/net/dns/dnsmessage/message.go b/vendor/golang.org/x/net/dns/dnsmessage/message.go deleted file mode 100644 index da43b0ba48e..00000000000 --- a/vendor/golang.org/x/net/dns/dnsmessage/message.go +++ /dev/null @@ -1,1418 +0,0 @@ -// Copyright 2009 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 dnsmessage provides a mostly RFC 1035 compliant implementation of -// DNS message packing and unpacking. -// -// This implementation is designed to minimize heap allocations and avoid -// unnecessary packing and unpacking as much as possible. -package dnsmessage - -import ( - "errors" -) - -// Packet formats - -// A Type is a type of DNS request and response. -type Type uint16 - -// A Class is a type of network. -type Class uint16 - -// An OpCode is a DNS operation code. -type OpCode uint16 - -// An RCode is a DNS response status code. -type RCode uint16 - -// Wire constants. -const ( - // ResourceHeader.Type and Question.Type - TypeA Type = 1 - TypeNS Type = 2 - TypeCNAME Type = 5 - TypeSOA Type = 6 - TypePTR Type = 12 - TypeMX Type = 15 - TypeTXT Type = 16 - TypeAAAA Type = 28 - TypeSRV Type = 33 - - // Question.Type - TypeWKS Type = 11 - TypeHINFO Type = 13 - TypeMINFO Type = 14 - TypeAXFR Type = 252 - TypeALL Type = 255 - - // ResourceHeader.Class and Question.Class - ClassINET Class = 1 - ClassCSNET Class = 2 - ClassCHAOS Class = 3 - ClassHESIOD Class = 4 - - // Question.Class - ClassANY Class = 255 - - // Message.Rcode - RCodeSuccess RCode = 0 - RCodeFormatError RCode = 1 - RCodeServerFailure RCode = 2 - RCodeNameError RCode = 3 - RCodeNotImplemented RCode = 4 - RCodeRefused RCode = 5 -) - -var ( - // ErrNotStarted indicates that the prerequisite information isn't - // available yet because the previous records haven't been appropriately - // parsed or skipped. - ErrNotStarted = errors.New("parsing of this type isn't available yet") - - // ErrSectionDone indicated that all records in the section have been - // parsed. - ErrSectionDone = errors.New("parsing of this section has completed") - - errBaseLen = errors.New("insufficient data for base length type") - errCalcLen = errors.New("insufficient data for calculated length type") - errReserved = errors.New("segment prefix is reserved") - errTooManyPtr = errors.New("too many pointers (>10)") - errInvalidPtr = errors.New("invalid pointer") - errResourceLen = errors.New("insufficient data for resource body length") - errSegTooLong = errors.New("segment length too long") - errZeroSegLen = errors.New("zero length segment") - errResTooLong = errors.New("resource length too long") - errTooManyQuestions = errors.New("too many Questions to pack (>65535)") - errTooManyAnswers = errors.New("too many Answers to pack (>65535)") - errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)") - errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)") -) - -type nestedError struct { - // s is the current level's error message. - s string - - // err is the nested error. - err error -} - -// nestedError implements error.Error. -func (e *nestedError) Error() string { - return e.s + ": " + e.err.Error() -} - -// Header is a representation of a DNS message header. -type Header struct { - ID uint16 - Response bool - OpCode OpCode - Authoritative bool - Truncated bool - RecursionDesired bool - RecursionAvailable bool - RCode RCode -} - -func (m *Header) pack() (id uint16, bits uint16) { - id = m.ID - bits = uint16(m.OpCode)<<11 | uint16(m.RCode) - if m.RecursionAvailable { - bits |= headerBitRA - } - if m.RecursionDesired { - bits |= headerBitRD - } - if m.Truncated { - bits |= headerBitTC - } - if m.Authoritative { - bits |= headerBitAA - } - if m.Response { - bits |= headerBitQR - } - return -} - -// Message is a representation of a DNS message. -type Message struct { - Header - Questions []Question - Answers []Resource - Authorities []Resource - Additionals []Resource -} - -type section uint8 - -const ( - sectionHeader section = iota - sectionQuestions - sectionAnswers - sectionAuthorities - sectionAdditionals - sectionDone - - headerBitQR = 1 << 15 // query/response (response=1) - headerBitAA = 1 << 10 // authoritative - headerBitTC = 1 << 9 // truncated - headerBitRD = 1 << 8 // recursion desired - headerBitRA = 1 << 7 // recursion available -) - -var sectionNames = map[section]string{ - sectionHeader: "header", - sectionQuestions: "Question", - sectionAnswers: "Answer", - sectionAuthorities: "Authority", - sectionAdditionals: "Additional", -} - -// header is the wire format for a DNS message header. -type header struct { - id uint16 - bits uint16 - questions uint16 - answers uint16 - authorities uint16 - additionals uint16 -} - -func (h *header) count(sec section) uint16 { - switch sec { - case sectionQuestions: - return h.questions - case sectionAnswers: - return h.answers - case sectionAuthorities: - return h.authorities - case sectionAdditionals: - return h.additionals - } - return 0 -} - -func (h *header) pack(msg []byte) []byte { - msg = packUint16(msg, h.id) - msg = packUint16(msg, h.bits) - msg = packUint16(msg, h.questions) - msg = packUint16(msg, h.answers) - msg = packUint16(msg, h.authorities) - return packUint16(msg, h.additionals) -} - -func (h *header) unpack(msg []byte, off int) (int, error) { - newOff := off - var err error - if h.id, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"id", err} - } - if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"bits", err} - } - if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"questions", err} - } - if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"answers", err} - } - if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"authorities", err} - } - if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"additionals", err} - } - return newOff, nil -} - -func (h *header) header() Header { - return Header{ - ID: h.id, - Response: (h.bits & headerBitQR) != 0, - OpCode: OpCode(h.bits>>11) & 0xF, - Authoritative: (h.bits & headerBitAA) != 0, - Truncated: (h.bits & headerBitTC) != 0, - RecursionDesired: (h.bits & headerBitRD) != 0, - RecursionAvailable: (h.bits & headerBitRA) != 0, - RCode: RCode(h.bits & 0xF), - } -} - -// A Resource is a DNS resource record. -type Resource interface { - // Header return's the Resource's ResourceHeader. - Header() *ResourceHeader - - // pack packs a Resource except for its header. - pack(msg []byte, compression map[string]int) ([]byte, error) - - // realType returns the actual type of the Resource. This is used to - // fill in the header Type field. - realType() Type -} - -func packResource(msg []byte, resource Resource, compression map[string]int) ([]byte, error) { - oldMsg := msg - resource.Header().Type = resource.realType() - msg, length, err := resource.Header().pack(msg, compression) - if err != nil { - return msg, &nestedError{"ResourceHeader", err} - } - preLen := len(msg) - msg, err = resource.pack(msg, compression) - if err != nil { - return msg, &nestedError{"content", err} - } - conLen := len(msg) - preLen - if conLen > int(^uint16(0)) { - return oldMsg, errResTooLong - } - // Fill in the length now that we know how long the content is. - packUint16(length[:0], uint16(conLen)) - resource.Header().Length = uint16(conLen) - return msg, nil -} - -// A Parser allows incrementally parsing a DNS message. -// -// When parsing is started, the Header is parsed. Next, each Question can be -// either parsed or skipped. Alternatively, all Questions can be skipped at -// once. When all Questions have been parsed, attempting to parse Questions -// will return (nil, nil) and attempting to skip Questions will return -// (true, nil). After all Questions have been either parsed or skipped, all -// Answers, Authorities and Additionals can be either parsed or skipped in the -// same way, and each type of Resource must be fully parsed or skipped before -// proceeding to the next type of Resource. -// -// Note that there is no requirement to fully skip or parse the message. -type Parser struct { - msg []byte - header header - - section section - off int - index int - resHeaderValid bool - resHeader ResourceHeader -} - -// Start parses the header and enables the parsing of Questions. -func (p *Parser) Start(msg []byte) (Header, error) { - if p.msg != nil { - *p = Parser{} - } - p.msg = msg - var err error - if p.off, err = p.header.unpack(msg, 0); err != nil { - return Header{}, &nestedError{"unpacking header", err} - } - p.section = sectionQuestions - return p.header.header(), nil -} - -func (p *Parser) checkAdvance(sec section) error { - if p.section < sec { - return ErrNotStarted - } - if p.section > sec { - return ErrSectionDone - } - p.resHeaderValid = false - if p.index == int(p.header.count(sec)) { - p.index = 0 - p.section++ - return ErrSectionDone - } - return nil -} - -func (p *Parser) resource(sec section) (Resource, error) { - var r Resource - hdr, err := p.resourceHeader(sec) - if err != nil { - return r, err - } - p.resHeaderValid = false - r, p.off, err = unpackResource(p.msg, p.off, hdr) - if err != nil { - return nil, &nestedError{"unpacking " + sectionNames[sec], err} - } - p.index++ - return r, nil -} - -func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) { - if p.resHeaderValid { - return p.resHeader, nil - } - if err := p.checkAdvance(sec); err != nil { - return ResourceHeader{}, err - } - var hdr ResourceHeader - off, err := hdr.unpack(p.msg, p.off) - if err != nil { - return ResourceHeader{}, err - } - p.resHeaderValid = true - p.resHeader = hdr - p.off = off - return hdr, nil -} - -func (p *Parser) skipResource(sec section) error { - if p.resHeaderValid { - newOff := p.off + int(p.resHeader.Length) - if newOff > len(p.msg) { - return errResourceLen - } - p.off = newOff - p.resHeaderValid = false - p.index++ - return nil - } - if err := p.checkAdvance(sec); err != nil { - return err - } - var err error - p.off, err = skipResource(p.msg, p.off) - if err != nil { - return &nestedError{"skipping: " + sectionNames[sec], err} - } - p.index++ - return nil -} - -// Question parses a single Question. -func (p *Parser) Question() (Question, error) { - if err := p.checkAdvance(sectionQuestions); err != nil { - return Question{}, err - } - name, off, err := unpackName(p.msg, p.off) - if err != nil { - return Question{}, &nestedError{"unpacking Question.Name", err} - } - typ, off, err := unpackType(p.msg, off) - if err != nil { - return Question{}, &nestedError{"unpacking Question.Type", err} - } - class, off, err := unpackClass(p.msg, off) - if err != nil { - return Question{}, &nestedError{"unpacking Question.Class", err} - } - p.off = off - p.index++ - return Question{name, typ, class}, nil -} - -// AllQuestions parses all Questions. -func (p *Parser) AllQuestions() ([]Question, error) { - qs := make([]Question, 0, p.header.questions) - for { - q, err := p.Question() - if err == ErrSectionDone { - return qs, nil - } - if err != nil { - return nil, err - } - qs = append(qs, q) - } -} - -// SkipQuestion skips a single Question. -func (p *Parser) SkipQuestion() error { - if err := p.checkAdvance(sectionQuestions); err != nil { - return err - } - off, err := skipName(p.msg, p.off) - if err != nil { - return &nestedError{"skipping Question Name", err} - } - if off, err = skipType(p.msg, off); err != nil { - return &nestedError{"skipping Question Type", err} - } - if off, err = skipClass(p.msg, off); err != nil { - return &nestedError{"skipping Question Class", err} - } - p.off = off - p.index++ - return nil -} - -// SkipAllQuestions skips all Questions. -func (p *Parser) SkipAllQuestions() error { - for { - if err := p.SkipQuestion(); err == ErrSectionDone { - return nil - } else if err != nil { - return err - } - } -} - -// AnswerHeader parses a single Answer ResourceHeader. -func (p *Parser) AnswerHeader() (ResourceHeader, error) { - return p.resourceHeader(sectionAnswers) -} - -// Answer parses a single Answer Resource. -func (p *Parser) Answer() (Resource, error) { - return p.resource(sectionAnswers) -} - -// AllAnswers parses all Answer Resources. -func (p *Parser) AllAnswers() ([]Resource, error) { - as := make([]Resource, 0, p.header.answers) - for { - a, err := p.Answer() - if err == ErrSectionDone { - return as, nil - } - if err != nil { - return nil, err - } - as = append(as, a) - } -} - -// SkipAnswer skips a single Answer Resource. -func (p *Parser) SkipAnswer() error { - return p.skipResource(sectionAnswers) -} - -// SkipAllAnswers skips all Answer Resources. -func (p *Parser) SkipAllAnswers() error { - for { - if err := p.SkipAnswer(); err == ErrSectionDone { - return nil - } else if err != nil { - return err - } - } -} - -// AuthorityHeader parses a single Authority ResourceHeader. -func (p *Parser) AuthorityHeader() (ResourceHeader, error) { - return p.resourceHeader(sectionAuthorities) -} - -// Authority parses a single Authority Resource. -func (p *Parser) Authority() (Resource, error) { - return p.resource(sectionAuthorities) -} - -// AllAuthorities parses all Authority Resources. -func (p *Parser) AllAuthorities() ([]Resource, error) { - as := make([]Resource, 0, p.header.authorities) - for { - a, err := p.Authority() - if err == ErrSectionDone { - return as, nil - } - if err != nil { - return nil, err - } - as = append(as, a) - } -} - -// SkipAuthority skips a single Authority Resource. -func (p *Parser) SkipAuthority() error { - return p.skipResource(sectionAuthorities) -} - -// SkipAllAuthorities skips all Authority Resources. -func (p *Parser) SkipAllAuthorities() error { - for { - if err := p.SkipAuthority(); err == ErrSectionDone { - return nil - } else if err != nil { - return err - } - } -} - -// AdditionalHeader parses a single Additional ResourceHeader. -func (p *Parser) AdditionalHeader() (ResourceHeader, error) { - return p.resourceHeader(sectionAdditionals) -} - -// Additional parses a single Additional Resource. -func (p *Parser) Additional() (Resource, error) { - return p.resource(sectionAdditionals) -} - -// AllAdditionals parses all Additional Resources. -func (p *Parser) AllAdditionals() ([]Resource, error) { - as := make([]Resource, 0, p.header.additionals) - for { - a, err := p.Additional() - if err == ErrSectionDone { - return as, nil - } - if err != nil { - return nil, err - } - as = append(as, a) - } -} - -// SkipAdditional skips a single Additional Resource. -func (p *Parser) SkipAdditional() error { - return p.skipResource(sectionAdditionals) -} - -// SkipAllAdditionals skips all Additional Resources. -func (p *Parser) SkipAllAdditionals() error { - for { - if err := p.SkipAdditional(); err == ErrSectionDone { - return nil - } else if err != nil { - return err - } - } -} - -// Unpack parses a full Message. -func (m *Message) Unpack(msg []byte) error { - var p Parser - var err error - if m.Header, err = p.Start(msg); err != nil { - return err - } - if m.Questions, err = p.AllQuestions(); err != nil { - return err - } - if m.Answers, err = p.AllAnswers(); err != nil { - return err - } - if m.Authorities, err = p.AllAuthorities(); err != nil { - return err - } - if m.Additionals, err = p.AllAdditionals(); err != nil { - return err - } - return nil -} - -// Pack packs a full Message. -func (m *Message) Pack() ([]byte, error) { - // Validate the lengths. It is very unlikely that anyone will try to - // pack more than 65535 of any particular type, but it is possible and - // we should fail gracefully. - if len(m.Questions) > int(^uint16(0)) { - return nil, errTooManyQuestions - } - if len(m.Answers) > int(^uint16(0)) { - return nil, errTooManyAnswers - } - if len(m.Authorities) > int(^uint16(0)) { - return nil, errTooManyAuthorities - } - if len(m.Additionals) > int(^uint16(0)) { - return nil, errTooManyAdditionals - } - - var h header - h.id, h.bits = m.Header.pack() - - h.questions = uint16(len(m.Questions)) - h.answers = uint16(len(m.Answers)) - h.authorities = uint16(len(m.Authorities)) - h.additionals = uint16(len(m.Additionals)) - - // The starting capacity doesn't matter too much, but most DNS responses - // Will be <= 512 bytes as it is the limit for DNS over UDP. - msg := make([]byte, 0, 512) - - msg = h.pack(msg) - - // RFC 1035 allows (but does not require) compression for packing. RFC - // 1035 requires unpacking implementations to support compression, so - // unconditionally enabling it is fine. - // - // DNS lookups are typically done over UDP, and RFC 1035 states that UDP - // DNS packets can be a maximum of 512 bytes long. Without compression, - // many DNS response packets are over this limit, so enabling - // compression will help ensure compliance. - compression := map[string]int{} - - for _, q := range m.Questions { - var err error - msg, err = q.pack(msg, compression) - if err != nil { - return nil, &nestedError{"packing Question", err} - } - } - for _, a := range m.Answers { - var err error - msg, err = packResource(msg, a, compression) - if err != nil { - return nil, &nestedError{"packing Answer", err} - } - } - for _, a := range m.Authorities { - var err error - msg, err = packResource(msg, a, compression) - if err != nil { - return nil, &nestedError{"packing Authority", err} - } - } - for _, a := range m.Additionals { - var err error - msg, err = packResource(msg, a, compression) - if err != nil { - return nil, &nestedError{"packing Additional", err} - } - } - - return msg, nil -} - -// An ResourceHeader is the header of a DNS resource record. There are -// many types of DNS resource records, but they all share the same header. -type ResourceHeader struct { - // Name is the domain name for which this resource record pertains. - Name string - - // Type is the type of DNS resource record. - // - // This field will be set automatically during packing. - Type Type - - // Class is the class of network to which this DNS resource record - // pertains. - Class Class - - // TTL is the length of time (measured in seconds) which this resource - // record is valid for (time to live). All Resources in a set should - // have the same TTL (RFC 2181 Section 5.2). - TTL uint32 - - // Length is the length of data in the resource record after the header. - // - // This field will be set automatically during packing. - Length uint16 -} - -// Header implements Resource.Header. -func (h *ResourceHeader) Header() *ResourceHeader { - return h -} - -// pack packs all of the fields in a ResourceHeader except for the length. The -// length bytes are returned as a slice so they can be filled in after the rest -// of the Resource has been packed. -func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int) (msg []byte, length []byte, err error) { - msg = oldMsg - if msg, err = packName(msg, h.Name, compression); err != nil { - return oldMsg, nil, &nestedError{"Name", err} - } - msg = packType(msg, h.Type) - msg = packClass(msg, h.Class) - msg = packUint32(msg, h.TTL) - lenBegin := len(msg) - msg = packUint16(msg, h.Length) - return msg, msg[lenBegin:], nil -} - -func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) { - newOff := off - var err error - if h.Name, newOff, err = unpackName(msg, newOff); err != nil { - return off, &nestedError{"Name", err} - } - if h.Type, newOff, err = unpackType(msg, newOff); err != nil { - return off, &nestedError{"Type", err} - } - if h.Class, newOff, err = unpackClass(msg, newOff); err != nil { - return off, &nestedError{"Class", err} - } - if h.TTL, newOff, err = unpackUint32(msg, newOff); err != nil { - return off, &nestedError{"TTL", err} - } - if h.Length, newOff, err = unpackUint16(msg, newOff); err != nil { - return off, &nestedError{"Length", err} - } - return newOff, nil -} - -func skipResource(msg []byte, off int) (int, error) { - newOff, err := skipName(msg, off) - if err != nil { - return off, &nestedError{"Name", err} - } - if newOff, err = skipType(msg, newOff); err != nil { - return off, &nestedError{"Type", err} - } - if newOff, err = skipClass(msg, newOff); err != nil { - return off, &nestedError{"Class", err} - } - if newOff, err = skipUint32(msg, newOff); err != nil { - return off, &nestedError{"TTL", err} - } - length, newOff, err := unpackUint16(msg, newOff) - if err != nil { - return off, &nestedError{"Length", err} - } - if newOff += int(length); newOff > len(msg) { - return off, errResourceLen - } - return newOff, nil -} - -func packUint16(msg []byte, field uint16) []byte { - return append(msg, byte(field>>8), byte(field)) -} - -func unpackUint16(msg []byte, off int) (uint16, int, error) { - if off+2 > len(msg) { - return 0, off, errBaseLen - } - return uint16(msg[off])<<8 | uint16(msg[off+1]), off + 2, nil -} - -func skipUint16(msg []byte, off int) (int, error) { - if off+2 > len(msg) { - return off, errBaseLen - } - return off + 2, nil -} - -func packType(msg []byte, field Type) []byte { - return packUint16(msg, uint16(field)) -} - -func unpackType(msg []byte, off int) (Type, int, error) { - t, o, err := unpackUint16(msg, off) - return Type(t), o, err -} - -func skipType(msg []byte, off int) (int, error) { - return skipUint16(msg, off) -} - -func packClass(msg []byte, field Class) []byte { - return packUint16(msg, uint16(field)) -} - -func unpackClass(msg []byte, off int) (Class, int, error) { - c, o, err := unpackUint16(msg, off) - return Class(c), o, err -} - -func skipClass(msg []byte, off int) (int, error) { - return skipUint16(msg, off) -} - -func packUint32(msg []byte, field uint32) []byte { - return append( - msg, - byte(field>>24), - byte(field>>16), - byte(field>>8), - byte(field), - ) -} - -func unpackUint32(msg []byte, off int) (uint32, int, error) { - if off+4 > len(msg) { - return 0, off, errBaseLen - } - v := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3]) - return v, off + 4, nil -} - -func skipUint32(msg []byte, off int) (int, error) { - if off+4 > len(msg) { - return off, errBaseLen - } - return off + 4, nil -} - -func packText(msg []byte, field string) []byte { - for len(field) > 0 { - l := len(field) - if l > 255 { - l = 255 - } - msg = append(msg, byte(l)) - msg = append(msg, field[:l]...) - field = field[l:] - } - return msg -} - -func unpackText(msg []byte, off int) (string, int, error) { - if off >= len(msg) { - return "", off, errBaseLen - } - beginOff := off + 1 - endOff := beginOff + int(msg[off]) - if endOff > len(msg) { - return "", off, errCalcLen - } - return string(msg[beginOff:endOff]), endOff, nil -} - -func skipText(msg []byte, off int) (int, error) { - if off >= len(msg) { - return off, errBaseLen - } - endOff := off + 1 + int(msg[off]) - if endOff > len(msg) { - return off, errCalcLen - } - return endOff, nil -} - -func packBytes(msg []byte, field []byte) []byte { - return append(msg, field...) -} - -func unpackBytes(msg []byte, off int, field []byte) (int, error) { - newOff := off + len(field) - if newOff > len(msg) { - return off, errBaseLen - } - copy(field, msg[off:newOff]) - return newOff, nil -} - -func skipBytes(msg []byte, off int, field []byte) (int, error) { - newOff := off + len(field) - if newOff > len(msg) { - return off, errBaseLen - } - return newOff, nil -} - -// packName packs a domain name. -// -// Domain names are a sequence of counted strings split at the dots. They end -// with a zero-length string. Compression can be used to reuse domain suffixes. -// -// The compression map will be updated with new domain suffixes. If compression -// is nil, compression will not be used. -func packName(msg []byte, name string, compression map[string]int) ([]byte, error) { - oldMsg := msg - - // Add a trailing dot to canonicalize name. - if n := len(name); n == 0 || name[n-1] != '.' { - name += "." - } - - // Allow root domain. - if name == "." { - return append(msg, 0), nil - } - - // Emit sequence of counted strings, chopping at dots. - for i, begin := 0, 0; i < len(name); i++ { - // Check for the end of the segment. - if name[i] == '.' { - // The two most significant bits have special meaning. - // It isn't allowed for segments to be long enough to - // need them. - if i-begin >= 1<<6 { - return oldMsg, errSegTooLong - } - - // Segments must have a non-zero length. - if i-begin == 0 { - return oldMsg, errZeroSegLen - } - - msg = append(msg, byte(i-begin)) - - for j := begin; j < i; j++ { - msg = append(msg, name[j]) - } - - begin = i + 1 - continue - } - - // We can only compress domain suffixes starting with a new - // segment. A pointer is two bytes with the two most significant - // bits set to 1 to indicate that it is a pointer. - if (i == 0 || name[i-1] == '.') && compression != nil { - if ptr, ok := compression[name[i:]]; ok { - // Hit. Emit a pointer instead of the rest of - // the domain. - return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil - } - - // Miss. Add the suffix to the compression table if the - // offset can be stored in the available 14 bytes. - if len(msg) <= int(^uint16(0)>>2) { - compression[name[i:]] = len(msg) - } - } - } - return append(msg, 0), nil -} - -// unpackName unpacks a domain name. -func unpackName(msg []byte, off int) (string, int, error) { - // currOff is the current working offset. - currOff := off - - // newOff is the offset where the next record will start. Pointers lead - // to data that belongs to other names and thus doesn't count towards to - // the usage of this name. - newOff := off - - // name is the domain name being unpacked. - name := make([]byte, 0, 255) - - // ptr is the number of pointers followed. - var ptr int -Loop: - for { - if currOff >= len(msg) { - return "", off, errBaseLen - } - c := int(msg[currOff]) - currOff++ - switch c & 0xC0 { - case 0x00: // String segment - if c == 0x00 { - // A zero length signals the end of the name. - break Loop - } - endOff := currOff + c - if endOff > len(msg) { - return "", off, errCalcLen - } - name = append(name, msg[currOff:endOff]...) - name = append(name, '.') - currOff = endOff - case 0xC0: // Pointer - if currOff >= len(msg) { - return "", off, errInvalidPtr - } - c1 := msg[currOff] - currOff++ - if ptr == 0 { - newOff = currOff - } - // Don't follow too many pointers, maybe there's a loop. - if ptr++; ptr > 10 { - return "", off, errTooManyPtr - } - currOff = (c^0xC0)<<8 | int(c1) - default: - // Prefixes 0x80 and 0x40 are reserved. - return "", off, errReserved - } - } - if len(name) == 0 { - name = append(name, '.') - } - if ptr == 0 { - newOff = currOff - } - return string(name), newOff, nil -} - -func skipName(msg []byte, off int) (int, error) { - // newOff is the offset where the next record will start. Pointers lead - // to data that belongs to other names and thus doesn't count towards to - // the usage of this name. - newOff := off - -Loop: - for { - if newOff >= len(msg) { - return off, errBaseLen - } - c := int(msg[newOff]) - newOff++ - switch c & 0xC0 { - case 0x00: - if c == 0x00 { - // A zero length signals the end of the name. - break Loop - } - // literal string - newOff += c - if newOff > len(msg) { - return off, errCalcLen - } - case 0xC0: - // Pointer to somewhere else in msg. - - // Pointers are two bytes. - newOff++ - - // Don't follow the pointer as the data here has ended. - break Loop - default: - // Prefixes 0x80 and 0x40 are reserved. - return off, errReserved - } - } - - return newOff, nil -} - -// A Question is a DNS query. -type Question struct { - Name string - Type Type - Class Class -} - -func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) { - msg, err := packName(msg, q.Name, compression) - if err != nil { - return msg, &nestedError{"Name", err} - } - msg = packType(msg, q.Type) - return packClass(msg, q.Class), nil -} - -func unpackResource(msg []byte, off int, hdr ResourceHeader) (Resource, int, error) { - var ( - r Resource - err error - name string - ) - switch hdr.Type { - case TypeA: - r, err = unpackAResource(hdr, msg, off) - name = "A" - case TypeNS: - r, err = unpackNSResource(hdr, msg, off) - name = "NS" - case TypeCNAME: - r, err = unpackCNAMEResource(hdr, msg, off) - name = "CNAME" - case TypeSOA: - r, err = unpackSOAResource(hdr, msg, off) - name = "SOA" - case TypePTR: - r, err = unpackPTRResource(hdr, msg, off) - name = "PTR" - case TypeMX: - r, err = unpackMXResource(hdr, msg, off) - name = "MX" - case TypeTXT: - r, err = unpackTXTResource(hdr, msg, off) - name = "TXT" - case TypeAAAA: - r, err = unpackAAAAResource(hdr, msg, off) - name = "AAAA" - case TypeSRV: - r, err = unpackSRVResource(hdr, msg, off) - name = "SRV" - } - if err != nil { - return nil, off, &nestedError{name + " record", err} - } - if r != nil { - return r, off + int(hdr.Length), nil - } - return nil, off, errors.New("invalid resource type: " + string(hdr.Type+'0')) -} - -// A CNAMEResource is a CNAME Resource record. -type CNAMEResource struct { - ResourceHeader - - CNAME string -} - -func (r *CNAMEResource) realType() Type { - return TypeCNAME -} - -func (r *CNAMEResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packName(msg, r.CNAME, compression) -} - -func unpackCNAMEResource(hdr ResourceHeader, msg []byte, off int) (*CNAMEResource, error) { - cname, _, err := unpackName(msg, off) - if err != nil { - return nil, err - } - return &CNAMEResource{hdr, cname}, nil -} - -// An MXResource is an MX Resource record. -type MXResource struct { - ResourceHeader - - Pref uint16 - MX string -} - -func (r *MXResource) realType() Type { - return TypeMX -} - -func (r *MXResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - oldMsg := msg - msg = packUint16(msg, r.Pref) - msg, err := packName(msg, r.MX, compression) - if err != nil { - return oldMsg, &nestedError{"MXResource.MX", err} - } - return msg, nil -} - -func unpackMXResource(hdr ResourceHeader, msg []byte, off int) (*MXResource, error) { - pref, off, err := unpackUint16(msg, off) - if err != nil { - return nil, &nestedError{"Pref", err} - } - mx, _, err := unpackName(msg, off) - if err != nil { - return nil, &nestedError{"MX", err} - } - return &MXResource{hdr, pref, mx}, nil -} - -// An NSResource is an NS Resource record. -type NSResource struct { - ResourceHeader - - NS string -} - -func (r *NSResource) realType() Type { - return TypeNS -} - -func (r *NSResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packName(msg, r.NS, compression) -} - -func unpackNSResource(hdr ResourceHeader, msg []byte, off int) (*NSResource, error) { - ns, _, err := unpackName(msg, off) - if err != nil { - return nil, err - } - return &NSResource{hdr, ns}, nil -} - -// A PTRResource is a PTR Resource record. -type PTRResource struct { - ResourceHeader - - PTR string -} - -func (r *PTRResource) realType() Type { - return TypePTR -} - -func (r *PTRResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packName(msg, r.PTR, compression) -} - -func unpackPTRResource(hdr ResourceHeader, msg []byte, off int) (*PTRResource, error) { - ptr, _, err := unpackName(msg, off) - if err != nil { - return nil, err - } - return &PTRResource{hdr, ptr}, nil -} - -// An SOAResource is an SOA Resource record. -type SOAResource struct { - ResourceHeader - - NS string - MBox string - Serial uint32 - Refresh uint32 - Retry uint32 - Expire uint32 - - // MinTTL the is the default TTL of Resources records which did not - // contain a TTL value and the TTL of negative responses. (RFC 2308 - // Section 4) - MinTTL uint32 -} - -func (r *SOAResource) realType() Type { - return TypeSOA -} - -func (r *SOAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - oldMsg := msg - msg, err := packName(msg, r.NS, compression) - if err != nil { - return oldMsg, &nestedError{"SOAResource.NS", err} - } - msg, err = packName(msg, r.MBox, compression) - if err != nil { - return oldMsg, &nestedError{"SOAResource.MBox", err} - } - msg = packUint32(msg, r.Serial) - msg = packUint32(msg, r.Refresh) - msg = packUint32(msg, r.Retry) - msg = packUint32(msg, r.Expire) - return packUint32(msg, r.MinTTL), nil -} - -func unpackSOAResource(hdr ResourceHeader, msg []byte, off int) (*SOAResource, error) { - ns, off, err := unpackName(msg, off) - if err != nil { - return nil, &nestedError{"NS", err} - } - mbox, off, err := unpackName(msg, off) - if err != nil { - return nil, &nestedError{"MBox", err} - } - serial, off, err := unpackUint32(msg, off) - if err != nil { - return nil, &nestedError{"Serial", err} - } - refresh, off, err := unpackUint32(msg, off) - if err != nil { - return nil, &nestedError{"Refresh", err} - } - retry, off, err := unpackUint32(msg, off) - if err != nil { - return nil, &nestedError{"Retry", err} - } - expire, off, err := unpackUint32(msg, off) - if err != nil { - return nil, &nestedError{"Expire", err} - } - minTTL, _, err := unpackUint32(msg, off) - if err != nil { - return nil, &nestedError{"MinTTL", err} - } - return &SOAResource{hdr, ns, mbox, serial, refresh, retry, expire, minTTL}, nil -} - -// A TXTResource is a TXT Resource record. -type TXTResource struct { - ResourceHeader - - Txt string // Not a domain name. -} - -func (r *TXTResource) realType() Type { - return TypeTXT -} - -func (r *TXTResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packText(msg, r.Txt), nil -} - -func unpackTXTResource(hdr ResourceHeader, msg []byte, off int) (*TXTResource, error) { - var txt string - for n := uint16(0); n < hdr.Length; { - var t string - var err error - if t, off, err = unpackText(msg, off); err != nil { - return nil, &nestedError{"text", err} - } - // Check if we got too many bytes. - if hdr.Length-n < uint16(len(t))+1 { - return nil, errCalcLen - } - n += uint16(len(t)) + 1 - txt += t - } - return &TXTResource{hdr, txt}, nil -} - -// An SRVResource is an SRV Resource record. -type SRVResource struct { - ResourceHeader - - Priority uint16 - Weight uint16 - Port uint16 - Target string // Not compressed as per RFC 2782. -} - -func (r *SRVResource) realType() Type { - return TypeSRV -} - -func (r *SRVResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - oldMsg := msg - msg = packUint16(msg, r.Priority) - msg = packUint16(msg, r.Weight) - msg = packUint16(msg, r.Port) - msg, err := packName(msg, r.Target, nil) - if err != nil { - return oldMsg, &nestedError{"SRVResource.Target", err} - } - return msg, nil -} - -func unpackSRVResource(hdr ResourceHeader, msg []byte, off int) (*SRVResource, error) { - priority, off, err := unpackUint16(msg, off) - if err != nil { - return nil, &nestedError{"Priority", err} - } - weight, off, err := unpackUint16(msg, off) - if err != nil { - return nil, &nestedError{"Weight", err} - } - port, off, err := unpackUint16(msg, off) - if err != nil { - return nil, &nestedError{"Port", err} - } - target, _, err := unpackName(msg, off) - if err != nil { - return nil, &nestedError{"Target", err} - } - return &SRVResource{hdr, priority, weight, port, target}, nil -} - -// An AResource is an A Resource record. -type AResource struct { - ResourceHeader - - A [4]byte -} - -func (r *AResource) realType() Type { - return TypeA -} - -func (r *AResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packBytes(msg, r.A[:]), nil -} - -func unpackAResource(hdr ResourceHeader, msg []byte, off int) (*AResource, error) { - var a [4]byte - if _, err := unpackBytes(msg, off, a[:]); err != nil { - return nil, err - } - return &AResource{hdr, a}, nil -} - -// An AAAAResource is an AAAA Resource record. -type AAAAResource struct { - ResourceHeader - - AAAA [16]byte -} - -func (r *AAAAResource) realType() Type { - return TypeAAAA -} - -func (r *AAAAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packBytes(msg, r.AAAA[:]), nil -} - -func unpackAAAAResource(hdr ResourceHeader, msg []byte, off int) (*AAAAResource, error) { - var aaaa [16]byte - if _, err := unpackBytes(msg, off, aaaa[:]); err != nil { - return nil, err - } - return &AAAAResource{hdr, aaaa}, nil -} diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go index 6bfa8660198..cc5dc5dbcee 100644 --- a/vendor/golang.org/x/net/html/atom/gen.go +++ b/vendor/golang.org/x/net/html/atom/gen.go @@ -4,17 +4,17 @@ // +build ignore -package main +//go:generate go run gen.go +//go:generate go run gen.go -test -// This program generates table.go and table_test.go. -// Invoke as -// -// go run gen.go |gofmt >table.go -// go run gen.go -test |gofmt >table_test.go +package main import ( + "bytes" "flag" "fmt" + "go/format" + "io/ioutil" "math/rand" "os" "sort" @@ -42,6 +42,18 @@ func identifier(s string) string { var test = flag.Bool("test", false, "generate table_test.go") +func genFile(name string, buf *bytes.Buffer) { + b, err := format.Source(buf.Bytes()) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err := ioutil.WriteFile(name, b, 0644); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + func main() { flag.Parse() @@ -52,32 +64,31 @@ func main() { all = append(all, extra...) sort.Strings(all) - if *test { - fmt.Printf("// generated by go run gen.go -test; DO NOT EDIT\n\n") - fmt.Printf("package atom\n\n") - fmt.Printf("var testAtomList = []string{\n") - for _, s := range all { - fmt.Printf("\t%q,\n", s) - } - fmt.Printf("}\n") - return - } - // uniq - lists have dups - // compute max len too - maxLen := 0 w := 0 for _, s := range all { if w == 0 || all[w-1] != s { - if maxLen < len(s) { - maxLen = len(s) - } all[w] = s w++ } } all = all[:w] + if *test { + var buf bytes.Buffer + fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") + fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") + fmt.Fprintln(&buf, "package atom\n") + fmt.Fprintln(&buf, "var testAtomList = []string{") + for _, s := range all { + fmt.Fprintf(&buf, "\t%q,\n", s) + } + fmt.Fprintln(&buf, "}") + + genFile("table_test.go", &buf) + return + } + // Find hash that minimizes table size. var best *table for i := 0; i < 1000000; i++ { @@ -163,36 +174,46 @@ func main() { atom[s] = uint32(off<<8 | len(s)) } + var buf bytes.Buffer // Generate the Go code. - fmt.Printf("// generated by go run gen.go; DO NOT EDIT\n\n") - fmt.Printf("package atom\n\nconst (\n") + fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") + fmt.Fprintln(&buf, "//go:generate go run gen.go\n") + fmt.Fprintln(&buf, "package atom\n\nconst (") + + // compute max len + maxLen := 0 for _, s := range all { - fmt.Printf("\t%s Atom = %#x\n", identifier(s), atom[s]) + if maxLen < len(s) { + maxLen = len(s) + } + fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) } - fmt.Printf(")\n\n") + fmt.Fprintln(&buf, ")\n") - fmt.Printf("const hash0 = %#x\n\n", best.h0) - fmt.Printf("const maxAtomLen = %d\n\n", maxLen) + fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) + fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) - fmt.Printf("var table = [1<<%d]Atom{\n", best.k) + fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) for i, s := range best.tab { if s == "" { continue } - fmt.Printf("\t%#x: %#x, // %s\n", i, atom[s], s) + fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) } - fmt.Printf("}\n") + fmt.Fprintf(&buf, "}\n") datasize := (1 << best.k) * 4 - fmt.Printf("const atomText =\n") + fmt.Fprintln(&buf, "const atomText =") textsize := len(text) for len(text) > 60 { - fmt.Printf("\t%q +\n", text[:60]) + fmt.Fprintf(&buf, "\t%q +\n", text[:60]) text = text[60:] } - fmt.Printf("\t%q\n\n", text) + fmt.Fprintf(&buf, "\t%q\n\n", text) + + genFile("table.go", &buf) - fmt.Fprintf(os.Stderr, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) + fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) } type byLen []string @@ -285,8 +306,10 @@ func (t *table) push(i uint32, depth int) bool { // The lists of element names and attribute keys were taken from // https://html.spec.whatwg.org/multipage/indices.html#index -// as of the "HTML Living Standard - Last Updated 21 February 2015" version. +// as of the "HTML Living Standard - Last Updated 18 September 2017" version. +// "command", "keygen" and "menuitem" have been removed from the spec, +// but are kept here for backwards compatibility. var elements = []string{ "a", "abbr", @@ -349,6 +372,7 @@ var elements = []string{ "legend", "li", "link", + "main", "map", "mark", "menu", @@ -364,6 +388,7 @@ var elements = []string{ "output", "p", "param", + "picture", "pre", "progress", "q", @@ -375,6 +400,7 @@ var elements = []string{ "script", "section", "select", + "slot", "small", "source", "span", @@ -403,14 +429,21 @@ var elements = []string{ } // https://html.spec.whatwg.org/multipage/indices.html#attributes-3 - +// +// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup", +// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec, +// but are kept here for backwards compatibility. var attributes = []string{ "abbr", "accept", "accept-charset", "accesskey", "action", + "allowfullscreen", + "allowpaymentrequest", + "allowusermedia", "alt", + "as", "async", "autocomplete", "autofocus", @@ -420,6 +453,7 @@ var attributes = []string{ "checked", "cite", "class", + "color", "cols", "colspan", "command", @@ -457,6 +491,8 @@ var attributes = []string{ "icon", "id", "inputmode", + "integrity", + "is", "ismap", "itemid", "itemprop", @@ -481,16 +517,20 @@ var attributes = []string{ "multiple", "muted", "name", + "nomodule", + "nonce", "novalidate", "open", "optimum", "pattern", "ping", "placeholder", + "playsinline", "poster", "preload", "radiogroup", "readonly", + "referrerpolicy", "rel", "required", "reversed", @@ -507,10 +547,13 @@ var attributes = []string{ "sizes", "sortable", "sorted", + "slot", "span", + "spellcheck", "src", "srcdoc", "srclang", + "srcset", "start", "step", "style", @@ -520,16 +563,22 @@ var attributes = []string{ "translate", "type", "typemustmatch", + "updateviacache", "usemap", "value", "width", + "workertype", "wrap", } +// "onautocomplete", "onautocompleteerror", "onmousewheel", +// "onshow" and "onsort" have been removed from the spec, +// but are kept here for backwards compatibility. var eventHandlers = []string{ "onabort", "onautocomplete", "onautocompleteerror", + "onauxclick", "onafterprint", "onbeforeprint", "onbeforeunload", @@ -541,11 +590,14 @@ var eventHandlers = []string{ "onclick", "onclose", "oncontextmenu", + "oncopy", "oncuechange", + "oncut", "ondblclick", "ondrag", "ondragend", "ondragenter", + "ondragexit", "ondragleave", "ondragover", "ondragstart", @@ -565,18 +617,24 @@ var eventHandlers = []string{ "onload", "onloadeddata", "onloadedmetadata", + "onloadend", "onloadstart", "onmessage", + "onmessageerror", "onmousedown", + "onmouseenter", + "onmouseleave", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmousewheel", + "onwheel", "onoffline", "ononline", "onpagehide", "onpageshow", + "onpaste", "onpause", "onplay", "onplaying", @@ -585,7 +643,9 @@ var eventHandlers = []string{ "onratechange", "onreset", "onresize", + "onrejectionhandled", "onscroll", + "onsecuritypolicyviolation", "onseeked", "onseeking", "onselect", @@ -597,6 +657,7 @@ var eventHandlers = []string{ "onsuspend", "ontimeupdate", "ontoggle", + "onunhandledrejection", "onunload", "onvolumechange", "onwaiting", diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go index 2605ba3102f..f74018ecea1 100644 --- a/vendor/golang.org/x/net/html/atom/table.go +++ b/vendor/golang.org/x/net/html/atom/table.go @@ -1,713 +1,777 @@ -// generated by go run gen.go; DO NOT EDIT +// Code generated by go generate gen.go; DO NOT EDIT. + +//go:generate go run gen.go package atom const ( - A Atom = 0x1 - Abbr Atom = 0x4 - Accept Atom = 0x2106 - AcceptCharset Atom = 0x210e - Accesskey Atom = 0x3309 - Action Atom = 0x1f606 - Address Atom = 0x4f307 - Align Atom = 0x1105 - Alt Atom = 0x4503 - Annotation Atom = 0x1670a - AnnotationXml Atom = 0x1670e - Applet Atom = 0x2b306 - Area Atom = 0x2fa04 - Article Atom = 0x38807 - Aside Atom = 0x8305 - Async Atom = 0x7b05 - Audio Atom = 0xa605 - Autocomplete Atom = 0x1fc0c - Autofocus Atom = 0xb309 - Autoplay Atom = 0xce08 - B Atom = 0x101 - Base Atom = 0xd604 - Basefont Atom = 0xd608 - Bdi Atom = 0x1a03 - Bdo Atom = 0xe703 - Bgsound Atom = 0x11807 - Big Atom = 0x12403 - Blink Atom = 0x12705 - Blockquote Atom = 0x12c0a - Body Atom = 0x2f04 - Br Atom = 0x202 - Button Atom = 0x13606 - Canvas Atom = 0x7f06 - Caption Atom = 0x1bb07 - Center Atom = 0x5b506 - Challenge Atom = 0x21f09 - Charset Atom = 0x2807 - Checked Atom = 0x32807 - Cite Atom = 0x3c804 - Class Atom = 0x4de05 - Code Atom = 0x14904 - Col Atom = 0x15003 - Colgroup Atom = 0x15008 - Color Atom = 0x15d05 - Cols Atom = 0x16204 - Colspan Atom = 0x16207 - Command Atom = 0x17507 - Content Atom = 0x42307 - Contenteditable Atom = 0x4230f - Contextmenu Atom = 0x3310b - Controls Atom = 0x18808 - Coords Atom = 0x19406 - Crossorigin Atom = 0x19f0b - Data Atom = 0x44a04 - Datalist Atom = 0x44a08 - Datetime Atom = 0x23c08 - Dd Atom = 0x26702 - Default Atom = 0x8607 - Defer Atom = 0x14b05 - Del Atom = 0x3ef03 - Desc Atom = 0x4db04 - Details Atom = 0x4807 - Dfn Atom = 0x6103 - Dialog Atom = 0x1b06 - Dir Atom = 0x6903 - Dirname Atom = 0x6907 - Disabled Atom = 0x10c08 - Div Atom = 0x11303 - Dl Atom = 0x11e02 - Download Atom = 0x40008 - Draggable Atom = 0x17b09 - Dropzone Atom = 0x39108 - Dt Atom = 0x50902 - Em Atom = 0x6502 - Embed Atom = 0x6505 - Enctype Atom = 0x21107 - Face Atom = 0x5b304 - Fieldset Atom = 0x1b008 - Figcaption Atom = 0x1b80a - Figure Atom = 0x1cc06 - Font Atom = 0xda04 - Footer Atom = 0x8d06 - For Atom = 0x1d803 - ForeignObject Atom = 0x1d80d - Foreignobject Atom = 0x1e50d - Form Atom = 0x1f204 - Formaction Atom = 0x1f20a - Formenctype Atom = 0x20d0b - Formmethod Atom = 0x2280a - Formnovalidate Atom = 0x2320e - Formtarget Atom = 0x2470a - Frame Atom = 0x9a05 - Frameset Atom = 0x9a08 - H1 Atom = 0x26e02 - H2 Atom = 0x29402 - H3 Atom = 0x2a702 - H4 Atom = 0x2e902 - H5 Atom = 0x2f302 - H6 Atom = 0x50b02 - Head Atom = 0x2d504 - Header Atom = 0x2d506 - Headers Atom = 0x2d507 - Height Atom = 0x25106 - Hgroup Atom = 0x25906 - Hidden Atom = 0x26506 - High Atom = 0x26b04 - Hr Atom = 0x27002 - Href Atom = 0x27004 - Hreflang Atom = 0x27008 - Html Atom = 0x25504 - HttpEquiv Atom = 0x2780a - I Atom = 0x601 - Icon Atom = 0x42204 - Id Atom = 0x8502 - Iframe Atom = 0x29606 - Image Atom = 0x29c05 - Img Atom = 0x2a103 - Input Atom = 0x3e805 - Inputmode Atom = 0x3e809 - Ins Atom = 0x1a803 - Isindex Atom = 0x2a907 - Ismap Atom = 0x2b005 - Itemid Atom = 0x33c06 - Itemprop Atom = 0x3c908 - Itemref Atom = 0x5ad07 - Itemscope Atom = 0x2b909 - Itemtype Atom = 0x2c308 - Kbd Atom = 0x1903 - Keygen Atom = 0x3906 - Keytype Atom = 0x53707 - Kind Atom = 0x10904 - Label Atom = 0xf005 - Lang Atom = 0x27404 - Legend Atom = 0x18206 - Li Atom = 0x1202 - Link Atom = 0x12804 - List Atom = 0x44e04 - Listing Atom = 0x44e07 - Loop Atom = 0xf404 - Low Atom = 0x11f03 - Malignmark Atom = 0x100a - Manifest Atom = 0x5f108 - Map Atom = 0x2b203 - Mark Atom = 0x1604 - Marquee Atom = 0x2cb07 - Math Atom = 0x2d204 - Max Atom = 0x2e103 - Maxlength Atom = 0x2e109 - Media Atom = 0x6e05 - Mediagroup Atom = 0x6e0a - Menu Atom = 0x33804 - Menuitem Atom = 0x33808 - Meta Atom = 0x45d04 - Meter Atom = 0x24205 - Method Atom = 0x22c06 - Mglyph Atom = 0x2a206 - Mi Atom = 0x2eb02 - Min Atom = 0x2eb03 - Minlength Atom = 0x2eb09 - Mn Atom = 0x23502 - Mo Atom = 0x3ed02 - Ms Atom = 0x2bc02 - Mtext Atom = 0x2f505 - Multiple Atom = 0x30308 - Muted Atom = 0x30b05 - Name Atom = 0x6c04 - Nav Atom = 0x3e03 - Nobr Atom = 0x5704 - Noembed Atom = 0x6307 - Noframes Atom = 0x9808 - Noscript Atom = 0x3d208 - Novalidate Atom = 0x2360a - Object Atom = 0x1ec06 - Ol Atom = 0xc902 - Onabort Atom = 0x13a07 - Onafterprint Atom = 0x1c00c - Onautocomplete Atom = 0x1fa0e - Onautocompleteerror Atom = 0x1fa13 - Onbeforeprint Atom = 0x6040d - Onbeforeunload Atom = 0x4e70e - Onblur Atom = 0xaa06 - Oncancel Atom = 0xe908 - Oncanplay Atom = 0x28509 - Oncanplaythrough Atom = 0x28510 - Onchange Atom = 0x3a708 - Onclick Atom = 0x31007 - Onclose Atom = 0x31707 - Oncontextmenu Atom = 0x32f0d - Oncuechange Atom = 0x3420b - Ondblclick Atom = 0x34d0a - Ondrag Atom = 0x35706 - Ondragend Atom = 0x35709 - Ondragenter Atom = 0x3600b - Ondragleave Atom = 0x36b0b - Ondragover Atom = 0x3760a - Ondragstart Atom = 0x3800b - Ondrop Atom = 0x38f06 - Ondurationchange Atom = 0x39f10 - Onemptied Atom = 0x39609 - Onended Atom = 0x3af07 - Onerror Atom = 0x3b607 - Onfocus Atom = 0x3bd07 - Onhashchange Atom = 0x3da0c - Oninput Atom = 0x3e607 - Oninvalid Atom = 0x3f209 - Onkeydown Atom = 0x3fb09 - Onkeypress Atom = 0x4080a - Onkeyup Atom = 0x41807 - Onlanguagechange Atom = 0x43210 - Onload Atom = 0x44206 - Onloadeddata Atom = 0x4420c - Onloadedmetadata Atom = 0x45510 - Onloadstart Atom = 0x46b0b - Onmessage Atom = 0x47609 - Onmousedown Atom = 0x47f0b - Onmousemove Atom = 0x48a0b - Onmouseout Atom = 0x4950a - Onmouseover Atom = 0x4a20b - Onmouseup Atom = 0x4ad09 - Onmousewheel Atom = 0x4b60c - Onoffline Atom = 0x4c209 - Ononline Atom = 0x4cb08 - Onpagehide Atom = 0x4d30a - Onpageshow Atom = 0x4fe0a - Onpause Atom = 0x50d07 - Onplay Atom = 0x51706 - Onplaying Atom = 0x51709 - Onpopstate Atom = 0x5200a - Onprogress Atom = 0x52a0a - Onratechange Atom = 0x53e0c - Onreset Atom = 0x54a07 - Onresize Atom = 0x55108 - Onscroll Atom = 0x55f08 - Onseeked Atom = 0x56708 - Onseeking Atom = 0x56f09 - Onselect Atom = 0x57808 - Onshow Atom = 0x58206 - Onsort Atom = 0x58b06 - Onstalled Atom = 0x59509 - Onstorage Atom = 0x59e09 - Onsubmit Atom = 0x5a708 - Onsuspend Atom = 0x5bb09 - Ontimeupdate Atom = 0xdb0c - Ontoggle Atom = 0x5c408 - Onunload Atom = 0x5cc08 - Onvolumechange Atom = 0x5d40e - Onwaiting Atom = 0x5e209 - Open Atom = 0x3cf04 - Optgroup Atom = 0xf608 - Optimum Atom = 0x5eb07 - Option Atom = 0x60006 - Output Atom = 0x49c06 - P Atom = 0xc01 - Param Atom = 0xc05 - Pattern Atom = 0x5107 - Ping Atom = 0x7704 - Placeholder Atom = 0xc30b - Plaintext Atom = 0xfd09 - Poster Atom = 0x15706 - Pre Atom = 0x25e03 - Preload Atom = 0x25e07 - Progress Atom = 0x52c08 - Prompt Atom = 0x5fa06 - Public Atom = 0x41e06 - Q Atom = 0x13101 - Radiogroup Atom = 0x30a - Readonly Atom = 0x2fb08 - Rel Atom = 0x25f03 - Required Atom = 0x1d008 - Reversed Atom = 0x5a08 - Rows Atom = 0x9204 - Rowspan Atom = 0x9207 - Rp Atom = 0x1c602 - Rt Atom = 0x13f02 - Ruby Atom = 0xaf04 - S Atom = 0x2c01 - Samp Atom = 0x4e04 - Sandbox Atom = 0xbb07 - Scope Atom = 0x2bd05 - Scoped Atom = 0x2bd06 - Script Atom = 0x3d406 - Seamless Atom = 0x31c08 - Section Atom = 0x4e207 - Select Atom = 0x57a06 - Selected Atom = 0x57a08 - Shape Atom = 0x4f905 - Size Atom = 0x55504 - Sizes Atom = 0x55505 - Small Atom = 0x18f05 - Sortable Atom = 0x58d08 - Sorted Atom = 0x19906 - Source Atom = 0x1aa06 - Spacer Atom = 0x2db06 - Span Atom = 0x9504 - Spellcheck Atom = 0x3230a - Src Atom = 0x3c303 - Srcdoc Atom = 0x3c306 - Srclang Atom = 0x41107 - Start Atom = 0x38605 - Step Atom = 0x5f704 - Strike Atom = 0x53306 - Strong Atom = 0x55906 - Style Atom = 0x61105 - Sub Atom = 0x5a903 - Summary Atom = 0x61607 - Sup Atom = 0x61d03 - Svg Atom = 0x62003 - System Atom = 0x62306 - Tabindex Atom = 0x46308 - Table Atom = 0x42d05 - Target Atom = 0x24b06 - Tbody Atom = 0x2e05 - Td Atom = 0x4702 - Template Atom = 0x62608 - Textarea Atom = 0x2f608 - Tfoot Atom = 0x8c05 - Th Atom = 0x22e02 - Thead Atom = 0x2d405 - Time Atom = 0xdd04 - Title Atom = 0xa105 - Tr Atom = 0x10502 - Track Atom = 0x10505 - Translate Atom = 0x14009 - Tt Atom = 0x5302 - Type Atom = 0x21404 - Typemustmatch Atom = 0x2140d - U Atom = 0xb01 - Ul Atom = 0x8a02 - Usemap Atom = 0x51106 - Value Atom = 0x4005 - Var Atom = 0x11503 - Video Atom = 0x28105 - Wbr Atom = 0x12103 - Width Atom = 0x50705 - Wrap Atom = 0x58704 - Xmp Atom = 0xc103 + A Atom = 0x1 + Abbr Atom = 0x4 + Accept Atom = 0x1a06 + AcceptCharset Atom = 0x1a0e + Accesskey Atom = 0x2c09 + Action Atom = 0x25a06 + Address Atom = 0x6ed07 + Align Atom = 0x6d405 + Allowfullscreen Atom = 0x1f00f + Allowpaymentrequest Atom = 0x6913 + Allowusermedia Atom = 0x850e + Alt Atom = 0xb003 + Annotation Atom = 0x1b90a + AnnotationXml Atom = 0x1b90e + Applet Atom = 0x30106 + Area Atom = 0x34a04 + Article Atom = 0x3f007 + As Atom = 0xb902 + Aside Atom = 0xc105 + Async Atom = 0xb905 + Audio Atom = 0xcf05 + Autocomplete Atom = 0x2600c + Autofocus Atom = 0xeb09 + Autoplay Atom = 0x10608 + B Atom = 0x101 + Base Atom = 0x11504 + Basefont Atom = 0x11508 + Bdi Atom = 0x16103 + Bdo Atom = 0x13403 + Bgsound Atom = 0x14707 + Big Atom = 0x15903 + Blink Atom = 0x15c05 + Blockquote Atom = 0x1680a + Body Atom = 0x2804 + Br Atom = 0x202 + Button Atom = 0x17206 + Canvas Atom = 0xbd06 + Caption Atom = 0x21907 + Center Atom = 0x20806 + Challenge Atom = 0x28309 + Charset Atom = 0x2107 + Checked Atom = 0x46d07 + Cite Atom = 0x55804 + Class Atom = 0x5b905 + Code Atom = 0x19004 + Col Atom = 0x19703 + Colgroup Atom = 0x19708 + Color Atom = 0x1af05 + Cols Atom = 0x1b404 + Colspan Atom = 0x1b407 + Command Atom = 0x1c707 + Content Atom = 0x57f07 + Contenteditable Atom = 0x57f0f + Contextmenu Atom = 0x3740b + Controls Atom = 0x1ce08 + Coords Atom = 0x1da06 + Crossorigin Atom = 0x1e30b + Data Atom = 0x49904 + Datalist Atom = 0x49908 + Datetime Atom = 0x2a008 + Dd Atom = 0x2bf02 + Default Atom = 0xc407 + Defer Atom = 0x19205 + Del Atom = 0x44603 + Desc Atom = 0x55504 + Details Atom = 0x4607 + Dfn Atom = 0x5f03 + Dialog Atom = 0x16206 + Dir Atom = 0xa303 + Dirname Atom = 0xa307 + Disabled Atom = 0x14d08 + Div Atom = 0x15403 + Dl Atom = 0x5e202 + Download Atom = 0x45708 + Draggable Atom = 0x18309 + Dropzone Atom = 0x3f908 + Dt Atom = 0x64702 + Em Atom = 0x4202 + Embed Atom = 0x4205 + Enctype Atom = 0x27507 + Face Atom = 0x20604 + Fieldset Atom = 0x20e08 + Figcaption Atom = 0x2160a + Figure Atom = 0x23006 + Font Atom = 0x11904 + Footer Atom = 0xb306 + For Atom = 0x23c03 + ForeignObject Atom = 0x23c0d + Foreignobject Atom = 0x2490d + Form Atom = 0x25604 + Formaction Atom = 0x2560a + Formenctype Atom = 0x2710b + Formmethod Atom = 0x28c0a + Formnovalidate Atom = 0x2960e + Formtarget Atom = 0x2a80a + Frame Atom = 0x5705 + Frameset Atom = 0x5708 + H1 Atom = 0x14502 + H2 Atom = 0x2c602 + H3 Atom = 0x2f502 + H4 Atom = 0x33902 + H5 Atom = 0x34302 + H6 Atom = 0x64902 + Head Atom = 0x32504 + Header Atom = 0x32506 + Headers Atom = 0x32507 + Height Atom = 0x12c06 + Hgroup Atom = 0x2b206 + Hidden Atom = 0x2bd06 + High Atom = 0x2c304 + Hr Atom = 0x14002 + Href Atom = 0x2c804 + Hreflang Atom = 0x2c808 + Html Atom = 0x13004 + HttpEquiv Atom = 0x2d00a + I Atom = 0x601 + Icon Atom = 0x57e04 + Id Atom = 0xc302 + Iframe Atom = 0x2e406 + Image Atom = 0x2ea05 + Img Atom = 0x2ef03 + Input Atom = 0x43f05 + Inputmode Atom = 0x43f09 + Ins Atom = 0x1ec03 + Integrity Atom = 0x22709 + Is Atom = 0x14e02 + Isindex Atom = 0x2f707 + Ismap Atom = 0x2fe05 + Itemid Atom = 0x37f06 + Itemprop Atom = 0x55908 + Itemref Atom = 0x3c107 + Itemscope Atom = 0x66d09 + Itemtype Atom = 0x30708 + Kbd Atom = 0x16003 + Keygen Atom = 0x3206 + Keytype Atom = 0x7e07 + Kind Atom = 0x18004 + Label Atom = 0xda05 + Lang Atom = 0x2cc04 + Legend Atom = 0x18a06 + Li Atom = 0x11102 + Link Atom = 0x15d04 + List Atom = 0x49d04 + Listing Atom = 0x49d07 + Loop Atom = 0xde04 + Low Atom = 0x6b03 + Main Atom = 0x1004 + Malignmark Atom = 0x6d30a + Manifest Atom = 0x30f08 + Map Atom = 0x30003 + Mark Atom = 0x6d904 + Marquee Atom = 0x31b07 + Math Atom = 0x32204 + Max Atom = 0x33103 + Maxlength Atom = 0x33109 + Media Atom = 0x8e05 + Mediagroup Atom = 0x8e0a + Menu Atom = 0x37b04 + Menuitem Atom = 0x37b08 + Meta Atom = 0x4ac04 + Meter Atom = 0xa805 + Method Atom = 0x29006 + Mglyph Atom = 0x2f006 + Mi Atom = 0x33b02 + Min Atom = 0x33b03 + Minlength Atom = 0x33b09 + Mn Atom = 0x29902 + Mo Atom = 0x6302 + Ms Atom = 0x67002 + Mtext Atom = 0x34505 + Multiple Atom = 0x35308 + Muted Atom = 0x35b05 + Name Atom = 0xa604 + Nav Atom = 0x1303 + Nobr Atom = 0x3704 + Noembed Atom = 0x4007 + Noframes Atom = 0x5508 + Nomodule Atom = 0x6108 + Nonce Atom = 0x56205 + Noscript Atom = 0x1fe08 + Novalidate Atom = 0x29a0a + Object Atom = 0x25006 + Ol Atom = 0x10102 + Onabort Atom = 0x17607 + Onafterprint Atom = 0x21e0c + Onautocomplete Atom = 0x25e0e + Onautocompleteerror Atom = 0x25e13 + Onauxclick Atom = 0x61b0a + Onbeforeprint Atom = 0x69a0d + Onbeforeunload Atom = 0x6e10e + Onblur Atom = 0x5c206 + Oncancel Atom = 0xd308 + Oncanplay Atom = 0x13609 + Oncanplaythrough Atom = 0x13610 + Onchange Atom = 0x40f08 + Onclick Atom = 0x2dd07 + Onclose Atom = 0x36007 + Oncontextmenu Atom = 0x3720d + Oncopy Atom = 0x38506 + Oncuechange Atom = 0x38b0b + Oncut Atom = 0x39605 + Ondblclick Atom = 0x39b0a + Ondrag Atom = 0x3a506 + Ondragend Atom = 0x3a509 + Ondragenter Atom = 0x3ae0b + Ondragexit Atom = 0x3b90a + Ondragleave Atom = 0x3d30b + Ondragover Atom = 0x3de0a + Ondragstart Atom = 0x3e80b + Ondrop Atom = 0x3f706 + Ondurationchange Atom = 0x40710 + Onemptied Atom = 0x3fe09 + Onended Atom = 0x41707 + Onerror Atom = 0x41e07 + Onfocus Atom = 0x42507 + Onhashchange Atom = 0x4310c + Oninput Atom = 0x43d07 + Oninvalid Atom = 0x44909 + Onkeydown Atom = 0x45209 + Onkeypress Atom = 0x45f0a + Onkeyup Atom = 0x47407 + Onlanguagechange Atom = 0x48110 + Onload Atom = 0x49106 + Onloadeddata Atom = 0x4910c + Onloadedmetadata Atom = 0x4a410 + Onloadend Atom = 0x4ba09 + Onloadstart Atom = 0x4c30b + Onmessage Atom = 0x4ce09 + Onmessageerror Atom = 0x4ce0e + Onmousedown Atom = 0x4dc0b + Onmouseenter Atom = 0x4e70c + Onmouseleave Atom = 0x4f30c + Onmousemove Atom = 0x4ff0b + Onmouseout Atom = 0x50a0a + Onmouseover Atom = 0x5170b + Onmouseup Atom = 0x52209 + Onmousewheel Atom = 0x5300c + Onoffline Atom = 0x53c09 + Ononline Atom = 0x54508 + Onpagehide Atom = 0x54d0a + Onpageshow Atom = 0x5670a + Onpaste Atom = 0x57307 + Onpause Atom = 0x58e07 + Onplay Atom = 0x59806 + Onplaying Atom = 0x59809 + Onpopstate Atom = 0x5a10a + Onprogress Atom = 0x5ab0a + Onratechange Atom = 0x5c80c + Onrejectionhandled Atom = 0x5d412 + Onreset Atom = 0x5e607 + Onresize Atom = 0x5ed08 + Onscroll Atom = 0x5fc08 + Onsecuritypolicyviolation Atom = 0x60419 + Onseeked Atom = 0x62508 + Onseeking Atom = 0x62d09 + Onselect Atom = 0x63608 + Onshow Atom = 0x64006 + Onsort Atom = 0x64b06 + Onstalled Atom = 0x65509 + Onstorage Atom = 0x65e09 + Onsubmit Atom = 0x66708 + Onsuspend Atom = 0x67709 + Ontimeupdate Atom = 0x11a0c + Ontoggle Atom = 0x68008 + Onunhandledrejection Atom = 0x68814 + Onunload Atom = 0x6a708 + Onvolumechange Atom = 0x6af0e + Onwaiting Atom = 0x6bd09 + Onwheel Atom = 0x6c607 + Open Atom = 0x55f04 + Optgroup Atom = 0xe008 + Optimum Atom = 0x6cd07 + Option Atom = 0x6dd06 + Output Atom = 0x51106 + P Atom = 0xc01 + Param Atom = 0xc05 + Pattern Atom = 0x4f07 + Picture Atom = 0x9707 + Ping Atom = 0xe704 + Placeholder Atom = 0xfb0b + Plaintext Atom = 0x19e09 + Playsinline Atom = 0x10a0b + Poster Atom = 0x2b706 + Pre Atom = 0x46403 + Preload Atom = 0x47a07 + Progress Atom = 0x5ad08 + Prompt Atom = 0x52a06 + Public Atom = 0x57a06 + Q Atom = 0x7701 + Radiogroup Atom = 0x30a + Readonly Atom = 0x34b08 + Referrerpolicy Atom = 0x3c50e + Rel Atom = 0x47b03 + Required Atom = 0x23408 + Reversed Atom = 0x9c08 + Rows Atom = 0x3a04 + Rowspan Atom = 0x3a07 + Rp Atom = 0x22402 + Rt Atom = 0x17b02 + Ruby Atom = 0xac04 + S Atom = 0x2501 + Samp Atom = 0x4c04 + Sandbox Atom = 0xf307 + Scope Atom = 0x67105 + Scoped Atom = 0x67106 + Script Atom = 0x20006 + Seamless Atom = 0x36508 + Section Atom = 0x5bd07 + Select Atom = 0x63806 + Selected Atom = 0x63808 + Shape Atom = 0x1d505 + Size Atom = 0x5f104 + Sizes Atom = 0x5f105 + Slot Atom = 0x1df04 + Small Atom = 0x1ee05 + Sortable Atom = 0x64d08 + Sorted Atom = 0x32b06 + Source Atom = 0x36c06 + Spacer Atom = 0x42b06 + Span Atom = 0x3d04 + Spellcheck Atom = 0x4680a + Src Atom = 0x5b403 + Srcdoc Atom = 0x5b406 + Srclang Atom = 0x5f507 + Srcset Atom = 0x6f306 + Start Atom = 0x3ee05 + Step Atom = 0x57704 + Strike Atom = 0x7a06 + Strong Atom = 0x31506 + Style Atom = 0x6f905 + Sub Atom = 0x66903 + Summary Atom = 0x6fe07 + Sup Atom = 0x70503 + Svg Atom = 0x70803 + System Atom = 0x70b06 + Tabindex Atom = 0x4b208 + Table Atom = 0x58905 + Target Atom = 0x2ac06 + Tbody Atom = 0x2705 + Td Atom = 0x5e02 + Template Atom = 0x70e08 + Textarea Atom = 0x34608 + Tfoot Atom = 0xb205 + Th Atom = 0x13f02 + Thead Atom = 0x32405 + Time Atom = 0x11c04 + Title Atom = 0xca05 + Tr Atom = 0x7402 + Track Atom = 0x17c05 + Translate Atom = 0x1a609 + Tt Atom = 0x5102 + Type Atom = 0x8104 + Typemustmatch Atom = 0x2780d + U Atom = 0xb01 + Ul Atom = 0x6602 + Updateviacache Atom = 0x1200e + Usemap Atom = 0x59206 + Value Atom = 0x1505 + Var Atom = 0x15603 + Video Atom = 0x2d905 + Wbr Atom = 0x57003 + Width Atom = 0x64505 + Workertype Atom = 0x7160a + Wrap Atom = 0x72004 + Xmp Atom = 0xf903 ) -const hash0 = 0xc17da63e +const hash0 = 0x81cdf10e -const maxAtomLen = 19 +const maxAtomLen = 25 var table = [1 << 9]Atom{ - 0x1: 0x48a0b, // onmousemove - 0x2: 0x5e209, // onwaiting - 0x3: 0x1fa13, // onautocompleteerror - 0x4: 0x5fa06, // prompt - 0x7: 0x5eb07, // optimum - 0x8: 0x1604, // mark - 0xa: 0x5ad07, // itemref - 0xb: 0x4fe0a, // onpageshow - 0xc: 0x57a06, // select - 0xd: 0x17b09, // draggable - 0xe: 0x3e03, // nav - 0xf: 0x17507, // command - 0x11: 0xb01, // u - 0x14: 0x2d507, // headers - 0x15: 0x44a08, // datalist - 0x17: 0x4e04, // samp - 0x1a: 0x3fb09, // onkeydown - 0x1b: 0x55f08, // onscroll - 0x1c: 0x15003, // col - 0x20: 0x3c908, // itemprop - 0x21: 0x2780a, // http-equiv - 0x22: 0x61d03, // sup - 0x24: 0x1d008, // required - 0x2b: 0x25e07, // preload - 0x2c: 0x6040d, // onbeforeprint - 0x2d: 0x3600b, // ondragenter - 0x2e: 0x50902, // dt - 0x2f: 0x5a708, // onsubmit - 0x30: 0x27002, // hr - 0x31: 0x32f0d, // oncontextmenu - 0x33: 0x29c05, // image - 0x34: 0x50d07, // onpause - 0x35: 0x25906, // hgroup - 0x36: 0x7704, // ping - 0x37: 0x57808, // onselect - 0x3a: 0x11303, // div - 0x3b: 0x1fa0e, // onautocomplete - 0x40: 0x2eb02, // mi - 0x41: 0x31c08, // seamless - 0x42: 0x2807, // charset - 0x43: 0x8502, // id - 0x44: 0x5200a, // onpopstate - 0x45: 0x3ef03, // del - 0x46: 0x2cb07, // marquee - 0x47: 0x3309, // accesskey - 0x49: 0x8d06, // footer - 0x4a: 0x44e04, // list - 0x4b: 0x2b005, // ismap - 0x51: 0x33804, // menu - 0x52: 0x2f04, // body - 0x55: 0x9a08, // frameset - 0x56: 0x54a07, // onreset - 0x57: 0x12705, // blink - 0x58: 0xa105, // title - 0x59: 0x38807, // article - 0x5b: 0x22e02, // th - 0x5d: 0x13101, // q - 0x5e: 0x3cf04, // open - 0x5f: 0x2fa04, // area - 0x61: 0x44206, // onload - 0x62: 0xda04, // font - 0x63: 0xd604, // base - 0x64: 0x16207, // colspan - 0x65: 0x53707, // keytype - 0x66: 0x11e02, // dl - 0x68: 0x1b008, // fieldset - 0x6a: 0x2eb03, // min - 0x6b: 0x11503, // var - 0x6f: 0x2d506, // header - 0x70: 0x13f02, // rt - 0x71: 0x15008, // colgroup - 0x72: 0x23502, // mn - 0x74: 0x13a07, // onabort - 0x75: 0x3906, // keygen - 0x76: 0x4c209, // onoffline - 0x77: 0x21f09, // challenge - 0x78: 0x2b203, // map - 0x7a: 0x2e902, // h4 - 0x7b: 0x3b607, // onerror - 0x7c: 0x2e109, // maxlength - 0x7d: 0x2f505, // mtext - 0x7e: 0xbb07, // sandbox - 0x7f: 0x58b06, // onsort - 0x80: 0x100a, // malignmark - 0x81: 0x45d04, // meta - 0x82: 0x7b05, // async - 0x83: 0x2a702, // h3 - 0x84: 0x26702, // dd - 0x85: 0x27004, // href - 0x86: 0x6e0a, // mediagroup - 0x87: 0x19406, // coords - 0x88: 0x41107, // srclang - 0x89: 0x34d0a, // ondblclick - 0x8a: 0x4005, // value - 0x8c: 0xe908, // oncancel - 0x8e: 0x3230a, // spellcheck - 0x8f: 0x9a05, // frame - 0x91: 0x12403, // big - 0x94: 0x1f606, // action - 0x95: 0x6903, // dir - 0x97: 0x2fb08, // readonly - 0x99: 0x42d05, // table - 0x9a: 0x61607, // summary - 0x9b: 0x12103, // wbr - 0x9c: 0x30a, // radiogroup - 0x9d: 0x6c04, // name - 0x9f: 0x62306, // system - 0xa1: 0x15d05, // color - 0xa2: 0x7f06, // canvas - 0xa3: 0x25504, // html - 0xa5: 0x56f09, // onseeking - 0xac: 0x4f905, // shape - 0xad: 0x25f03, // rel - 0xae: 0x28510, // oncanplaythrough - 0xaf: 0x3760a, // ondragover - 0xb0: 0x62608, // template - 0xb1: 0x1d80d, // foreignObject - 0xb3: 0x9204, // rows - 0xb6: 0x44e07, // listing - 0xb7: 0x49c06, // output - 0xb9: 0x3310b, // contextmenu - 0xbb: 0x11f03, // low - 0xbc: 0x1c602, // rp - 0xbd: 0x5bb09, // onsuspend - 0xbe: 0x13606, // button - 0xbf: 0x4db04, // desc - 0xc1: 0x4e207, // section - 0xc2: 0x52a0a, // onprogress - 0xc3: 0x59e09, // onstorage - 0xc4: 0x2d204, // math - 0xc5: 0x4503, // alt - 0xc7: 0x8a02, // ul - 0xc8: 0x5107, // pattern - 0xc9: 0x4b60c, // onmousewheel - 0xca: 0x35709, // ondragend - 0xcb: 0xaf04, // ruby - 0xcc: 0xc01, // p - 0xcd: 0x31707, // onclose - 0xce: 0x24205, // meter - 0xcf: 0x11807, // bgsound - 0xd2: 0x25106, // height - 0xd4: 0x101, // b - 0xd5: 0x2c308, // itemtype - 0xd8: 0x1bb07, // caption - 0xd9: 0x10c08, // disabled - 0xdb: 0x33808, // menuitem - 0xdc: 0x62003, // svg - 0xdd: 0x18f05, // small - 0xde: 0x44a04, // data - 0xe0: 0x4cb08, // ononline - 0xe1: 0x2a206, // mglyph - 0xe3: 0x6505, // embed - 0xe4: 0x10502, // tr - 0xe5: 0x46b0b, // onloadstart - 0xe7: 0x3c306, // srcdoc - 0xeb: 0x5c408, // ontoggle - 0xed: 0xe703, // bdo - 0xee: 0x4702, // td - 0xef: 0x8305, // aside - 0xf0: 0x29402, // h2 - 0xf1: 0x52c08, // progress - 0xf2: 0x12c0a, // blockquote - 0xf4: 0xf005, // label - 0xf5: 0x601, // i - 0xf7: 0x9207, // rowspan - 0xfb: 0x51709, // onplaying - 0xfd: 0x2a103, // img - 0xfe: 0xf608, // optgroup - 0xff: 0x42307, // content - 0x101: 0x53e0c, // onratechange - 0x103: 0x3da0c, // onhashchange - 0x104: 0x4807, // details - 0x106: 0x40008, // download - 0x109: 0x14009, // translate - 0x10b: 0x4230f, // contenteditable - 0x10d: 0x36b0b, // ondragleave - 0x10e: 0x2106, // accept - 0x10f: 0x57a08, // selected - 0x112: 0x1f20a, // formaction - 0x113: 0x5b506, // center - 0x115: 0x45510, // onloadedmetadata - 0x116: 0x12804, // link - 0x117: 0xdd04, // time - 0x118: 0x19f0b, // crossorigin - 0x119: 0x3bd07, // onfocus - 0x11a: 0x58704, // wrap - 0x11b: 0x42204, // icon - 0x11d: 0x28105, // video - 0x11e: 0x4de05, // class - 0x121: 0x5d40e, // onvolumechange - 0x122: 0xaa06, // onblur - 0x123: 0x2b909, // itemscope - 0x124: 0x61105, // style - 0x127: 0x41e06, // public - 0x129: 0x2320e, // formnovalidate - 0x12a: 0x58206, // onshow - 0x12c: 0x51706, // onplay - 0x12d: 0x3c804, // cite - 0x12e: 0x2bc02, // ms - 0x12f: 0xdb0c, // ontimeupdate - 0x130: 0x10904, // kind - 0x131: 0x2470a, // formtarget - 0x135: 0x3af07, // onended - 0x136: 0x26506, // hidden - 0x137: 0x2c01, // s - 0x139: 0x2280a, // formmethod - 0x13a: 0x3e805, // input - 0x13c: 0x50b02, // h6 - 0x13d: 0xc902, // ol - 0x13e: 0x3420b, // oncuechange - 0x13f: 0x1e50d, // foreignobject - 0x143: 0x4e70e, // onbeforeunload - 0x144: 0x2bd05, // scope - 0x145: 0x39609, // onemptied - 0x146: 0x14b05, // defer - 0x147: 0xc103, // xmp - 0x148: 0x39f10, // ondurationchange - 0x149: 0x1903, // kbd - 0x14c: 0x47609, // onmessage - 0x14d: 0x60006, // option - 0x14e: 0x2eb09, // minlength - 0x14f: 0x32807, // checked - 0x150: 0xce08, // autoplay - 0x152: 0x202, // br - 0x153: 0x2360a, // novalidate - 0x156: 0x6307, // noembed - 0x159: 0x31007, // onclick - 0x15a: 0x47f0b, // onmousedown - 0x15b: 0x3a708, // onchange - 0x15e: 0x3f209, // oninvalid - 0x15f: 0x2bd06, // scoped - 0x160: 0x18808, // controls - 0x161: 0x30b05, // muted - 0x162: 0x58d08, // sortable - 0x163: 0x51106, // usemap - 0x164: 0x1b80a, // figcaption - 0x165: 0x35706, // ondrag - 0x166: 0x26b04, // high - 0x168: 0x3c303, // src - 0x169: 0x15706, // poster - 0x16b: 0x1670e, // annotation-xml - 0x16c: 0x5f704, // step - 0x16d: 0x4, // abbr - 0x16e: 0x1b06, // dialog - 0x170: 0x1202, // li - 0x172: 0x3ed02, // mo - 0x175: 0x1d803, // for - 0x176: 0x1a803, // ins - 0x178: 0x55504, // size - 0x179: 0x43210, // onlanguagechange - 0x17a: 0x8607, // default - 0x17b: 0x1a03, // bdi - 0x17c: 0x4d30a, // onpagehide - 0x17d: 0x6907, // dirname - 0x17e: 0x21404, // type - 0x17f: 0x1f204, // form - 0x181: 0x28509, // oncanplay - 0x182: 0x6103, // dfn - 0x183: 0x46308, // tabindex - 0x186: 0x6502, // em - 0x187: 0x27404, // lang - 0x189: 0x39108, // dropzone - 0x18a: 0x4080a, // onkeypress - 0x18b: 0x23c08, // datetime - 0x18c: 0x16204, // cols - 0x18d: 0x1, // a - 0x18e: 0x4420c, // onloadeddata - 0x190: 0xa605, // audio - 0x192: 0x2e05, // tbody - 0x193: 0x22c06, // method - 0x195: 0xf404, // loop - 0x196: 0x29606, // iframe - 0x198: 0x2d504, // head - 0x19e: 0x5f108, // manifest - 0x19f: 0xb309, // autofocus - 0x1a0: 0x14904, // code - 0x1a1: 0x55906, // strong - 0x1a2: 0x30308, // multiple - 0x1a3: 0xc05, // param - 0x1a6: 0x21107, // enctype - 0x1a7: 0x5b304, // face - 0x1a8: 0xfd09, // plaintext - 0x1a9: 0x26e02, // h1 - 0x1aa: 0x59509, // onstalled - 0x1ad: 0x3d406, // script - 0x1ae: 0x2db06, // spacer - 0x1af: 0x55108, // onresize - 0x1b0: 0x4a20b, // onmouseover - 0x1b1: 0x5cc08, // onunload - 0x1b2: 0x56708, // onseeked - 0x1b4: 0x2140d, // typemustmatch - 0x1b5: 0x1cc06, // figure - 0x1b6: 0x4950a, // onmouseout - 0x1b7: 0x25e03, // pre - 0x1b8: 0x50705, // width - 0x1b9: 0x19906, // sorted - 0x1bb: 0x5704, // nobr - 0x1be: 0x5302, // tt - 0x1bf: 0x1105, // align - 0x1c0: 0x3e607, // oninput - 0x1c3: 0x41807, // onkeyup - 0x1c6: 0x1c00c, // onafterprint - 0x1c7: 0x210e, // accept-charset - 0x1c8: 0x33c06, // itemid - 0x1c9: 0x3e809, // inputmode - 0x1cb: 0x53306, // strike - 0x1cc: 0x5a903, // sub - 0x1cd: 0x10505, // track - 0x1ce: 0x38605, // start - 0x1d0: 0xd608, // basefont - 0x1d6: 0x1aa06, // source - 0x1d7: 0x18206, // legend - 0x1d8: 0x2d405, // thead - 0x1da: 0x8c05, // tfoot - 0x1dd: 0x1ec06, // object - 0x1de: 0x6e05, // media - 0x1df: 0x1670a, // annotation - 0x1e0: 0x20d0b, // formenctype - 0x1e2: 0x3d208, // noscript - 0x1e4: 0x55505, // sizes - 0x1e5: 0x1fc0c, // autocomplete - 0x1e6: 0x9504, // span - 0x1e7: 0x9808, // noframes - 0x1e8: 0x24b06, // target - 0x1e9: 0x38f06, // ondrop - 0x1ea: 0x2b306, // applet - 0x1ec: 0x5a08, // reversed - 0x1f0: 0x2a907, // isindex - 0x1f3: 0x27008, // hreflang - 0x1f5: 0x2f302, // h5 - 0x1f6: 0x4f307, // address - 0x1fa: 0x2e103, // max - 0x1fb: 0xc30b, // placeholder - 0x1fc: 0x2f608, // textarea - 0x1fe: 0x4ad09, // onmouseup - 0x1ff: 0x3800b, // ondragstart + 0x1: 0x8e0a, // mediagroup + 0x2: 0x2cc04, // lang + 0x4: 0x2c09, // accesskey + 0x5: 0x5708, // frameset + 0x7: 0x63608, // onselect + 0x8: 0x70b06, // system + 0xa: 0x64505, // width + 0xc: 0x2710b, // formenctype + 0xd: 0x10102, // ol + 0xe: 0x38b0b, // oncuechange + 0x10: 0x13403, // bdo + 0x11: 0xcf05, // audio + 0x12: 0x18309, // draggable + 0x14: 0x2d905, // video + 0x15: 0x29902, // mn + 0x16: 0x37b04, // menu + 0x17: 0x2b706, // poster + 0x19: 0xb306, // footer + 0x1a: 0x29006, // method + 0x1b: 0x2a008, // datetime + 0x1c: 0x17607, // onabort + 0x1d: 0x1200e, // updateviacache + 0x1e: 0xb905, // async + 0x1f: 0x49106, // onload + 0x21: 0xd308, // oncancel + 0x22: 0x62508, // onseeked + 0x23: 0x2ea05, // image + 0x24: 0x5d412, // onrejectionhandled + 0x26: 0x15d04, // link + 0x27: 0x51106, // output + 0x28: 0x32504, // head + 0x29: 0x4f30c, // onmouseleave + 0x2a: 0x57307, // onpaste + 0x2b: 0x59809, // onplaying + 0x2c: 0x1b407, // colspan + 0x2f: 0x1af05, // color + 0x30: 0x5f104, // size + 0x31: 0x2d00a, // http-equiv + 0x33: 0x601, // i + 0x34: 0x54d0a, // onpagehide + 0x35: 0x68814, // onunhandledrejection + 0x37: 0x41e07, // onerror + 0x3a: 0x11508, // basefont + 0x3f: 0x1303, // nav + 0x40: 0x18004, // kind + 0x41: 0x34b08, // readonly + 0x42: 0x2f006, // mglyph + 0x44: 0x11102, // li + 0x46: 0x2bd06, // hidden + 0x47: 0x70803, // svg + 0x48: 0x57704, // step + 0x49: 0x22709, // integrity + 0x4a: 0x57a06, // public + 0x4c: 0x19703, // col + 0x4d: 0x1680a, // blockquote + 0x4e: 0x34302, // h5 + 0x50: 0x5ad08, // progress + 0x51: 0x5f105, // sizes + 0x52: 0x33902, // h4 + 0x56: 0x32405, // thead + 0x57: 0x7e07, // keytype + 0x58: 0x5ab0a, // onprogress + 0x59: 0x43f09, // inputmode + 0x5a: 0x3a509, // ondragend + 0x5d: 0x39605, // oncut + 0x5e: 0x42b06, // spacer + 0x5f: 0x19708, // colgroup + 0x62: 0x14e02, // is + 0x65: 0xb902, // as + 0x66: 0x53c09, // onoffline + 0x67: 0x32b06, // sorted + 0x69: 0x48110, // onlanguagechange + 0x6c: 0x4310c, // onhashchange + 0x6d: 0xa604, // name + 0x6e: 0xb205, // tfoot + 0x6f: 0x55504, // desc + 0x70: 0x33103, // max + 0x72: 0x1da06, // coords + 0x73: 0x2f502, // h3 + 0x74: 0x6e10e, // onbeforeunload + 0x75: 0x3a04, // rows + 0x76: 0x63806, // select + 0x77: 0xa805, // meter + 0x78: 0x37f06, // itemid + 0x79: 0x5300c, // onmousewheel + 0x7a: 0x5b406, // srcdoc + 0x7d: 0x17c05, // track + 0x7f: 0x30708, // itemtype + 0x82: 0x6302, // mo + 0x83: 0x40f08, // onchange + 0x84: 0x32507, // headers + 0x85: 0x5c80c, // onratechange + 0x86: 0x60419, // onsecuritypolicyviolation + 0x88: 0x49908, // datalist + 0x89: 0x4dc0b, // onmousedown + 0x8a: 0x1df04, // slot + 0x8b: 0x4a410, // onloadedmetadata + 0x8c: 0x1a06, // accept + 0x8d: 0x25006, // object + 0x91: 0x6af0e, // onvolumechange + 0x92: 0x2107, // charset + 0x93: 0x25e13, // onautocompleteerror + 0x94: 0x6913, // allowpaymentrequest + 0x95: 0x2804, // body + 0x96: 0xc407, // default + 0x97: 0x63808, // selected + 0x98: 0x20604, // face + 0x99: 0x1d505, // shape + 0x9b: 0x68008, // ontoggle + 0x9e: 0x64702, // dt + 0x9f: 0x6d904, // mark + 0xa1: 0xb01, // u + 0xa4: 0x6a708, // onunload + 0xa5: 0xde04, // loop + 0xa6: 0x14d08, // disabled + 0xaa: 0x41707, // onended + 0xab: 0x6d30a, // malignmark + 0xad: 0x67709, // onsuspend + 0xae: 0x34505, // mtext + 0xaf: 0x64b06, // onsort + 0xb0: 0x55908, // itemprop + 0xb3: 0x66d09, // itemscope + 0xb4: 0x15c05, // blink + 0xb6: 0x3a506, // ondrag + 0xb7: 0x6602, // ul + 0xb8: 0x25604, // form + 0xb9: 0xf307, // sandbox + 0xba: 0x5705, // frame + 0xbb: 0x1505, // value + 0xbc: 0x65e09, // onstorage + 0xc0: 0x17b02, // rt + 0xc2: 0x202, // br + 0xc3: 0x20e08, // fieldset + 0xc4: 0x2780d, // typemustmatch + 0xc5: 0x6108, // nomodule + 0xc6: 0x4007, // noembed + 0xc7: 0x69a0d, // onbeforeprint + 0xc8: 0x17206, // button + 0xc9: 0x2dd07, // onclick + 0xca: 0x6fe07, // summary + 0xcd: 0xac04, // ruby + 0xce: 0x5b905, // class + 0xcf: 0x3e80b, // ondragstart + 0xd0: 0x21907, // caption + 0xd4: 0x850e, // allowusermedia + 0xd5: 0x4c30b, // onloadstart + 0xd9: 0x15403, // div + 0xda: 0x49d04, // list + 0xdb: 0x32204, // math + 0xdc: 0x43f05, // input + 0xdf: 0x3de0a, // ondragover + 0xe0: 0x2c602, // h2 + 0xe2: 0x19e09, // plaintext + 0xe4: 0x4e70c, // onmouseenter + 0xe7: 0x46d07, // checked + 0xe8: 0x46403, // pre + 0xea: 0x35308, // multiple + 0xeb: 0x16103, // bdi + 0xec: 0x33109, // maxlength + 0xed: 0x7701, // q + 0xee: 0x61b0a, // onauxclick + 0xf0: 0x57003, // wbr + 0xf2: 0x11504, // base + 0xf3: 0x6dd06, // option + 0xf5: 0x40710, // ondurationchange + 0xf7: 0x5508, // noframes + 0xf9: 0x3f908, // dropzone + 0xfb: 0x67105, // scope + 0xfc: 0x9c08, // reversed + 0xfd: 0x3ae0b, // ondragenter + 0xfe: 0x3ee05, // start + 0xff: 0xf903, // xmp + 0x100: 0x5f507, // srclang + 0x101: 0x2ef03, // img + 0x104: 0x101, // b + 0x105: 0x23c03, // for + 0x106: 0xc105, // aside + 0x107: 0x43d07, // oninput + 0x108: 0x34a04, // area + 0x109: 0x28c0a, // formmethod + 0x10a: 0x72004, // wrap + 0x10c: 0x22402, // rp + 0x10d: 0x45f0a, // onkeypress + 0x10e: 0x5102, // tt + 0x110: 0x33b02, // mi + 0x111: 0x35b05, // muted + 0x112: 0xb003, // alt + 0x113: 0x19004, // code + 0x114: 0x4202, // em + 0x115: 0x3b90a, // ondragexit + 0x117: 0x3d04, // span + 0x119: 0x30f08, // manifest + 0x11a: 0x37b08, // menuitem + 0x11b: 0x57f07, // content + 0x11d: 0x6bd09, // onwaiting + 0x11f: 0x4ba09, // onloadend + 0x121: 0x3720d, // oncontextmenu + 0x123: 0x5c206, // onblur + 0x124: 0x3f007, // article + 0x125: 0xa303, // dir + 0x126: 0xe704, // ping + 0x127: 0x23408, // required + 0x128: 0x44909, // oninvalid + 0x129: 0x6d405, // align + 0x12b: 0x57e04, // icon + 0x12c: 0x64902, // h6 + 0x12d: 0x1b404, // cols + 0x12e: 0x2160a, // figcaption + 0x12f: 0x45209, // onkeydown + 0x130: 0x66708, // onsubmit + 0x131: 0x13609, // oncanplay + 0x132: 0x70503, // sup + 0x133: 0xc01, // p + 0x135: 0x3fe09, // onemptied + 0x136: 0x38506, // oncopy + 0x137: 0x55804, // cite + 0x138: 0x39b0a, // ondblclick + 0x13a: 0x4ff0b, // onmousemove + 0x13c: 0x66903, // sub + 0x13d: 0x47b03, // rel + 0x13e: 0xe008, // optgroup + 0x142: 0x3a07, // rowspan + 0x143: 0x36c06, // source + 0x144: 0x1fe08, // noscript + 0x145: 0x55f04, // open + 0x146: 0x1ec03, // ins + 0x147: 0x23c0d, // foreignObject + 0x148: 0x5a10a, // onpopstate + 0x14a: 0x27507, // enctype + 0x14b: 0x25e0e, // onautocomplete + 0x14c: 0x34608, // textarea + 0x14e: 0x2600c, // autocomplete + 0x14f: 0x14002, // hr + 0x150: 0x1ce08, // controls + 0x151: 0xc302, // id + 0x153: 0x21e0c, // onafterprint + 0x155: 0x2490d, // foreignobject + 0x156: 0x31b07, // marquee + 0x157: 0x58e07, // onpause + 0x158: 0x5e202, // dl + 0x159: 0x12c06, // height + 0x15a: 0x33b03, // min + 0x15b: 0xa307, // dirname + 0x15c: 0x1a609, // translate + 0x15d: 0x13004, // html + 0x15e: 0x33b09, // minlength + 0x15f: 0x47a07, // preload + 0x160: 0x70e08, // template + 0x161: 0x3d30b, // ondragleave + 0x164: 0x5b403, // src + 0x165: 0x31506, // strong + 0x167: 0x4c04, // samp + 0x168: 0x6ed07, // address + 0x169: 0x54508, // ononline + 0x16b: 0xfb0b, // placeholder + 0x16c: 0x2ac06, // target + 0x16d: 0x1ee05, // small + 0x16e: 0x6c607, // onwheel + 0x16f: 0x1b90a, // annotation + 0x170: 0x4680a, // spellcheck + 0x171: 0x4607, // details + 0x172: 0xbd06, // canvas + 0x173: 0xeb09, // autofocus + 0x174: 0xc05, // param + 0x176: 0x45708, // download + 0x177: 0x44603, // del + 0x178: 0x36007, // onclose + 0x179: 0x16003, // kbd + 0x17a: 0x30106, // applet + 0x17b: 0x2c804, // href + 0x17c: 0x5ed08, // onresize + 0x17e: 0x4910c, // onloadeddata + 0x180: 0x7402, // tr + 0x181: 0x2a80a, // formtarget + 0x182: 0xca05, // title + 0x183: 0x6f905, // style + 0x184: 0x7a06, // strike + 0x185: 0x59206, // usemap + 0x186: 0x2e406, // iframe + 0x187: 0x1004, // main + 0x189: 0x9707, // picture + 0x18c: 0x2fe05, // ismap + 0x18e: 0x49904, // data + 0x18f: 0xda05, // label + 0x191: 0x3c50e, // referrerpolicy + 0x192: 0x13f02, // th + 0x194: 0x52a06, // prompt + 0x195: 0x5bd07, // section + 0x197: 0x6cd07, // optimum + 0x198: 0x2c304, // high + 0x199: 0x14502, // h1 + 0x19a: 0x65509, // onstalled + 0x19b: 0x15603, // var + 0x19c: 0x11c04, // time + 0x19e: 0x67002, // ms + 0x19f: 0x32506, // header + 0x1a0: 0x4ce09, // onmessage + 0x1a1: 0x56205, // nonce + 0x1a2: 0x2560a, // formaction + 0x1a3: 0x20806, // center + 0x1a4: 0x3704, // nobr + 0x1a5: 0x58905, // table + 0x1a6: 0x49d07, // listing + 0x1a7: 0x18a06, // legend + 0x1a9: 0x28309, // challenge + 0x1aa: 0x23006, // figure + 0x1ab: 0x8e05, // media + 0x1ae: 0x8104, // type + 0x1af: 0x11904, // font + 0x1b0: 0x4ce0e, // onmessageerror + 0x1b1: 0x36508, // seamless + 0x1b2: 0x5f03, // dfn + 0x1b3: 0x19205, // defer + 0x1b4: 0x6b03, // low + 0x1b5: 0x62d09, // onseeking + 0x1b6: 0x5170b, // onmouseover + 0x1b7: 0x29a0a, // novalidate + 0x1b8: 0x7160a, // workertype + 0x1ba: 0x3c107, // itemref + 0x1bd: 0x1, // a + 0x1be: 0x30003, // map + 0x1bf: 0x11a0c, // ontimeupdate + 0x1c0: 0x14707, // bgsound + 0x1c1: 0x3206, // keygen + 0x1c2: 0x2705, // tbody + 0x1c5: 0x64006, // onshow + 0x1c7: 0x2501, // s + 0x1c8: 0x4f07, // pattern + 0x1cc: 0x13610, // oncanplaythrough + 0x1ce: 0x2bf02, // dd + 0x1cf: 0x6f306, // srcset + 0x1d0: 0x15903, // big + 0x1d2: 0x64d08, // sortable + 0x1d3: 0x47407, // onkeyup + 0x1d5: 0x59806, // onplay + 0x1d7: 0x4ac04, // meta + 0x1d8: 0x3f706, // ondrop + 0x1da: 0x5fc08, // onscroll + 0x1db: 0x1e30b, // crossorigin + 0x1dc: 0x5670a, // onpageshow + 0x1dd: 0x4, // abbr + 0x1de: 0x5e02, // td + 0x1df: 0x57f0f, // contenteditable + 0x1e0: 0x25a06, // action + 0x1e1: 0x10a0b, // playsinline + 0x1e2: 0x42507, // onfocus + 0x1e3: 0x2c808, // hreflang + 0x1e5: 0x50a0a, // onmouseout + 0x1e6: 0x5e607, // onreset + 0x1e7: 0x10608, // autoplay + 0x1ea: 0x67106, // scoped + 0x1ec: 0x30a, // radiogroup + 0x1ee: 0x3740b, // contextmenu + 0x1ef: 0x52209, // onmouseup + 0x1f1: 0x2b206, // hgroup + 0x1f2: 0x1f00f, // allowfullscreen + 0x1f3: 0x4b208, // tabindex + 0x1f6: 0x2f707, // isindex + 0x1f7: 0x1a0e, // accept-charset + 0x1f8: 0x2960e, // formnovalidate + 0x1fb: 0x1b90e, // annotation-xml + 0x1fc: 0x4205, // embed + 0x1fd: 0x20006, // script + 0x1fe: 0x16206, // dialog + 0x1ff: 0x1c707, // command } -const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" + - "genavaluealtdetailsampatternobreversedfnoembedirnamediagroup" + - "ingasyncanvasidefaultfooterowspanoframesetitleaudionblurubya" + - "utofocusandboxmplaceholderautoplaybasefontimeupdatebdoncance" + - "labelooptgrouplaintextrackindisabledivarbgsoundlowbrbigblink" + - "blockquotebuttonabortranslatecodefercolgroupostercolorcolspa" + - "nnotation-xmlcommandraggablegendcontrolsmallcoordsortedcross" + - "originsourcefieldsetfigcaptionafterprintfigurequiredforeignO" + - "bjectforeignobjectformactionautocompleteerrorformenctypemust" + - "matchallengeformmethodformnovalidatetimeterformtargetheightm" + - "lhgroupreloadhiddenhigh1hreflanghttp-equivideoncanplaythroug" + - "h2iframeimageimglyph3isindexismappletitemscopeditemtypemarqu" + - "eematheaderspacermaxlength4minlength5mtextareadonlymultiplem" + - "utedonclickoncloseamlesspellcheckedoncontextmenuitemidoncuec" + - "hangeondblclickondragendondragenterondragleaveondragoverondr" + - "agstarticleondropzonemptiedondurationchangeonendedonerroronf" + - "ocusrcdocitempropenoscriptonhashchangeoninputmodeloninvalido" + - "nkeydownloadonkeypressrclangonkeyupublicontenteditableonlang" + - "uagechangeonloadeddatalistingonloadedmetadatabindexonloadsta" + - "rtonmessageonmousedownonmousemoveonmouseoutputonmouseoveronm" + - "ouseuponmousewheelonofflineononlineonpagehidesclassectionbef" + - "oreunloaddresshapeonpageshowidth6onpausemaponplayingonpopsta" + - "teonprogresstrikeytypeonratechangeonresetonresizestrongonscr" + - "ollonseekedonseekingonselectedonshowraponsortableonstalledon" + - "storageonsubmitemrefacenteronsuspendontoggleonunloadonvolume" + - "changeonwaitingoptimumanifestepromptoptionbeforeprintstylesu" + - "mmarysupsvgsystemplate" +const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobro" + + "wspanoembedetailsampatternoframesetdfnomoduleallowpaymentreq" + + "uestrikeytypeallowusermediagroupictureversedirnameterubyaltf" + + "ooterasyncanvasidefaultitleaudioncancelabelooptgroupingautof" + + "ocusandboxmplaceholderautoplaysinlinebasefontimeupdateviacac" + + "heightmlbdoncanplaythrough1bgsoundisabledivarbigblinkbdialog" + + "blockquotebuttonabortrackindraggablegendcodefercolgrouplaint" + + "extranslatecolorcolspannotation-xmlcommandcontrolshapecoords" + + "lotcrossoriginsmallowfullscreenoscriptfacenterfieldsetfigcap" + + "tionafterprintegrityfigurequiredforeignObjectforeignobjectfo" + + "rmactionautocompleteerrorformenctypemustmatchallengeformmeth" + + "odformnovalidatetimeformtargethgrouposterhiddenhigh2hreflang" + + "http-equivideonclickiframeimageimglyph3isindexismappletitemt" + + "ypemanifestrongmarqueematheadersortedmaxlength4minlength5mte" + + "xtareadonlymultiplemutedoncloseamlessourceoncontextmenuitemi" + + "doncopyoncuechangeoncutondblclickondragendondragenterondrage" + + "xitemreferrerpolicyondragleaveondragoverondragstarticleondro" + + "pzonemptiedondurationchangeonendedonerroronfocuspaceronhashc" + + "hangeoninputmodeloninvalidonkeydownloadonkeypresspellchecked" + + "onkeyupreloadonlanguagechangeonloadeddatalistingonloadedmeta" + + "databindexonloadendonloadstartonmessageerroronmousedownonmou" + + "seenteronmouseleaveonmousemoveonmouseoutputonmouseoveronmous" + + "eupromptonmousewheelonofflineononlineonpagehidescitempropeno" + + "nceonpageshowbronpastepublicontenteditableonpausemaponplayin" + + "gonpopstateonprogressrcdoclassectionbluronratechangeonreject" + + "ionhandledonresetonresizesrclangonscrollonsecuritypolicyviol" + + "ationauxclickonseekedonseekingonselectedonshowidth6onsortabl" + + "eonstalledonstorageonsubmitemscopedonsuspendontoggleonunhand" + + "ledrejectionbeforeprintonunloadonvolumechangeonwaitingonwhee" + + "loptimumalignmarkoptionbeforeunloaddressrcsetstylesummarysup" + + "svgsystemplateworkertypewrap" diff --git a/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html b/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html deleted file mode 100644 index 9915fa0ee4f..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/HTTP-charset.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - HTTP charset - - - - - - - - - - - -

HTTP charset

- - -
- - -
 
- - - - - -
-

The character encoding of a page can be set using the HTTP header charset declaration.

-

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.

-
-
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html b/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html deleted file mode 100644 index 26e5d8b4ebf..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - HTTP vs UTF-8 BOM - - - - - - - - - - - -

HTTP vs UTF-8 BOM

- - -
- - -
 
- - - - - -
-

A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.

-

The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

If the test is unsuccessful, the characters  should appear at the top of the page. These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding.

-
-
-
HTML5
-

the-input-byte-stream-034
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html b/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html deleted file mode 100644 index 2f07e95158e..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - HTTP vs meta charset - - - - - - - - - - - -

HTTP vs meta charset

- - -
- - -
 
- - - - - -
-

The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.

-

The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-018
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html b/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html deleted file mode 100644 index 6853cddeccc..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - HTTP vs meta content - - - - - - - - - - - -

HTTP vs meta content

- - -
- - -
 
- - - - - -
-

The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.

-

The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-016
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html b/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html deleted file mode 100644 index 612e26c6c52..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/No-encoding-declaration.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - No encoding declaration - - - - - - - - - - - -

No encoding declaration

- - -
- - -
 
- - - - - -
-

A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.

-

The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-015
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/README b/vendor/golang.org/x/net/html/charset/testdata/README deleted file mode 100644 index 38ef0f9f121..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/README +++ /dev/null @@ -1,9 +0,0 @@ -These test cases come from -http://www.w3.org/International/tests/repository/html5/the-input-byte-stream/results-basics - -Distributed under both the W3C Test Suite License -(http://www.w3.org/Consortium/Legal/2008/04-testsuite-license) -and the W3C 3-clause BSD License -(http://www.w3.org/Consortium/Legal/2008/03-bsd-license). -To contribute to a W3C Test Suite, see the policies and contribution -forms (http://www.w3.org/2004/10/27-testcases). diff --git a/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html b/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html deleted file mode 100644 index 3abf7a9343c..00000000000 Binary files a/vendor/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html and /dev/null differ diff --git a/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html b/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html deleted file mode 100644 index 76254c980c2..00000000000 Binary files a/vendor/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html and /dev/null differ diff --git a/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html b/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html deleted file mode 100644 index 83de43338ec..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - UTF-8 BOM vs meta charset - - - - - - - - - - - -

UTF-8 BOM vs meta charset

- - -
- - -
 
- - - - - -
-

A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.

-

The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-038
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html b/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html deleted file mode 100644 index 501aac2d6a5..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/UTF-8-BOM-vs-meta-content.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - UTF-8 BOM vs meta content - - - - - - - - - - - -

UTF-8 BOM vs meta content

- - -
- - -
 
- - - - - -
-

A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.

-

The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-037
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html b/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html deleted file mode 100644 index 2d7d25aba14..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - meta charset attribute - - - - - - - - - - - -

meta charset attribute

- - -
- - -
 
- - - - - -
-

The character encoding of the page can be set by a meta element with charset attribute.

-

The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-009
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html b/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html deleted file mode 100644 index 1c3f228e7c9..00000000000 --- a/vendor/golang.org/x/net/html/charset/testdata/meta-content-attribute.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - meta content attribute - - - - - - - - - - - -

meta content attribute

- - -
- - -
 
- - - - - -
-

The character encoding of the page can be set by a meta element with http-equiv and content attributes.

-

The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
HTML5
-

the-input-byte-stream-007
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • -
  • The test is read from a server that supports HTTP.
-
- - - - - - diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go index 52f651ff6db..b37e6212471 100644 --- a/vendor/golang.org/x/net/html/const.go +++ b/vendor/golang.org/x/net/html/const.go @@ -52,10 +52,12 @@ var isSpecialElementMap = map[string]bool{ "iframe": true, "img": true, "input": true, - "isindex": true, + "isindex": true, // The 'isindex' element has been removed, but keep it for backwards compatibility. + "keygen": true, "li": true, "link": true, "listing": true, + "main": true, "marquee": true, "menu": true, "meta": true, diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go index 94f496874ab..822ed42a04c 100644 --- a/vendor/golang.org/x/net/html/doc.go +++ b/vendor/golang.org/x/net/html/doc.go @@ -49,18 +49,18 @@ call to Next. For example, to extract an HTML page's anchor text: for { tt := z.Next() switch tt { - case ErrorToken: + case html.ErrorToken: return z.Err() - case TextToken: + case html.TextToken: if depth > 0 { // emitBytes should copy the []byte it receives, // if it doesn't process it immediately. emitBytes(z.Text()) } - case StartTagToken, EndTagToken: + case html.StartTagToken, html.EndTagToken: tn, _ := z.TagName() if len(tn) == 1 && tn[0] == 'a' { - if tt == StartTagToken { + if tt == html.StartTagToken { depth++ } else { depth-- diff --git a/vendor/golang.org/x/net/html/testdata/go1.html b/vendor/golang.org/x/net/html/testdata/go1.html deleted file mode 100644 index d238257c33c..00000000000 --- a/vendor/golang.org/x/net/html/testdata/go1.html +++ /dev/null @@ -1,2237 +0,0 @@ - - - - - - Go 1 Release Notes - The Go Programming Language - - - - - - - - - - - - -
- - -
-

Go 1 Release Notes

- - - - - - - - - -

Introduction to Go 1

- -

-Go version 1, Go 1 for short, defines a language and a set of core libraries -that provide a stable foundation for creating reliable products, projects, and -publications. -

- -

-The driving motivation for Go 1 is stability for its users. People should be able to -write Go programs and expect that they will continue to compile and run without -change, on a time scale of years, including in production environments such as -Google App Engine. Similarly, people should be able to write books about Go, be -able to say which version of Go the book is describing, and have that version -number still be meaningful much later. -

- -

-Code that compiles in Go 1 should, with few exceptions, continue to compile and -run throughout the lifetime of that version, even as we issue updates and bug -fixes such as Go version 1.1, 1.2, and so on. Other than critical fixes, changes -made to the language and library for subsequent releases of Go 1 may -add functionality but will not break existing Go 1 programs. -The Go 1 compatibility document -explains the compatibility guidelines in more detail. -

- -

-Go 1 is a representation of Go as it used today, not a wholesale rethinking of -the language. We avoided designing new features and instead focused on cleaning -up problems and inconsistencies and improving portability. There are a number -changes to the Go language and packages that we had considered for some time and -prototyped but not released primarily because they are significant and -backwards-incompatible. Go 1 was an opportunity to get them out, which is -helpful for the long term, but also means that Go 1 introduces incompatibilities -for old programs. Fortunately, the go fix tool can -automate much of the work needed to bring programs up to the Go 1 standard. -

- -

-This document outlines the major changes in Go 1 that will affect programmers -updating existing code; its reference point is the prior release, r60 (tagged as -r60.3). It also explains how to update code from r60 to run under Go 1. -

- -

Changes to the language

- -

Append

- -

-The append predeclared variadic function makes it easy to grow a slice -by adding elements to the end. -A common use is to add bytes to the end of a byte slice when generating output. -However, append did not provide a way to append a string to a []byte, -which is another common case. -

- -
    greeting := []byte{}
-    greeting = append(greeting, []byte("hello ")...)
- -

-By analogy with the similar property of copy, Go 1 -permits a string to be appended (byte-wise) directly to a byte -slice, reducing the friction between strings and byte slices. -The conversion is no longer necessary: -

- -
    greeting = append(greeting, "world"...)
- -

-Updating: -This is a new feature, so existing code needs no changes. -

- -

Close

- -

-The close predeclared function provides a mechanism -for a sender to signal that no more values will be sent. -It is important to the implementation of for range -loops over channels and is helpful in other situations. -Partly by design and partly because of race conditions that can occur otherwise, -it is intended for use only by the goroutine sending on the channel, -not by the goroutine receiving data. -However, before Go 1 there was no compile-time checking that close -was being used correctly. -

- -

-To close this gap, at least in part, Go 1 disallows close on receive-only channels. -Attempting to close such a channel is a compile-time error. -

- -
-    var c chan int
-    var csend chan<- int = c
-    var crecv <-chan int = c
-    close(c)     // legal
-    close(csend) // legal
-    close(crecv) // illegal
-
- -

-Updating: -Existing code that attempts to close a receive-only channel was -erroneous even before Go 1 and should be fixed. The compiler will -now reject such code. -

- -

Composite literals

- -

-In Go 1, a composite literal of array, slice, or map type can elide the -type specification for the elements' initializers if they are of pointer type. -All four of the initializations in this example are legal; the last one was illegal before Go 1. -

- -
    type Date struct {
-        month string
-        day   int
-    }
-    // Struct values, fully qualified; always legal.
-    holiday1 := []Date{
-        Date{"Feb", 14},
-        Date{"Nov", 11},
-        Date{"Dec", 25},
-    }
-    // Struct values, type name elided; always legal.
-    holiday2 := []Date{
-        {"Feb", 14},
-        {"Nov", 11},
-        {"Dec", 25},
-    }
-    // Pointers, fully qualified, always legal.
-    holiday3 := []*Date{
-        &Date{"Feb", 14},
-        &Date{"Nov", 11},
-        &Date{"Dec", 25},
-    }
-    // Pointers, type name elided; legal in Go 1.
-    holiday4 := []*Date{
-        {"Feb", 14},
-        {"Nov", 11},
-        {"Dec", 25},
-    }
- -

-Updating: -This change has no effect on existing code, but the command -gofmt -s applied to existing source -will, among other things, elide explicit element types wherever permitted. -

- - -

Goroutines during init

- -

-The old language defined that go statements executed during initialization created goroutines but that they did not begin to run until initialization of the entire program was complete. -This introduced clumsiness in many places and, in effect, limited the utility -of the init construct: -if it was possible for another package to use the library during initialization, the library -was forced to avoid goroutines. -This design was done for reasons of simplicity and safety but, -as our confidence in the language grew, it seemed unnecessary. -Running goroutines during initialization is no more complex or unsafe than running them during normal execution. -

- -

-In Go 1, code that uses goroutines can be called from -init routines and global initialization expressions -without introducing a deadlock. -

- -
var PackageGlobal int
-
-func init() {
-    c := make(chan int)
-    go initializationFunction(c)
-    PackageGlobal = <-c
-}
- -

-Updating: -This is a new feature, so existing code needs no changes, -although it's possible that code that depends on goroutines not starting before main will break. -There was no such code in the standard repository. -

- -

The rune type

- -

-The language spec allows the int type to be 32 or 64 bits wide, but current implementations set int to 32 bits even on 64-bit platforms. -It would be preferable to have int be 64 bits on 64-bit platforms. -(There are important consequences for indexing large slices.) -However, this change would waste space when processing Unicode characters with -the old language because the int type was also used to hold Unicode code points: each code point would waste an extra 32 bits of storage if int grew from 32 bits to 64. -

- -

-To make changing to 64-bit int feasible, -Go 1 introduces a new basic type, rune, to represent -individual Unicode code points. -It is an alias for int32, analogous to byte -as an alias for uint8. -

- -

-Character literals such as 'a', '語', and '\u0345' -now have default type rune, -analogous to 1.0 having default type float64. -A variable initialized to a character constant will therefore -have type rune unless otherwise specified. -

- -

-Libraries have been updated to use rune rather than int -when appropriate. For instance, the functions unicode.ToLower and -relatives now take and return a rune. -

- -
    delta := 'δ' // delta has type rune.
-    var DELTA rune
-    DELTA = unicode.ToUpper(delta)
-    epsilon := unicode.ToLower(DELTA + 1)
-    if epsilon != 'δ'+1 {
-        log.Fatal("inconsistent casing for Greek")
-    }
- -

-Updating: -Most source code will be unaffected by this because the type inference from -:= initializers introduces the new type silently, and it propagates -from there. -Some code may get type errors that a trivial conversion will resolve. -

- -

The error type

- -

-Go 1 introduces a new built-in type, error, which has the following definition: -

- -
-    type error interface {
-        Error() string
-    }
-
- -

-Since the consequences of this type are all in the package library, -it is discussed below. -

- -

Deleting from maps

- -

-In the old language, to delete the entry with key k from map m, one wrote the statement, -

- -
-    m[k] = value, false
-
- -

-This syntax was a peculiar special case, the only two-to-one assignment. -It required passing a value (usually ignored) that is evaluated but discarded, -plus a boolean that was nearly always the constant false. -It did the job but was odd and a point of contention. -

- -

-In Go 1, that syntax has gone; instead there is a new built-in -function, delete. The call -

- -
    delete(m, k)
- -

-will delete the map entry retrieved by the expression m[k]. -There is no return value. Deleting a non-existent entry is a no-op. -

- -

-Updating: -Running go fix will convert expressions of the form m[k] = value, -false into delete(m, k) when it is clear that -the ignored value can be safely discarded from the program and -false refers to the predefined boolean constant. -The fix tool -will flag other uses of the syntax for inspection by the programmer. -

- -

Iterating in maps

- -

-The old language specification did not define the order of iteration for maps, -and in practice it differed across hardware platforms. -This caused tests that iterated over maps to be fragile and non-portable, with the -unpleasant property that a test might always pass on one machine but break on another. -

- -

-In Go 1, the order in which elements are visited when iterating -over a map using a for range statement -is defined to be unpredictable, even if the same loop is run multiple -times with the same map. -Code should not assume that the elements are visited in any particular order. -

- -

-This change means that code that depends on iteration order is very likely to break early and be fixed long before it becomes a problem. -Just as important, it allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map. -

- -
    m := map[string]int{"Sunday": 0, "Monday": 1}
-    for name, value := range m {
-        // This loop should not assume Sunday will be visited first.
-        f(name, value)
-    }
- -

-Updating: -This is one change where tools cannot help. Most existing code -will be unaffected, but some programs may break or misbehave; we -recommend manual checking of all range statements over maps to -verify they do not depend on iteration order. There were a few such -examples in the standard repository; they have been fixed. -Note that it was already incorrect to depend on the iteration order, which -was unspecified. This change codifies the unpredictability. -

- -

Multiple assignment

- -

-The language specification has long guaranteed that in assignments -the right-hand-side expressions are all evaluated before any left-hand-side expressions are assigned. -To guarantee predictable behavior, -Go 1 refines the specification further. -

- -

-If the left-hand side of the assignment -statement contains expressions that require evaluation, such as -function calls or array indexing operations, these will all be done -using the usual left-to-right rule before any variables are assigned -their value. Once everything is evaluated, the actual assignments -proceed in left-to-right order. -

- -

-These examples illustrate the behavior. -

- -
    sa := []int{1, 2, 3}
-    i := 0
-    i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
-
-    sb := []int{1, 2, 3}
-    j := 0
-    sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
-
-    sc := []int{1, 2, 3}
-    sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)
- -

-Updating: -This is one change where tools cannot help, but breakage is unlikely. -No code in the standard repository was broken by this change, and code -that depended on the previous unspecified behavior was already incorrect. -

- -

Returns and shadowed variables

- -

-A common mistake is to use return (without arguments) after an assignment to a variable that has the same name as a result variable but is not the same variable. -This situation is called shadowing: the result variable has been shadowed by another variable with the same name declared in an inner scope. -

- -

-In functions with named return values, -the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement. -(It isn't part of the specification, because this is one area we are still exploring; -the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.) -

- -

-This function implicitly returns a shadowed return value and will be rejected by the compiler: -

- -
-    func Bug() (i, j, k int) {
-        for i = 0; i < 5; i++ {
-            for j := 0; j < 5; j++ { // Redeclares j.
-                k += i*j
-                if k > 100 {
-                    return // Rejected: j is shadowed here.
-                }
-            }
-        }
-        return // OK: j is not shadowed here.
-    }
-
- -

-Updating: -Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand. -The few cases that arose in the standard repository were mostly bugs. -

- -

Copying structs with unexported fields

- -

-The old language did not allow a package to make a copy of a struct value containing unexported fields belonging to a different package. -There was, however, a required exception for a method receiver; -also, the implementations of copy and append have never honored the restriction. -

- -

-Go 1 will allow packages to copy struct values containing unexported fields from other packages. -Besides resolving the inconsistency, -this change admits a new kind of API: a package can return an opaque value without resorting to a pointer or interface. -The new implementations of time.Time and -reflect.Value are examples of types taking advantage of this new property. -

- -

-As an example, if package p includes the definitions, -

- -
-    type Struct struct {
-        Public int
-        secret int
-    }
-    func NewStruct(a int) Struct {  // Note: not a pointer.
-        return Struct{a, f(a)}
-    }
-    func (s Struct) String() string {
-        return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
-    }
-
- -

-a package that imports p can assign and copy values of type -p.Struct at will. -Behind the scenes the unexported fields will be assigned and copied just -as if they were exported, -but the client code will never be aware of them. The code -

- -
-    import "p"
-
-    myStruct := p.NewStruct(23)
-    copyOfMyStruct := myStruct
-    fmt.Println(myStruct, copyOfMyStruct)
-
- -

-will show that the secret field of the struct has been copied to the new value. -

- -

-Updating: -This is a new feature, so existing code needs no changes. -

- -

Equality

- -

-Before Go 1, the language did not define equality on struct and array values. -This meant, -among other things, that structs and arrays could not be used as map keys. -On the other hand, Go did define equality on function and map values. -Function equality was problematic in the presence of closures -(when are two closures equal?) -while map equality compared pointers, not the maps' content, which was usually -not what the user would want. -

- -

-Go 1 addressed these issues. -First, structs and arrays can be compared for equality and inequality -(== and !=), -and therefore be used as map keys, -provided they are composed from elements for which equality is also defined, -using element-wise comparison. -

- -
    type Day struct {
-        long  string
-        short string
-    }
-    Christmas := Day{"Christmas", "XMas"}
-    Thanksgiving := Day{"Thanksgiving", "Turkey"}
-    holiday := map[Day]bool{
-        Christmas:    true,
-        Thanksgiving: true,
-    }
-    fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])
- -

-Second, Go 1 removes the definition of equality for function values, -except for comparison with nil. -Finally, map equality is gone too, also except for comparison with nil. -

- -

-Note that equality is still undefined for slices, for which the -calculation is in general infeasible. Also note that the ordered -comparison operators (< <= -> >=) are still undefined for -structs and arrays. - -

-Updating: -Struct and array equality is a new feature, so existing code needs no changes. -Existing code that depends on function or map equality will be -rejected by the compiler and will need to be fixed by hand. -Few programs will be affected, but the fix may require some -redesign. -

- -

The package hierarchy

- -

-Go 1 addresses many deficiencies in the old standard library and -cleans up a number of packages, making them more internally consistent -and portable. -

- -

-This section describes how the packages have been rearranged in Go 1. -Some have moved, some have been renamed, some have been deleted. -New packages are described in later sections. -

- -

The package hierarchy

- -

-Go 1 has a rearranged package hierarchy that groups related items -into subdirectories. For instance, utf8 and -utf16 now occupy subdirectories of unicode. -Also, some packages have moved into -subrepositories of -code.google.com/p/go -while others have been deleted outright. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Old pathNew path

asn1 encoding/asn1
csv encoding/csv
gob encoding/gob
json encoding/json
xml encoding/xml

exp/template/html html/template

big math/big
cmath math/cmplx
rand math/rand

http net/http
http/cgi net/http/cgi
http/fcgi net/http/fcgi
http/httptest net/http/httptest
http/pprof net/http/pprof
mail net/mail
rpc net/rpc
rpc/jsonrpc net/rpc/jsonrpc
smtp net/smtp
url net/url

exec os/exec

scanner text/scanner
tabwriter text/tabwriter
template text/template
template/parse text/template/parse

utf8 unicode/utf8
utf16 unicode/utf16
- -

-Note that the package names for the old cmath and -exp/template/html packages have changed to cmplx -and template. -

- -

-Updating: -Running go fix will update all imports and package renames for packages that -remain inside the standard repository. Programs that import packages -that are no longer in the standard repository will need to be edited -by hand. -

- -

The package tree exp

- -

-Because they are not standardized, the packages under the exp directory will not be available in the -standard Go 1 release distributions, although they will be available in source code form -in the repository for -developers who wish to use them. -

- -

-Several packages have moved under exp at the time of Go 1's release: -

- -
    -
  • ebnf
  • -
  • html
  • -
  • go/types
  • -
- -

-(The EscapeString and UnescapeString types remain -in package html.) -

- -

-All these packages are available under the same names, with the prefix exp/: exp/ebnf etc. -

- -

-Also, the utf8.String type has been moved to its own package, exp/utf8string. -

- -

-Finally, the gotype command now resides in exp/gotype, while -ebnflint is now in exp/ebnflint. -If they are installed, they now reside in $GOROOT/bin/tool. -

- -

-Updating: -Code that uses packages in exp will need to be updated by hand, -or else compiled from an installation that has exp available. -The go fix tool or the compiler will complain about such uses. -

- -

The package tree old

- -

-Because they are deprecated, the packages under the old directory will not be available in the -standard Go 1 release distributions, although they will be available in source code form for -developers who wish to use them. -

- -

-The packages in their new locations are: -

- -
    -
  • old/netchan
  • -
  • old/regexp
  • -
  • old/template
  • -
- -

-Updating: -Code that uses packages now in old will need to be updated by hand, -or else compiled from an installation that has old available. -The go fix tool will warn about such uses. -

- -

Deleted packages

- -

-Go 1 deletes several packages outright: -

- -
    -
  • container/vector
  • -
  • exp/datafmt
  • -
  • go/typechecker
  • -
  • try
  • -
- -

-and also the command gotry. -

- -

-Updating: -Code that uses container/vector should be updated to use -slices directly. See -the Go -Language Community Wiki for some suggestions. -Code that uses the other packages (there should be almost zero) will need to be rethought. -

- -

Packages moving to subrepositories

- -

-Go 1 has moved a number of packages into other repositories, usually sub-repositories of -the main Go repository. -This table lists the old and new import paths: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OldNew

crypto/bcrypt code.google.com/p/go.crypto/bcrypt
crypto/blowfish code.google.com/p/go.crypto/blowfish
crypto/cast5 code.google.com/p/go.crypto/cast5
crypto/md4 code.google.com/p/go.crypto/md4
crypto/ocsp code.google.com/p/go.crypto/ocsp
crypto/openpgp code.google.com/p/go.crypto/openpgp
crypto/openpgp/armor code.google.com/p/go.crypto/openpgp/armor
crypto/openpgp/elgamal code.google.com/p/go.crypto/openpgp/elgamal
crypto/openpgp/errors code.google.com/p/go.crypto/openpgp/errors
crypto/openpgp/packet code.google.com/p/go.crypto/openpgp/packet
crypto/openpgp/s2k code.google.com/p/go.crypto/openpgp/s2k
crypto/ripemd160 code.google.com/p/go.crypto/ripemd160
crypto/twofish code.google.com/p/go.crypto/twofish
crypto/xtea code.google.com/p/go.crypto/xtea
exp/ssh code.google.com/p/go.crypto/ssh

image/bmp code.google.com/p/go.image/bmp
image/tiff code.google.com/p/go.image/tiff

net/dict code.google.com/p/go.net/dict
net/websocket code.google.com/p/go.net/websocket
exp/spdy code.google.com/p/go.net/spdy

encoding/git85 code.google.com/p/go.codereview/git85
patch code.google.com/p/go.codereview/patch

exp/wingui code.google.com/p/gowingui
- -

-Updating: -Running go fix will update imports of these packages to use the new import paths. -Installations that depend on these packages will need to install them using -a go get command. -

- -

Major changes to the library

- -

-This section describes significant changes to the core libraries, the ones that -affect the most programs. -

- -

The error type and errors package

- -

-The placement of os.Error in package os is mostly historical: errors first came up when implementing package os, and they seemed system-related at the time. -Since then it has become clear that errors are more fundamental than the operating system. For example, it would be nice to use Errors in packages that os depends on, like syscall. -Also, having Error in os introduces many dependencies on os that would otherwise not exist. -

- -

-Go 1 solves these problems by introducing a built-in error interface type and a separate errors package (analogous to bytes and strings) that contains utility functions. -It replaces os.NewError with -errors.New, -giving errors a more central place in the environment. -

- -

-So the widely-used String method does not cause accidental satisfaction -of the error interface, the error interface uses instead -the name Error for that method: -

- -
-    type error interface {
-        Error() string
-    }
-
- -

-The fmt library automatically invokes Error, as it already -does for String, for easy printing of error values. -

- -
type SyntaxError struct {
-    File    string
-    Line    int
-    Message string
-}
-
-func (se *SyntaxError) Error() string {
-    return fmt.Sprintf("%s:%d: %s", se.File, se.Line, se.Message)
-}
- -

-All standard packages have been updated to use the new interface; the old os.Error is gone. -

- -

-A new package, errors, contains the function -

- -
-func New(text string) error
-
- -

-to turn a string into an error. It replaces the old os.NewError. -

- -
    var ErrSyntax = errors.New("syntax error")
- -

-Updating: -Running go fix will update almost all code affected by the change. -Code that defines error types with a String method will need to be updated -by hand to rename the methods to Error. -

- -

System call errors

- -

-The old syscall package, which predated os.Error -(and just about everything else), -returned errors as int values. -In turn, the os package forwarded many of these errors, such -as EINVAL, but using a different set of errors on each platform. -This behavior was unpleasant and unportable. -

- -

-In Go 1, the -syscall -package instead returns an error for system call errors. -On Unix, the implementation is done by a -syscall.Errno type -that satisfies error and replaces the old os.Errno. -

- -

-The changes affecting os.EINVAL and relatives are -described elsewhere. - -

-Updating: -Running go fix will update almost all code affected by the change. -Regardless, most code should use the os package -rather than syscall and so will be unaffected. -

- -

Time

- -

-Time is always a challenge to support well in a programming language. -The old Go time package had int64 units, no -real type safety, -and no distinction between absolute times and durations. -

- -

-One of the most sweeping changes in the Go 1 library is therefore a -complete redesign of the -time package. -Instead of an integer number of nanoseconds as an int64, -and a separate *time.Time type to deal with human -units such as hours and years, -there are now two fundamental types: -time.Time -(a value, so the * is gone), which represents a moment in time; -and time.Duration, -which represents an interval. -Both have nanosecond resolution. -A Time can represent any time into the ancient -past and remote future, while a Duration can -span plus or minus only about 290 years. -There are methods on these types, plus a number of helpful -predefined constant durations such as time.Second. -

- -

-Among the new methods are things like -Time.Add, -which adds a Duration to a Time, and -Time.Sub, -which subtracts two Times to yield a Duration. -

- -

-The most important semantic change is that the Unix epoch (Jan 1, 1970) is now -relevant only for those functions and methods that mention Unix: -time.Unix -and the Unix -and UnixNano methods -of the Time type. -In particular, -time.Now -returns a time.Time value rather than, in the old -API, an integer nanosecond count since the Unix epoch. -

- -
// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
-func sleepUntil(wakeup time.Time) {
-    now := time.Now() // A Time.
-    if !wakeup.After(now) {
-        return
-    }
-    delta := wakeup.Sub(now) // A Duration.
-    fmt.Printf("Sleeping for %.3fs\n", delta.Seconds())
-    time.Sleep(delta)
-}
- -

-The new types, methods, and constants have been propagated through -all the standard packages that use time, such as os and -its representation of file time stamps. -

- -

-Updating: -The go fix tool will update many uses of the old time package to use the new -types and methods, although it does not replace values such as 1e9 -representing nanoseconds per second. -Also, because of type changes in some of the values that arise, -some of the expressions rewritten by the fix tool may require -further hand editing; in such cases the rewrite will include -the correct function or method for the old functionality, but -may have the wrong type or require further analysis. -

- -

Minor changes to the library

- -

-This section describes smaller changes, such as those to less commonly -used packages or that affect -few programs beyond the need to run go fix. -This category includes packages that are new in Go 1. -Collectively they improve portability, regularize behavior, and -make the interfaces more modern and Go-like. -

- -

The archive/zip package

- -

-In Go 1, *zip.Writer no -longer has a Write method. Its presence was a mistake. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The bufio package

- -

-In Go 1, bufio.NewReaderSize -and -bufio.NewWriterSize -functions no longer return an error for invalid sizes. -If the argument size is too small or invalid, it is adjusted. -

- -

-Updating: -Running go fix will update calls that assign the error to _. -Calls that aren't fixed will be caught by the compiler and must be updated by hand. -

- -

The compress/flate, compress/gzip and compress/zlib packages

- -

-In Go 1, the NewWriterXxx functions in -compress/flate, -compress/gzip and -compress/zlib -all return (*Writer, error) if they take a compression level, -and *Writer otherwise. Package gzip's -Compressor and Decompressor types have been renamed -to Writer and Reader. Package flate's -WrongValueError type has been removed. -

- -

-Updating -Running go fix will update old names and calls that assign the error to _. -Calls that aren't fixed will be caught by the compiler and must be updated by hand. -

- -

The crypto/aes and crypto/des packages

- -

-In Go 1, the Reset method has been removed. Go does not guarantee -that memory is not copied and therefore this method was misleading. -

- -

-The cipher-specific types *aes.Cipher, *des.Cipher, -and *des.TripleDESCipher have been removed in favor of -cipher.Block. -

- -

-Updating: -Remove the calls to Reset. Replace uses of the specific cipher types with -cipher.Block. -

- -

The crypto/elliptic package

- -

-In Go 1, elliptic.Curve -has been made an interface to permit alternative implementations. The curve -parameters have been moved to the -elliptic.CurveParams -structure. -

- -

-Updating: -Existing users of *elliptic.Curve will need to change to -simply elliptic.Curve. Calls to Marshal, -Unmarshal and GenerateKey are now functions -in crypto/elliptic that take an elliptic.Curve -as their first argument. -

- -

The crypto/hmac package

- -

-In Go 1, the hash-specific functions, such as hmac.NewMD5, have -been removed from crypto/hmac. Instead, hmac.New takes -a function that returns a hash.Hash, such as md5.New. -

- -

-Updating: -Running go fix will perform the needed changes. -

- -

The crypto/x509 package

- -

-In Go 1, the -CreateCertificate -and -CreateCRL -functions in crypto/x509 have been altered to take an -interface{} where they previously took a *rsa.PublicKey -or *rsa.PrivateKey. This will allow other public key algorithms -to be implemented in the future. -

- -

-Updating: -No changes will be needed. -

- -

The encoding/binary package

- -

-In Go 1, the binary.TotalSize function has been replaced by -Size, -which takes an interface{} argument rather than -a reflect.Value. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The encoding/xml package

- -

-In Go 1, the xml package -has been brought closer in design to the other marshaling packages such -as encoding/gob. -

- -

-The old Parser type is renamed -Decoder and has a new -Decode method. An -Encoder type was also introduced. -

- -

-The functions Marshal -and Unmarshal -work with []byte values now. To work with streams, -use the new Encoder -and Decoder types. -

- -

-When marshaling or unmarshaling values, the format of supported flags in -field tags has changed to be closer to the -json package -(`xml:"name,flag"`). The matching done between field tags, field -names, and the XML attribute and element names is now case-sensitive. -The XMLName field tag, if present, must also match the name -of the XML element being marshaled. -

- -

-Updating: -Running go fix will update most uses of the package except for some calls to -Unmarshal. Special care must be taken with field tags, -since the fix tool will not update them and if not fixed by hand they will -misbehave silently in some cases. For example, the old -"attr" is now written ",attr" while plain -"attr" remains valid but with a different meaning. -

- -

The expvar package

- -

-In Go 1, the RemoveAll function has been removed. -The Iter function and Iter method on *Map have -been replaced by -Do -and -(*Map).Do. -

- -

-Updating: -Most code using expvar will not need changing. The rare code that used -Iter can be updated to pass a closure to Do to achieve the same effect. -

- -

The flag package

- -

-In Go 1, the interface flag.Value has changed slightly. -The Set method now returns an error instead of -a bool to indicate success or failure. -

- -

-There is also a new kind of flag, Duration, to support argument -values specifying time intervals. -Values for such flags must be given units, just as time.Duration -formats them: 10s, 1h30m, etc. -

- -
var timeout = flag.Duration("timeout", 30*time.Second, "how long to wait for completion")
- -

-Updating: -Programs that implement their own flags will need minor manual fixes to update their -Set methods. -The Duration flag is new and affects no existing code. -

- - -

The go/* packages

- -

-Several packages under go have slightly revised APIs. -

- -

-A concrete Mode type was introduced for configuration mode flags -in the packages -go/scanner, -go/parser, -go/printer, and -go/doc. -

- -

-The modes AllowIllegalChars and InsertSemis have been removed -from the go/scanner package. They were mostly -useful for scanning text other then Go source files. Instead, the -text/scanner package should be used -for that purpose. -

- -

-The ErrorHandler provided -to the scanner's Init method is -now simply a function rather than an interface. The ErrorVector type has -been removed in favor of the (existing) ErrorList -type, and the ErrorVector methods have been migrated. Instead of embedding -an ErrorVector in a client of the scanner, now a client should maintain -an ErrorList. -

- -

-The set of parse functions provided by the go/parser -package has been reduced to the primary parse function -ParseFile, and a couple of -convenience functions ParseDir -and ParseExpr. -

- -

-The go/printer package supports an additional -configuration mode SourcePos; -if set, the printer will emit //line comments such that the generated -output contains the original source code position information. The new type -CommentedNode can be -used to provide comments associated with an arbitrary -ast.Node (until now only -ast.File carried comment information). -

- -

-The type names of the go/doc package have been -streamlined by removing the Doc suffix: PackageDoc -is now Package, ValueDoc is Value, etc. -Also, all types now consistently have a Name field (or Names, -in the case of type Value) and Type.Factories has become -Type.Funcs. -Instead of calling doc.NewPackageDoc(pkg, importpath), -documentation for a package is created with: -

- -
-    doc.New(pkg, importpath, mode)
-
- -

-where the new mode parameter specifies the operation mode: -if set to AllDecls, all declarations -(not just exported ones) are considered. -The function NewFileDoc was removed, and the function -CommentText has become the method -Text of -ast.CommentGroup. -

- -

-In package go/token, the -token.FileSet method Files -(which originally returned a channel of *token.Files) has been replaced -with the iterator Iterate that -accepts a function argument instead. -

- -

-In package go/build, the API -has been nearly completely replaced. -The package still computes Go package information -but it does not run the build: the Cmd and Script -types are gone. -(To build code, use the new -go command instead.) -The DirInfo type is now named -Package. -FindTree and ScanDir are replaced by -Import -and -ImportDir. -

- -

-Updating: -Code that uses packages in go will have to be updated by hand; the -compiler will reject incorrect uses. Templates used in conjunction with any of the -go/doc types may need manual fixes; the renamed fields will lead -to run-time errors. -

- -

The hash package

- -

-In Go 1, the definition of hash.Hash includes -a new method, BlockSize. This new method is used primarily in the -cryptographic libraries. -

- -

-The Sum method of the -hash.Hash interface now takes a -[]byte argument, to which the hash value will be appended. -The previous behavior can be recreated by adding a nil argument to the call. -

- -

-Updating: -Existing implementations of hash.Hash will need to add a -BlockSize method. Hashes that process the input one byte at -a time can implement BlockSize to return 1. -Running go fix will update calls to the Sum methods of the various -implementations of hash.Hash. -

- -

-Updating: -Since the package's functionality is new, no updating is necessary. -

- -

The http package

- -

-In Go 1 the http package is refactored, -putting some of the utilities into a -httputil subdirectory. -These pieces are only rarely needed by HTTP clients. -The affected items are: -

- -
    -
  • ClientConn
  • -
  • DumpRequest
  • -
  • DumpRequestOut
  • -
  • DumpResponse
  • -
  • NewChunkedReader
  • -
  • NewChunkedWriter
  • -
  • NewClientConn
  • -
  • NewProxyClientConn
  • -
  • NewServerConn
  • -
  • NewSingleHostReverseProxy
  • -
  • ReverseProxy
  • -
  • ServerConn
  • -
- -

-The Request.RawURL field has been removed; it was a -historical artifact. -

- -

-The Handle and HandleFunc -functions, and the similarly-named methods of ServeMux, -now panic if an attempt is made to register the same pattern twice. -

- -

-Updating: -Running go fix will update the few programs that are affected except for -uses of RawURL, which must be fixed by hand. -

- -

The image package

- -

-The image package has had a number of -minor changes, rearrangements and renamings. -

- -

-Most of the color handling code has been moved into its own package, -image/color. -For the elements that moved, a symmetry arises; for instance, -each pixel of an -image.RGBA -is a -color.RGBA. -

- -

-The old image/ycbcr package has been folded, with some -renamings, into the -image -and -image/color -packages. -

- -

-The old image.ColorImage type is still in the image -package but has been renamed -image.Uniform, -while image.Tiled has been removed. -

- -

-This table lists the renamings. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OldNew

image.Color color.Color
image.ColorModel color.Model
image.ColorModelFunc color.ModelFunc
image.PalettedColorModel color.Palette

image.RGBAColor color.RGBA
image.RGBA64Color color.RGBA64
image.NRGBAColor color.NRGBA
image.NRGBA64Color color.NRGBA64
image.AlphaColor color.Alpha
image.Alpha16Color color.Alpha16
image.GrayColor color.Gray
image.Gray16Color color.Gray16

image.RGBAColorModel color.RGBAModel
image.RGBA64ColorModel color.RGBA64Model
image.NRGBAColorModel color.NRGBAModel
image.NRGBA64ColorModel color.NRGBA64Model
image.AlphaColorModel color.AlphaModel
image.Alpha16ColorModel color.Alpha16Model
image.GrayColorModel color.GrayModel
image.Gray16ColorModel color.Gray16Model

ycbcr.RGBToYCbCr color.RGBToYCbCr
ycbcr.YCbCrToRGB color.YCbCrToRGB
ycbcr.YCbCrColorModel color.YCbCrModel
ycbcr.YCbCrColor color.YCbCr
ycbcr.YCbCr image.YCbCr

ycbcr.SubsampleRatio444 image.YCbCrSubsampleRatio444
ycbcr.SubsampleRatio422 image.YCbCrSubsampleRatio422
ycbcr.SubsampleRatio420 image.YCbCrSubsampleRatio420

image.ColorImage image.Uniform
- -

-The image package's New functions -(NewRGBA, -NewRGBA64, etc.) -take an image.Rectangle as an argument -instead of four integers. -

- -

-Finally, there are new predefined color.Color variables -color.Black, -color.White, -color.Opaque -and -color.Transparent. -

- -

-Updating: -Running go fix will update almost all code affected by the change. -

- -

The log/syslog package

- -

-In Go 1, the syslog.NewLogger -function returns an error as well as a log.Logger. -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The mime package

- -

-In Go 1, the FormatMediaType function -of the mime package has been simplified to make it -consistent with -ParseMediaType. -It now takes "text/html" rather than "text" and "html". -

- -

-Updating: -What little code is affected will be caught by the compiler and must be updated by hand. -

- -

The net package

- -

-In Go 1, the various SetTimeout, -SetReadTimeout, and SetWriteTimeout methods -have been replaced with -SetDeadline, -SetReadDeadline, and -SetWriteDeadline, -respectively. Rather than taking a timeout value in nanoseconds that -apply to any activity on the connection, the new methods set an -absolute deadline (as a time.Time value) after which -reads and writes will time out and no longer block. -

- -

-There are also new functions -net.DialTimeout -to simplify timing out dialing a network address and -net.ListenMulticastUDP -to allow multicast UDP to listen concurrently across multiple listeners. -The net.ListenMulticastUDP function replaces the old -JoinGroup and LeaveGroup methods. -

- -

-Updating: -Code that uses the old methods will fail to compile and must be updated by hand. -The semantic change makes it difficult for the fix tool to update automatically. -

- -

The os package

- -

-The Time function has been removed; callers should use -the Time type from the -time package. -

- -

-The Exec function has been removed; callers should use -Exec from the syscall package, where available. -

- -

-The ShellExpand function has been renamed to ExpandEnv. -

- -

-The NewFile function -now takes a uintptr fd, instead of an int. -The Fd method on files now -also returns a uintptr. -

- -

-There are no longer error constants such as EINVAL -in the os package, since the set of values varied with -the underlying operating system. There are new portable functions like -IsPermission -to test common error properties, plus a few new error values -with more Go-like names, such as -ErrPermission -and -ErrNoEnv. -

- -

-The Getenverror function has been removed. To distinguish -between a non-existent environment variable and an empty string, -use os.Environ or -syscall.Getenv. -

- - -

-The Process.Wait method has -dropped its option argument and the associated constants are gone -from the package. -Also, the function Wait is gone; only the method of -the Process type persists. -

- -

-The Waitmsg type returned by -Process.Wait -has been replaced with a more portable -ProcessState -type with accessor methods to recover information about the -process. -Because of changes to Wait, the ProcessState -value always describes an exited process. -Portability concerns simplified the interface in other ways, but the values returned by the -ProcessState.Sys and -ProcessState.SysUsage -methods can be type-asserted to underlying system-specific data structures such as -syscall.WaitStatus and -syscall.Rusage on Unix. -

- -

-Updating: -Running go fix will drop a zero argument to Process.Wait. -All other changes will be caught by the compiler and must be updated by hand. -

- -

The os.FileInfo type

- -

-Go 1 redefines the os.FileInfo type, -changing it from a struct to an interface: -

- -
-    type FileInfo interface {
-        Name() string       // base name of the file
-        Size() int64        // length in bytes
-        Mode() FileMode     // file mode bits
-        ModTime() time.Time // modification time
-        IsDir() bool        // abbreviation for Mode().IsDir()
-        Sys() interface{}   // underlying data source (can return nil)
-    }
-
- -

-The file mode information has been moved into a subtype called -os.FileMode, -a simple integer type with IsDir, Perm, and String -methods. -

- -

-The system-specific details of file modes and properties such as (on Unix) -i-number have been removed from FileInfo altogether. -Instead, each operating system's os package provides an -implementation of the FileInfo interface, which -has a Sys method that returns the -system-specific representation of file metadata. -For instance, to discover the i-number of a file on a Unix system, unpack -the FileInfo like this: -

- -
-    fi, err := os.Stat("hello.go")
-    if err != nil {
-        log.Fatal(err)
-    }
-    // Check that it's a Unix file.
-    unixStat, ok := fi.Sys().(*syscall.Stat_t)
-    if !ok {
-        log.Fatal("hello.go: not a Unix file")
-    }
-    fmt.Printf("file i-number: %d\n", unixStat.Ino)
-
- -

-Assuming (which is unwise) that "hello.go" is a Unix file, -the i-number expression could be contracted to -

- -
-    fi.Sys().(*syscall.Stat_t).Ino
-
- -

-The vast majority of uses of FileInfo need only the methods -of the standard interface. -

- -

-The os package no longer contains wrappers for the POSIX errors -such as ENOENT. -For the few programs that need to verify particular error conditions, there are -now the boolean functions -IsExist, -IsNotExist -and -IsPermission. -

- -
    f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
-    if os.IsExist(err) {
-        log.Printf("%s already exists", name)
-    }
- -

-Updating: -Running go fix will update code that uses the old equivalent of the current os.FileInfo -and os.FileMode API. -Code that needs system-specific file details will need to be updated by hand. -Code that uses the old POSIX error values from the os package -will fail to compile and will also need to be updated by hand. -

- -

The os/signal package

- -

-The os/signal package in Go 1 replaces the -Incoming function, which returned a channel -that received all incoming signals, -with the selective Notify function, which asks -for delivery of specific signals on an existing channel. -

- -

-Updating: -Code must be updated by hand. -A literal translation of -

-
-c := signal.Incoming()
-
-

-is -

-
-c := make(chan os.Signal)
-signal.Notify(c) // ask for all signals
-
-

-but most code should list the specific signals it wants to handle instead: -

-
-c := make(chan os.Signal)
-signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
-
- -

The path/filepath package

- -

-In Go 1, the Walk function of the -path/filepath package -has been changed to take a function value of type -WalkFunc -instead of a Visitor interface value. -WalkFunc unifies the handling of both files and directories. -

- -
-    type WalkFunc func(path string, info os.FileInfo, err error) error
-
- -

-The WalkFunc function will be called even for files or directories that could not be opened; -in such cases the error argument will describe the failure. -If a directory's contents are to be skipped, -the function should return the value filepath.SkipDir -

- -
    markFn := func(path string, info os.FileInfo, err error) error {
-        if path == "pictures" { // Will skip walking of directory pictures and its contents.
-            return filepath.SkipDir
-        }
-        if err != nil {
-            return err
-        }
-        log.Println(path)
-        return nil
-    }
-    err := filepath.Walk(".", markFn)
-    if err != nil {
-        log.Fatal(err)
-    }
- -

-Updating: -The change simplifies most code but has subtle consequences, so affected programs -will need to be updated by hand. -The compiler will catch code using the old interface. -

- -

The regexp package

- -

-The regexp package has been rewritten. -It has the same interface but the specification of the regular expressions -it supports has changed from the old "egrep" form to that of -RE2. -

- -

-Updating: -Code that uses the package should have its regular expressions checked by hand. -

- -

The runtime package

- -

-In Go 1, much of the API exported by package -runtime has been removed in favor of -functionality provided by other packages. -Code using the runtime.Type interface -or its specific concrete type implementations should -now use package reflect. -Code using runtime.Semacquire or runtime.Semrelease -should use channels or the abstractions in package sync. -The runtime.Alloc, runtime.Free, -and runtime.Lookup functions, an unsafe API created for -debugging the memory allocator, have no replacement. -

- -

-Before, runtime.MemStats was a global variable holding -statistics about memory allocation, and calls to runtime.UpdateMemStats -ensured that it was up to date. -In Go 1, runtime.MemStats is a struct type, and code should use -runtime.ReadMemStats -to obtain the current statistics. -

- -

-The package adds a new function, -runtime.NumCPU, that returns the number of CPUs available -for parallel execution, as reported by the operating system kernel. -Its value can inform the setting of GOMAXPROCS. -The runtime.Cgocalls and runtime.Goroutines functions -have been renamed to runtime.NumCgoCall and runtime.NumGoroutine. -

- -

-Updating: -Running go fix will update code for the function renamings. -Other code will need to be updated by hand. -

- -

The strconv package

- -

-In Go 1, the -strconv -package has been significantly reworked to make it more Go-like and less C-like, -although Atoi lives on (it's similar to -int(ParseInt(x, 10, 0)), as does -Itoa(x) (FormatInt(int64(x), 10)). -There are also new variants of some of the functions that append to byte slices rather than -return strings, to allow control over allocation. -

- -

-This table summarizes the renamings; see the -package documentation -for full details. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Old callNew call

Atob(x) ParseBool(x)

Atof32(x) ParseFloat(x, 32)§
Atof64(x) ParseFloat(x, 64)
AtofN(x, n) ParseFloat(x, n)

Atoi(x) Atoi(x)
Atoi(x) ParseInt(x, 10, 0)§
Atoi64(x) ParseInt(x, 10, 64)

Atoui(x) ParseUint(x, 10, 0)§
Atoui64(x) ParseUint(x, 10, 64)

Btoi64(x, b) ParseInt(x, b, 64)
Btoui64(x, b) ParseUint(x, b, 64)

Btoa(x) FormatBool(x)

Ftoa32(x, f, p) FormatFloat(float64(x), f, p, 32)
Ftoa64(x, f, p) FormatFloat(x, f, p, 64)
FtoaN(x, f, p, n) FormatFloat(x, f, p, n)

Itoa(x) Itoa(x)
Itoa(x) FormatInt(int64(x), 10)
Itoa64(x) FormatInt(x, 10)

Itob(x, b) FormatInt(int64(x), b)
Itob64(x, b) FormatInt(x, b)

Uitoa(x) FormatUint(uint64(x), 10)
Uitoa64(x) FormatUint(x, 10)

Uitob(x, b) FormatUint(uint64(x), b)
Uitob64(x, b) FormatUint(x, b)
- -

-Updating: -Running go fix will update almost all code affected by the change. -
Atoi persists but Atoui and Atof32 do not, so -they may require -a cast that must be added by hand; the go fix tool will warn about it. -

- - -

The template packages

- -

-The template and exp/template/html packages have moved to -text/template and -html/template. -More significant, the interface to these packages has been simplified. -The template language is the same, but the concept of "template set" is gone -and the functions and methods of the packages have changed accordingly, -often by elimination. -

- -

-Instead of sets, a Template object -may contain multiple named template definitions, -in effect constructing -name spaces for template invocation. -A template can invoke any other template associated with it, but only those -templates associated with it. -The simplest way to associate templates is to parse them together, something -made easier with the new structure of the packages. -

- -

-Updating: -The imports will be updated by fix tool. -Single-template uses will be otherwise be largely unaffected. -Code that uses multiple templates in concert will need to be updated by hand. -The examples in -the documentation for text/template can provide guidance. -

- -

The testing package

- -

-The testing package has a type, B, passed as an argument to benchmark functions. -In Go 1, B has new methods, analogous to those of T, enabling -logging and failure reporting. -

- -
func BenchmarkSprintf(b *testing.B) {
-    // Verify correctness before running benchmark.
-    b.StopTimer()
-    got := fmt.Sprintf("%x", 23)
-    const expect = "17"
-    if expect != got {
-        b.Fatalf("expected %q; got %q", expect, got)
-    }
-    b.StartTimer()
-    for i := 0; i < b.N; i++ {
-        fmt.Sprintf("%x", 23)
-    }
-}
- -

-Updating: -Existing code is unaffected, although benchmarks that use println -or panic should be updated to use the new methods. -

- -

The testing/script package

- -

-The testing/script package has been deleted. It was a dreg. -

- -

-Updating: -No code is likely to be affected. -

- -

The unsafe package

- -

-In Go 1, the functions -unsafe.Typeof, unsafe.Reflect, -unsafe.Unreflect, unsafe.New, and -unsafe.NewArray have been removed; -they duplicated safer functionality provided by -package reflect. -

- -

-Updating: -Code using these functions must be rewritten to use -package reflect. -The changes to encoding/gob and the protocol buffer library -may be helpful as examples. -

- -

The url package

- -

-In Go 1 several fields from the url.URL type -were removed or replaced. -

- -

-The String method now -predictably rebuilds an encoded URL string using all of URL's -fields as necessary. The resulting string will also no longer have -passwords escaped. -

- -

-The Raw field has been removed. In most cases the String -method may be used in its place. -

- -

-The old RawUserinfo field is replaced by the User -field, of type *net.Userinfo. -Values of this type may be created using the new net.User -and net.UserPassword -functions. The EscapeUserinfo and UnescapeUserinfo -functions are also gone. -

- -

-The RawAuthority field has been removed. The same information is -available in the Host and User fields. -

- -

-The RawPath field and the EncodedPath method have -been removed. The path information in rooted URLs (with a slash following the -schema) is now available only in decoded form in the Path field. -Occasionally, the encoded data may be required to obtain information that -was lost in the decoding process. These cases must be handled by accessing -the data the URL was built from. -

- -

-URLs with non-rooted paths, such as "mailto:dev@golang.org?subject=Hi", -are also handled differently. The OpaquePath boolean field has been -removed and a new Opaque string field introduced to hold the encoded -path for such URLs. In Go 1, the cited URL parses as: -

- -
-    URL{
-        Scheme: "mailto",
-        Opaque: "dev@golang.org",
-        RawQuery: "subject=Hi",
-    }
-
- -

-A new RequestURI method was -added to URL. -

- -

-The ParseWithReference function has been renamed to ParseWithFragment. -

- -

-Updating: -Code that uses the old fields will fail to compile and must be updated by hand. -The semantic changes make it difficult for the fix tool to update automatically. -

- -

The go command

- -

-Go 1 introduces the go command, a tool for fetching, -building, and installing Go packages and commands. The go command -does away with makefiles, instead using Go source code to find dependencies and -determine build conditions. Most existing Go programs will no longer require -makefiles to be built. -

- -

-See How to Write Go Code for a primer on the -go command and the go command documentation -for the full details. -

- -

-Updating: -Projects that depend on the Go project's old makefile-based build -infrastructure (Make.pkg, Make.cmd, and so on) should -switch to using the go command for building Go code and, if -necessary, rewrite their makefiles to perform any auxiliary build tasks. -

- -

The cgo command

- -

-In Go 1, the cgo command -uses a different _cgo_export.h -file, which is generated for packages containing //export lines. -The _cgo_export.h file now begins with the C preamble comment, -so that exported function definitions can use types defined there. -This has the effect of compiling the preamble multiple times, so a -package using //export must not put function definitions -or variable initializations in the C preamble. -

- -

Packaged releases

- -

-One of the most significant changes associated with Go 1 is the availability -of prepackaged, downloadable distributions. -They are available for many combinations of architecture and operating system -(including Windows) and the list will grow. -Installation details are described on the -Getting Started page, while -the distributions themselves are listed on the -downloads page. - - -

- - - - - - - - diff --git a/vendor/golang.org/x/net/html/testdata/webkit/README b/vendor/golang.org/x/net/html/testdata/webkit/README deleted file mode 100644 index 9b4c2d8be0a..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/README +++ /dev/null @@ -1,28 +0,0 @@ -The *.dat files in this directory are copied from The WebKit Open Source -Project, specifically $WEBKITROOT/LayoutTests/html5lib/resources. -WebKit is licensed under a BSD style license. -http://webkit.org/coding/bsd-license.html says: - -Copyright (C) 2009 Apple Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -2. 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. - -THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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/golang.org/x/net/html/testdata/webkit/adoption01.dat b/vendor/golang.org/x/net/html/testdata/webkit/adoption01.dat deleted file mode 100644 index 787e1b01e19..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/adoption01.dat +++ /dev/null @@ -1,194 +0,0 @@ -#data -

-#errors -#document -| -| -| -| -|

-| - -#data -1

23

-#errors -#document -| -| -| -| -| "1" -|

-| -| "2" -| "3" - -#data -1 -#errors -#document -| -| -| -| -| "1" -| -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 20 Unexpected end tag (strong) in table context caused voodoo mode. -Line: 1 Col: 20 End tag (strong) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 24 Unexpected end tag (b) in table context caused voodoo mode. -Line: 1 Col: 24 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 29 Unexpected end tag (em) in table context caused voodoo mode. -Line: 1 Col: 29 End tag (em) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 33 Unexpected end tag (i) in table context caused voodoo mode. -Line: 1 Col: 33 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 37 Unexpected end tag (u) in table context caused voodoo mode. -Line: 1 Col: 37 End tag (u) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 46 Unexpected end tag (strike) in table context caused voodoo mode. -Line: 1 Col: 46 End tag (strike) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 50 Unexpected end tag (s) in table context caused voodoo mode. -Line: 1 Col: 50 End tag (s) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 58 Unexpected end tag (blink) in table context caused voodoo mode. -Line: 1 Col: 58 Unexpected end tag (blink). Ignored. -Line: 1 Col: 63 Unexpected end tag (tt) in table context caused voodoo mode. -Line: 1 Col: 63 End tag (tt) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 69 Unexpected end tag (pre) in table context caused voodoo mode. -Line: 1 Col: 69 End tag (pre) seen too early. Expected other end tag. -Line: 1 Col: 75 Unexpected end tag (big) in table context caused voodoo mode. -Line: 1 Col: 75 End tag (big) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 83 Unexpected end tag (small) in table context caused voodoo mode. -Line: 1 Col: 83 End tag (small) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 90 Unexpected end tag (font) in table context caused voodoo mode. -Line: 1 Col: 90 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 99 Unexpected end tag (select) in table context caused voodoo mode. -Line: 1 Col: 99 Unexpected end tag (select). Ignored. -Line: 1 Col: 104 Unexpected end tag (h1) in table context caused voodoo mode. -Line: 1 Col: 104 End tag (h1) seen too early. Expected other end tag. -Line: 1 Col: 109 Unexpected end tag (h2) in table context caused voodoo mode. -Line: 1 Col: 109 End tag (h2) seen too early. Expected other end tag. -Line: 1 Col: 114 Unexpected end tag (h3) in table context caused voodoo mode. -Line: 1 Col: 114 End tag (h3) seen too early. Expected other end tag. -Line: 1 Col: 119 Unexpected end tag (h4) in table context caused voodoo mode. -Line: 1 Col: 119 End tag (h4) seen too early. Expected other end tag. -Line: 1 Col: 124 Unexpected end tag (h5) in table context caused voodoo mode. -Line: 1 Col: 124 End tag (h5) seen too early. Expected other end tag. -Line: 1 Col: 129 Unexpected end tag (h6) in table context caused voodoo mode. -Line: 1 Col: 129 End tag (h6) seen too early. Expected other end tag. -Line: 1 Col: 136 Unexpected end tag (body) in the table row phase. Ignored. -Line: 1 Col: 141 Unexpected end tag (br) in table context caused voodoo mode. -Line: 1 Col: 141 Unexpected end tag (br). Treated as br element. -Line: 1 Col: 145 Unexpected end tag (a) in table context caused voodoo mode. -Line: 1 Col: 145 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 151 Unexpected end tag (img) in table context caused voodoo mode. -Line: 1 Col: 151 This element (img) has no end tag. -Line: 1 Col: 159 Unexpected end tag (title) in table context caused voodoo mode. -Line: 1 Col: 159 Unexpected end tag (title). Ignored. -Line: 1 Col: 166 Unexpected end tag (span) in table context caused voodoo mode. -Line: 1 Col: 166 Unexpected end tag (span). Ignored. -Line: 1 Col: 174 Unexpected end tag (style) in table context caused voodoo mode. -Line: 1 Col: 174 Unexpected end tag (style). Ignored. -Line: 1 Col: 183 Unexpected end tag (script) in table context caused voodoo mode. -Line: 1 Col: 183 Unexpected end tag (script). Ignored. -Line: 1 Col: 196 Unexpected end tag (th). Ignored. -Line: 1 Col: 201 Unexpected end tag (td). Ignored. -Line: 1 Col: 206 Unexpected end tag (tr). Ignored. -Line: 1 Col: 214 This element (frame) has no end tag. -Line: 1 Col: 221 This element (area) has no end tag. -Line: 1 Col: 228 Unexpected end tag (link). Ignored. -Line: 1 Col: 236 This element (param) has no end tag. -Line: 1 Col: 241 This element (hr) has no end tag. -Line: 1 Col: 249 This element (input) has no end tag. -Line: 1 Col: 255 Unexpected end tag (col). Ignored. -Line: 1 Col: 262 Unexpected end tag (base). Ignored. -Line: 1 Col: 269 Unexpected end tag (meta). Ignored. -Line: 1 Col: 280 This element (basefont) has no end tag. -Line: 1 Col: 290 This element (bgsound) has no end tag. -Line: 1 Col: 298 This element (embed) has no end tag. -Line: 1 Col: 307 This element (spacer) has no end tag. -Line: 1 Col: 311 Unexpected end tag (p). Ignored. -Line: 1 Col: 316 End tag (dd) seen too early. Expected other end tag. -Line: 1 Col: 321 End tag (dt) seen too early. Expected other end tag. -Line: 1 Col: 331 Unexpected end tag (caption). Ignored. -Line: 1 Col: 342 Unexpected end tag (colgroup). Ignored. -Line: 1 Col: 350 Unexpected end tag (tbody). Ignored. -Line: 1 Col: 358 Unexpected end tag (tfoot). Ignored. -Line: 1 Col: 366 Unexpected end tag (thead). Ignored. -Line: 1 Col: 376 End tag (address) seen too early. Expected other end tag. -Line: 1 Col: 389 End tag (blockquote) seen too early. Expected other end tag. -Line: 1 Col: 398 End tag (center) seen too early. Expected other end tag. -Line: 1 Col: 404 Unexpected end tag (dir). Ignored. -Line: 1 Col: 410 End tag (div) seen too early. Expected other end tag. -Line: 1 Col: 415 End tag (dl) seen too early. Expected other end tag. -Line: 1 Col: 426 End tag (fieldset) seen too early. Expected other end tag. -Line: 1 Col: 436 End tag (listing) seen too early. Expected other end tag. -Line: 1 Col: 443 End tag (menu) seen too early. Expected other end tag. -Line: 1 Col: 448 End tag (ol) seen too early. Expected other end tag. -Line: 1 Col: 453 End tag (ul) seen too early. Expected other end tag. -Line: 1 Col: 458 End tag (li) seen too early. Expected other end tag. -Line: 1 Col: 465 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm. -Line: 1 Col: 471 This element (wbr) has no end tag. -Line: 1 Col: 487 End tag (button) seen too early. Expected other end tag. -Line: 1 Col: 497 End tag (marquee) seen too early. Expected other end tag. -Line: 1 Col: 506 End tag (object) seen too early. Expected other end tag. -Line: 1 Col: 524 Unexpected end tag (html). Ignored. -Line: 1 Col: 524 Unexpected end tag (frameset). Ignored. -Line: 1 Col: 531 Unexpected end tag (head). Ignored. -Line: 1 Col: 540 Unexpected end tag (iframe). Ignored. -Line: 1 Col: 548 This element (image) has no end tag. -Line: 1 Col: 558 This element (isindex) has no end tag. -Line: 1 Col: 568 Unexpected end tag (noembed). Ignored. -Line: 1 Col: 579 Unexpected end tag (noframes). Ignored. -Line: 1 Col: 590 Unexpected end tag (noscript). Ignored. -Line: 1 Col: 601 Unexpected end tag (optgroup). Ignored. -Line: 1 Col: 610 Unexpected end tag (option). Ignored. -Line: 1 Col: 622 Unexpected end tag (plaintext). Ignored. -Line: 1 Col: 633 Unexpected end tag (textarea). Ignored. -#document -| -| -| -|
-| -| -| -|

- -#data - -#errors -Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. -Line: 1 Col: 10 Expected closing tag. Unexpected end of file. -#document -| -| -| diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat deleted file mode 100644 index 4f8df86f208..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests10.dat +++ /dev/null @@ -1,799 +0,0 @@ -#data - -#errors -#document -| -| -| -| -| - -#data -a -#errors -29: Bogus comment -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| - -#data - -#errors -35: Stray “svg” start tag. -42: Stray end tag “svg” -#document -| -| -| -| -| -#errors -43: Stray “svg” start tag. -50: Stray end tag “svg” -#document -| -| -| -| -|

-#errors -34: Start tag “svg” seen in “table”. -41: Stray end tag “svg”. -#document -| -| -| -| -| -| - -#data -
foo
-#errors -34: Start tag “svg” seen in “table”. -46: Stray end tag “g”. -53: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| - -#data -
foobar
-#errors -34: Start tag “svg” seen in “table”. -46: Stray end tag “g”. -58: Stray end tag “g”. -65: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -| - -#data -
foobar
-#errors -41: Start tag “svg” seen in “table”. -53: Stray end tag “g”. -65: Stray end tag “g”. -72: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -| -| - -#data -
foobar
-#errors -45: Start tag “svg” seen in “table”. -57: Stray end tag “g”. -69: Stray end tag “g”. -76: Stray end tag “svg”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -| -| -| - -#data -
foobar
-#errors -#document -| -| -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" - -#data -
foobar

baz

-#errors -#document -| -| -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -
foobar

baz

-#errors -#document -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -
foobar

baz

quux -#errors -70: HTML start tag “p” in a foreign namespace context. -81: “table” closed but “caption” was still open. -#document -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -|

-| "baz" -|

-| "quux" - -#data -
foobarbaz

quux -#errors -78: “table” closed but “caption” was still open. -78: Unclosed elements on stack. -#document -| -| -| -| -| -|
-| -| -| "foo" -| -| "bar" -| "baz" -|

-| "quux" - -#data -foobar

baz

quux -#errors -44: Start tag “svg” seen in “table”. -56: Stray end tag “g”. -68: Stray end tag “g”. -71: HTML start tag “p” in a foreign namespace context. -71: Start tag “p” seen in “table”. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -|

-| "baz" -| -| -|

-| "quux" - -#data -

quux -#errors -50: Stray “svg” start tag. -54: Stray “g” start tag. -62: Stray end tag “g” -66: Stray “g” start tag. -74: Stray end tag “g” -77: Stray “p” start tag. -88: “table” end tag with “select” open. -#document -| -| -| -| -| -| -| -|
-|

quux -#errors -36: Start tag “select” seen in “table”. -42: Stray “svg” start tag. -46: Stray “g” start tag. -54: Stray end tag “g” -58: Stray “g” start tag. -66: Stray end tag “g” -69: Stray “p” start tag. -80: “table” end tag with “select” open. -#document -| -| -| -| -| -|

-| "quux" - -#data -foobar

baz -#errors -41: Stray “svg” start tag. -68: HTML start tag “p” in a foreign namespace context. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -foobar

baz -#errors -34: Stray “svg” start tag. -61: HTML start tag “p” in a foreign namespace context. -#document -| -| -| -| -| -| -| "foo" -| -| "bar" -|

-| "baz" - -#data -

-#errors -31: Stray “svg” start tag. -35: Stray “g” start tag. -40: Stray end tag “g” -44: Stray “g” start tag. -49: Stray end tag “g” -52: Stray “p” start tag. -58: Stray “span” start tag. -58: End of file seen and there were open elements. -#document -| -| -| -| - -#data -

-#errors -42: Stray “svg” start tag. -46: Stray “g” start tag. -51: Stray end tag “g” -55: Stray “g” start tag. -60: Stray end tag “g” -63: Stray “p” start tag. -69: Stray “span” start tag. -#document -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| xlink:href="foo" -| -| xlink href="foo" - -#data - -#errors -#document -| -| -| -| -| xlink:href="foo" -| xml:lang="en" -| -| -| xlink href="foo" -| xml lang="en" - -#data - -#errors -#document -| -| -| -| -| xlink:href="foo" -| xml:lang="en" -| -| -| xlink href="foo" -| xml lang="en" - -#data -bar -#errors -#document -| -| -| -| -| xlink:href="foo" -| xml:lang="en" -| -| -| xlink href="foo" -| xml lang="en" -| "bar" - -#data - -#errors -#document -| -| -| -| - -#data -

a -#errors -#document -| -| -| -|
-| -| "a" - -#data -
a -#errors -#document -| -| -| -|
-| -| -| "a" - -#data -
-#errors -#document -| -| -| -|
-| -| -| - -#data -
a -#errors -#document -| -| -| -|
-| -| -| -| -| "a" - -#data -

a -#errors -#document -| -| -| -|

-| -| -| -|

-| "a" - -#data -
    a -#errors -40: HTML start tag “ul” in a foreign namespace context. -41: End of file in a foreign namespace context. -#document -| -| -| -| -| -| -|
    -| -|
      -| "a" - -#data -
        a -#errors -35: HTML start tag “ul” in a foreign namespace context. -36: End of file in a foreign namespace context. -#document -| -| -| -| -| -| -| -|
          -| "a" - -#data -

          -#errors -#document -| -| -| -| -|

          -| -| -|

          - -#data -

          -#errors -#document -| -| -| -| -|

          -| -| -|

          - -#data -

          -#errors -#document -| -| -| -|

          -| -| -| -|

          -|

          - -#data -
          -#errors -#document -| -| -| -| -| -|
          -| -|
          -| -| - -#data -
          -#errors -#document -| -| -| -| -| -| -| -|
          -|
          -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data -

-#errors -#document -| -| -| -| -|
-| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| - -#data -
-#errors -#document -| -| -| -| -| -| -| -|
-| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat deleted file mode 100644 index 638cde479f7..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests11.dat +++ /dev/null @@ -1,482 +0,0 @@ -#data - -#errors -#document -| -| -| -| -| -| attributeName="" -| attributeType="" -| baseFrequency="" -| baseProfile="" -| calcMode="" -| clipPathUnits="" -| contentScriptType="" -| contentStyleType="" -| diffuseConstant="" -| edgeMode="" -| externalResourcesRequired="" -| filterRes="" -| filterUnits="" -| glyphRef="" -| gradientTransform="" -| gradientUnits="" -| kernelMatrix="" -| kernelUnitLength="" -| keyPoints="" -| keySplines="" -| keyTimes="" -| lengthAdjust="" -| limitingConeAngle="" -| markerHeight="" -| markerUnits="" -| markerWidth="" -| maskContentUnits="" -| maskUnits="" -| numOctaves="" -| pathLength="" -| patternContentUnits="" -| patternTransform="" -| patternUnits="" -| pointsAtX="" -| pointsAtY="" -| pointsAtZ="" -| preserveAlpha="" -| preserveAspectRatio="" -| primitiveUnits="" -| refX="" -| refY="" -| repeatCount="" -| repeatDur="" -| requiredExtensions="" -| requiredFeatures="" -| specularConstant="" -| specularExponent="" -| spreadMethod="" -| startOffset="" -| stdDeviation="" -| stitchTiles="" -| surfaceScale="" -| systemLanguage="" -| tableValues="" -| targetX="" -| targetY="" -| textLength="" -| viewBox="" -| viewTarget="" -| xChannelSelector="" -| yChannelSelector="" -| zoomAndPan="" - -#data - -#errors -#document -| -| -| -| -| -| attributeName="" -| attributeType="" -| baseFrequency="" -| baseProfile="" -| calcMode="" -| clipPathUnits="" -| contentScriptType="" -| contentStyleType="" -| diffuseConstant="" -| edgeMode="" -| externalResourcesRequired="" -| filterRes="" -| filterUnits="" -| glyphRef="" -| gradientTransform="" -| gradientUnits="" -| kernelMatrix="" -| kernelUnitLength="" -| keyPoints="" -| keySplines="" -| keyTimes="" -| lengthAdjust="" -| limitingConeAngle="" -| markerHeight="" -| markerUnits="" -| markerWidth="" -| maskContentUnits="" -| maskUnits="" -| numOctaves="" -| pathLength="" -| patternContentUnits="" -| patternTransform="" -| patternUnits="" -| pointsAtX="" -| pointsAtY="" -| pointsAtZ="" -| preserveAlpha="" -| preserveAspectRatio="" -| primitiveUnits="" -| refX="" -| refY="" -| repeatCount="" -| repeatDur="" -| requiredExtensions="" -| requiredFeatures="" -| specularConstant="" -| specularExponent="" -| spreadMethod="" -| startOffset="" -| stdDeviation="" -| stitchTiles="" -| surfaceScale="" -| systemLanguage="" -| tableValues="" -| targetX="" -| targetY="" -| textLength="" -| viewBox="" -| viewTarget="" -| xChannelSelector="" -| yChannelSelector="" -| zoomAndPan="" - -#data - -#errors -#document -| -| -| -| -| -| attributeName="" -| attributeType="" -| baseFrequency="" -| baseProfile="" -| calcMode="" -| clipPathUnits="" -| contentScriptType="" -| contentStyleType="" -| diffuseConstant="" -| edgeMode="" -| externalResourcesRequired="" -| filterRes="" -| filterUnits="" -| glyphRef="" -| gradientTransform="" -| gradientUnits="" -| kernelMatrix="" -| kernelUnitLength="" -| keyPoints="" -| keySplines="" -| keyTimes="" -| lengthAdjust="" -| limitingConeAngle="" -| markerHeight="" -| markerUnits="" -| markerWidth="" -| maskContentUnits="" -| maskUnits="" -| numOctaves="" -| pathLength="" -| patternContentUnits="" -| patternTransform="" -| patternUnits="" -| pointsAtX="" -| pointsAtY="" -| pointsAtZ="" -| preserveAlpha="" -| preserveAspectRatio="" -| primitiveUnits="" -| refX="" -| refY="" -| repeatCount="" -| repeatDur="" -| requiredExtensions="" -| requiredFeatures="" -| specularConstant="" -| specularExponent="" -| spreadMethod="" -| startOffset="" -| stdDeviation="" -| stitchTiles="" -| surfaceScale="" -| systemLanguage="" -| tableValues="" -| targetX="" -| targetY="" -| textLength="" -| viewBox="" -| viewTarget="" -| xChannelSelector="" -| yChannelSelector="" -| zoomAndPan="" - -#data - -#errors -#document -| -| -| -| -| -| attributename="" -| attributetype="" -| basefrequency="" -| baseprofile="" -| calcmode="" -| clippathunits="" -| contentscripttype="" -| contentstyletype="" -| diffuseconstant="" -| edgemode="" -| externalresourcesrequired="" -| filterres="" -| filterunits="" -| glyphref="" -| gradienttransform="" -| gradientunits="" -| kernelmatrix="" -| kernelunitlength="" -| keypoints="" -| keysplines="" -| keytimes="" -| lengthadjust="" -| limitingconeangle="" -| markerheight="" -| markerunits="" -| markerwidth="" -| maskcontentunits="" -| maskunits="" -| numoctaves="" -| pathlength="" -| patterncontentunits="" -| patterntransform="" -| patternunits="" -| pointsatx="" -| pointsaty="" -| pointsatz="" -| preservealpha="" -| preserveaspectratio="" -| primitiveunits="" -| refx="" -| refy="" -| repeatcount="" -| repeatdur="" -| requiredextensions="" -| requiredfeatures="" -| specularconstant="" -| specularexponent="" -| spreadmethod="" -| startoffset="" -| stddeviation="" -| stitchtiles="" -| surfacescale="" -| systemlanguage="" -| tablevalues="" -| targetx="" -| targety="" -| textlength="" -| viewbox="" -| viewtarget="" -| xchannelselector="" -| ychannelselector="" -| zoomandpan="" - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat deleted file mode 100644 index 63107d277b6..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests12.dat +++ /dev/null @@ -1,62 +0,0 @@ -#data -

foobazeggs

spam

quuxbar -#errors -#document -| -| -| -| -|

-| "foo" -| -| -| -| "baz" -| -| -| -| -| "eggs" -| -| -|

-| "spam" -| -| -| -|
-| -| -| "quux" -| "bar" - -#data -foobazeggs

spam
quuxbar -#errors -#document -| -| -| -| -| "foo" -| -| -| -| "baz" -| -| -| -| -| "eggs" -| -| -|

-| "spam" -| -| -| -|
-| -| -| "quux" -| "bar" diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat deleted file mode 100644 index b8713f88582..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests14.dat +++ /dev/null @@ -1,74 +0,0 @@ -#data - -#errors -#document -| -| -| -| -| - -#data - -#errors -#document -| -| -| -| -| -| - -#data - -#errors -15: Unexpected start tag html -#document -| -| -| abc:def="gh" -| -| -| - -#data - -#errors -15: Unexpected start tag html -#document -| -| -| xml:lang="bar" -| -| - -#data - -#errors -#document -| -| -| 123="456" -| -| - -#data - -#errors -#document -| -| -| 123="456" -| 789="012" -| -| - -#data - -#errors -#document -| -| -| -| -| 789="012" diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat deleted file mode 100644 index 6ce1c0d1663..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests15.dat +++ /dev/null @@ -1,208 +0,0 @@ -#data -

X -#errors -Line: 1 Col: 31 Unexpected end tag (p). Ignored. -Line: 1 Col: 36 Expected closing tag. Unexpected end of file. -#document -| -| -| -| -|

-| -| -| -| -| -| -| " " -|

-| "X" - -#data -

-

X -#errors -Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. -Line: 1 Col: 16 Unexpected end tag (p). Ignored. -Line: 2 Col: 4 Expected closing tag. Unexpected end of file. -#document -| -| -| -|

-| -| -| -| -| -| -| " -" -|

-| "X" - -#data - -#errors -Line: 1 Col: 22 Unexpected end tag (html) after the (implied) root element. -#document -| -| -| -| -| " " - -#data - -#errors -Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element. -#document -| -| -| -| -| - -#data - -#errors -Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end tag (html) after the (implied) root element. -#document -| -| -| -| - -#data -X -#errors -Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element. -#document -| -| -| -| -| -| "X" - -#data -<!doctype html><table> X<meta></table> -#errors -Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode. -Line: 1 Col: 30 Unexpected start tag (meta) in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " X" -| <meta> -| <table> - -#data -<!doctype html><table> x</table> -#errors -Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " x" -| <table> - -#data -<!doctype html><table> x </table> -#errors -Line: 1 Col: 25 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " x " -| <table> - -#data -<!doctype html><table><tr> x</table> -#errors -Line: 1 Col: 28 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " x" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table>X<style> <tr>x </style> </table> -#errors -Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "X" -| <table> -| <style> -| " <tr>x " -| " " - -#data -<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div> -#errors -Line: 1 Col: 30 Unexpected start tag (a) in table context caused voodoo mode. -Line: 1 Col: 37 Unexpected end tag (a) in table context caused voodoo mode. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> -| <a> -| "foo" -| <table> -| " " -| <tbody> -| <tr> -| <td> -| "bar" -| " " - -#data -<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes> -#errors -6: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. -13: Stray start tag “frame”. -21: Stray end tag “frame”. -29: Stray end tag “frame”. -39: “frameset” start tag after “body” already open. -105: End of file seen inside an [R]CDATA element. -105: End of file seen and there were open elements. -XXX: These errors are wrong, please fix me! -#document -| <html> -| <head> -| <frameset> -| <frame> -| <frameset> -| <frame> -| <noframes> -| "</frameset><noframes>" - -#data -<!DOCTYPE html><object></html> -#errors -1: Expected closing tag. Unexpected end of file -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <object> diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat deleted file mode 100644 index c8ef66f0e6e..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests16.dat +++ /dev/null @@ -1,2299 +0,0 @@ -#data -<!doctype html><script> -#errors -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| <body> - -#data -<!doctype html><script>a -#errors -Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "a" -| <body> - -#data -<!doctype html><script>< -#errors -Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<" -| <body> - -#data -<!doctype html><script></ -#errors -Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</" -| <body> - -#data -<!doctype html><script></S -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</S" -| <body> - -#data -<!doctype html><script></SC -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SC" -| <body> - -#data -<!doctype html><script></SCR -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCR" -| <body> - -#data -<!doctype html><script></SCRI -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCRI" -| <body> - -#data -<!doctype html><script></SCRIP -#errors -Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCRIP" -| <body> - -#data -<!doctype html><script></SCRIPT -#errors -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</SCRIPT" -| <body> - -#data -<!doctype html><script></SCRIPT -#errors -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| <body> - -#data -<!doctype html><script></s -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</s" -| <body> - -#data -<!doctype html><script></sc -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</sc" -| <body> - -#data -<!doctype html><script></scr -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</scr" -| <body> - -#data -<!doctype html><script></scri -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</scri" -| <body> - -#data -<!doctype html><script></scrip -#errors -Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</scrip" -| <body> - -#data -<!doctype html><script></script -#errors -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "</script" -| <body> - -#data -<!doctype html><script></script -#errors -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| <body> - -#data -<!doctype html><script><! -#errors -Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!" -| <body> - -#data -<!doctype html><script><!a -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!a" -| <body> - -#data -<!doctype html><script><!- -#errors -Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!-" -| <body> - -#data -<!doctype html><script><!-a -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!-a" -| <body> - -#data -<!doctype html><script><!-- -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<!doctype html><script><!--a -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--a" -| <body> - -#data -<!doctype html><script><!--< -#errors -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<" -| <body> - -#data -<!doctype html><script><!--<a -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<a" -| <body> - -#data -<!doctype html><script><!--</ -#errors -Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--</" -| <body> - -#data -<!doctype html><script><!--</script -#errors -Line: 1 Col: 35 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--</script" -| <body> - -#data -<!doctype html><script><!--</script -#errors -Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<!doctype html><script><!--<s -#errors -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<s" -| <body> - -#data -<!doctype html><script><!--<script -#errors -Line: 1 Col: 34 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script" -| <body> - -#data -<!doctype html><script><!--<script -#errors -Line: 1 Col: 35 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script " -| <body> - -#data -<!doctype html><script><!--<script < -#errors -Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script <" -| <body> - -#data -<!doctype html><script><!--<script <a -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script <a" -| <body> - -#data -<!doctype html><script><!--<script </ -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </" -| <body> - -#data -<!doctype html><script><!--<script </s -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </s" -| <body> - -#data -<!doctype html><script><!--<script </script -#errors -Line: 1 Col: 43 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script" -| <body> - -#data -<!doctype html><script><!--<script </scripta -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </scripta" -| <body> - -#data -<!doctype html><script><!--<script </script -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script </script> -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script>" -| <body> - -#data -<!doctype html><script><!--<script </script/ -#errors -Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script/" -| <body> - -#data -<!doctype html><script><!--<script </script < -#errors -Line: 1 Col: 45 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script <" -| <body> - -#data -<!doctype html><script><!--<script </script <a -#errors -Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script <a" -| <body> - -#data -<!doctype html><script><!--<script </script </ -#errors -Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script </" -| <body> - -#data -<!doctype html><script><!--<script </script </script -#errors -Line: 1 Col: 52 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script </script" -| <body> - -#data -<!doctype html><script><!--<script </script </script -#errors -Line: 1 Col: 53 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script </script </script/ -#errors -Line: 1 Col: 53 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script </script </script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<!doctype html><script><!--<script - -#errors -Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -" -| <body> - -#data -<!doctype html><script><!--<script -a -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -a" -| <body> - -#data -<!doctype html><script><!--<script -< -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -<" -| <body> - -#data -<!doctype html><script><!--<script -- -#errors -Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --" -| <body> - -#data -<!doctype html><script><!--<script --a -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --a" -| <body> - -#data -<!doctype html><script><!--<script --< -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --<" -| <body> - -#data -<!doctype html><script><!--<script --> -#errors -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script -->< -#errors -Line: 1 Col: 39 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --><" -| <body> - -#data -<!doctype html><script><!--<script --></ -#errors -Line: 1 Col: 40 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --></" -| <body> - -#data -<!doctype html><script><!--<script --></script -#errors -Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script --></script" -| <body> - -#data -<!doctype html><script><!--<script --></script -#errors -Line: 1 Col: 47 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script --></script/ -#errors -Line: 1 Col: 47 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script --></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<!doctype html><script><!--<script><\/script>--></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script><\/script>-->" -| <body> - -#data -<!doctype html><script><!--<script></scr'+'ipt>--></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt>-->" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>--><!--</script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>--><!--" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>-- ></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>-- >" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>- -></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- ->" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>- - ></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- - >" -| <body> - -#data -<!doctype html><script><!--<script></script><script></script>-></script> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>->" -| <body> - -#data -<!doctype html><script><!--<script>--!></script>X -#errors -Line: 1 Col: 49 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script>--!></script>X" -| <body> - -#data -<!doctype html><script><!--<scr'+'ipt></script>--></script> -#errors -Line: 1 Col: 59 Unexpected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<scr'+'ipt>" -| <body> -| "-->" - -#data -<!doctype html><script><!--<script></scr'+'ipt></script>X -#errors -Line: 1 Col: 57 Unexpected end of file. Expected end tag (script). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt></script>X" -| <body> - -#data -<!doctype html><style><!--<style></style>--></style> -#errors -Line: 1 Col: 52 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--<style>" -| <body> -| "-->" - -#data -<!doctype html><style><!--</style>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--" -| <body> -| "X" - -#data -<!doctype html><style><!--...</style>...--></style> -#errors -Line: 1 Col: 51 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--..." -| <body> -| "...-->" - -#data -<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>" -| <body> -| "X" - -#data -<!doctype html><style><!--...<style><!--...--!></style>--></style> -#errors -Line: 1 Col: 66 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--...<style><!--...--!>" -| <body> -| "-->" - -#data -<!doctype html><style><!--...</style><!-- --><style>@import ...</style> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "<!--..." -| <!-- --> -| <style> -| "@import ..." -| <body> - -#data -<!doctype html><style>...<style><!--...</style><!-- --></style> -#errors -Line: 1 Col: 63 Unexpected end tag (style). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "...<style><!--..." -| <!-- --> -| <body> - -#data -<!doctype html><style>...<!--[if IE]><style>...</style>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <style> -| "...<!--[if IE]><style>..." -| <body> -| "X" - -#data -<!doctype html><title><!--<title>--> -#errors -Line: 1 Col: 52 Unexpected end tag (title). -#document -| -| -| -| -| "<!--<title>" -| <body> -| "-->" - -#data -<!doctype html><title></title> -#errors -#document -| -| -| -| -| "" -| - -#data -foo/title><link></head><body>X -#errors -Line: 1 Col: 52 Unexpected end of file. Expected end tag (title). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <title> -| "foo/title><link></head><body>X" -| <body> - -#data -<!doctype html><noscript><!--<noscript></noscript>--></noscript> -#errors -Line: 1 Col: 64 Unexpected end tag (noscript). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noscript> -| "<!--<noscript>" -| <body> -| "-->" - -#data -<!doctype html><noscript><!--</noscript>X<noscript>--></noscript> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noscript> -| "<!--" -| <body> -| "X" -| <noscript> -| "-->" - -#data -<!doctype html><noscript><iframe></noscript>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noscript> -| "<iframe>" -| <body> -| "X" - -#data -<!doctype html><noframes><!--<noframes></noframes>--></noframes> -#errors -Line: 1 Col: 64 Unexpected end tag (noframes). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noframes> -| "<!--<noframes>" -| <body> -| "-->" - -#data -<!doctype html><noframes><body><script><!--...</script></body></noframes></html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <noframes> -| "<body><script><!--...</script></body>" -| <body> - -#data -<!doctype html><textarea><!--<textarea></textarea>--></textarea> -#errors -Line: 1 Col: 64 Unexpected end tag (textarea). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "<!--<textarea>" -| "-->" - -#data -<!doctype html><textarea></textarea></textarea> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "</textarea>" - -#data -<!doctype html><textarea><</textarea> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "<" - -#data -<!doctype html><textarea>a<b</textarea> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> -| "a<b" - -#data -<!doctype html><iframe><!--<iframe></iframe>--></iframe> -#errors -Line: 1 Col: 56 Unexpected end tag (iframe). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <iframe> -| "<!--<iframe>" -| "-->" - -#data -<!doctype html><iframe>...<!--X->...<!--/X->...</iframe> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <iframe> -| "...<!--X->...<!--/X->..." - -#data -<!doctype html><xmp><!--<xmp></xmp>--></xmp> -#errors -Line: 1 Col: 44 Unexpected end tag (xmp). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <xmp> -| "<!--<xmp>" -| "-->" - -#data -<!doctype html><noembed><!--<noembed></noembed>--></noembed> -#errors -Line: 1 Col: 60 Unexpected end tag (noembed). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <noembed> -| "<!--<noembed>" -| "-->" - -#data -<script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 8 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| <body> - -#data -<script>a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 9 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "a" -| <body> - -#data -<script>< -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 9 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<" -| <body> - -#data -<script></ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 10 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</" -| <body> - -#data -<script></S -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</S" -| <body> - -#data -<script></SC -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SC" -| <body> - -#data -<script></SCR -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCR" -| <body> - -#data -<script></SCRI -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCRI" -| <body> - -#data -<script></SCRIP -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 15 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCRIP" -| <body> - -#data -<script></SCRIPT -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 16 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</SCRIPT" -| <body> - -#data -<script></SCRIPT -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 17 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| <body> - -#data -<script></s -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</s" -| <body> - -#data -<script></sc -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</sc" -| <body> - -#data -<script></scr -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</scr" -| <body> - -#data -<script></scri -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</scri" -| <body> - -#data -<script></scrip -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 15 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</scrip" -| <body> - -#data -<script></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 16 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</script" -| <body> - -#data -<script></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 17 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| <body> - -#data -<script><! -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 10 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!" -| <body> - -#data -<script><!a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!a" -| <body> - -#data -<script><!- -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!-" -| <body> - -#data -<script><!-a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!-a" -| <body> - -#data -<script><!-- -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<script><!--a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--a" -| <body> - -#data -<script><!--< -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<" -| <body> - -#data -<script><!--<a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<a" -| <body> - -#data -<script><!--</ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--</" -| <body> - -#data -<script><!--</script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 20 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--</script" -| <body> - -#data -<script><!--</script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--" -| <body> - -#data -<script><!--<s -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<s" -| <body> - -#data -<script><!--<script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 19 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script" -| <body> - -#data -<script><!--<script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 20 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script " -| <body> - -#data -<script><!--<script < -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script <" -| <body> - -#data -<script><!--<script <a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script <a" -| <body> - -#data -<script><!--<script </ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </" -| <body> - -#data -<script><!--<script </s -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </s" -| <body> - -#data -<script><!--<script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script" -| <body> - -#data -<script><!--<script </scripta -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </scripta" -| <body> - -#data -<script><!--<script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script </script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script>" -| <body> - -#data -<script><!--<script </script/ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script/" -| <body> - -#data -<script><!--<script </script < -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script <" -| <body> - -#data -<script><!--<script </script <a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script <a" -| <body> - -#data -<script><!--<script </script </ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script </" -| <body> - -#data -<script><!--<script </script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script </script" -| <body> - -#data -<script><!--<script </script </script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script </script </script/ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script </script </script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script </script " -| <body> - -#data -<script><!--<script - -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -" -| <body> - -#data -<script><!--<script -a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -a" -| <body> - -#data -<script><!--<script -- -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --" -| <body> - -#data -<script><!--<script --a -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --a" -| <body> - -#data -<script><!--<script --> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script -->< -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --><" -| <body> - -#data -<script><!--<script --></ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --></" -| <body> - -#data -<script><!--<script --></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script --></script" -| <body> - -#data -<script><!--<script --></script -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script --></script/ -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script --></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script -->" -| <body> - -#data -<script><!--<script><\/script>--></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script><\/script>-->" -| <body> - -#data -<script><!--<script></scr'+'ipt>--></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt>-->" -| <body> - -#data -<script><!--<script></script><script></script></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>" -| <body> - -#data -<script><!--<script></script><script></script>--><!--</script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>--><!--" -| <body> - -#data -<script><!--<script></script><script></script>-- ></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>-- >" -| <body> - -#data -<script><!--<script></script><script></script>- -></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- ->" -| <body> - -#data -<script><!--<script></script><script></script>- - ></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>- - >" -| <body> - -#data -<script><!--<script></script><script></script>-></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -#document -| <html> -| <head> -| <script> -| "<!--<script></script><script></script>->" -| <body> - -#data -<script><!--<script>--!></script>X -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 34 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script>--!></script>X" -| <body> - -#data -<script><!--<scr'+'ipt></script>--></script> -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 44 Unexpected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<scr'+'ipt>" -| <body> -| "-->" - -#data -<script><!--<script></scr'+'ipt></script>X -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 42 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "<!--<script></scr'+'ipt></script>X" -| <body> - -#data -<style><!--<style></style>--></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 37 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "<!--<style>" -| <body> -| "-->" - -#data -<style><!--</style>X -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "<!--" -| <body> -| "X" - -#data -<style><!--...</style>...--></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 36 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "<!--..." -| <body> -| "...-->" - -#data -<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>" -| <body> -| "X" - -#data -<style><!--...<style><!--...--!></style>--></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 51 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "<!--...<style><!--...--!>" -| <body> -| "-->" - -#data -<style><!--...</style><!-- --><style>@import ...</style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "<!--..." -| <!-- --> -| <style> -| "@import ..." -| <body> - -#data -<style>...<style><!--...</style><!-- --></style> -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 48 Unexpected end tag (style). -#document -| <html> -| <head> -| <style> -| "...<style><!--..." -| <!-- --> -| <body> - -#data -<style>...<!--[if IE]><style>...</style>X -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| <html> -| <head> -| <style> -| "...<!--[if IE]><style>..." -| <body> -| "X" - -#data -<title><!--<title>--> -#errors -Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. -Line: 1 Col: 37 Unexpected end tag (title). -#document -| -| -| -| "<!--<title>" -| <body> -| "-->" - -#data -<title></title> -#errors -Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. -#document -| -| -| -| "" -| - -#data -foo/title><link></head><body>X -#errors -Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. -Line: 1 Col: 37 Unexpected end of file. Expected end tag (title). -#document -| <html> -| <head> -| <title> -| "foo/title><link></head><body>X" -| <body> - -#data -<noscript><!--<noscript></noscript>--></noscript> -#errors -Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. -Line: 1 Col: 49 Unexpected end tag (noscript). -#document -| <html> -| <head> -| <noscript> -| "<!--<noscript>" -| <body> -| "-->" - -#data -<noscript><!--</noscript>X<noscript>--></noscript> -#errors -Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. -#document -| <html> -| <head> -| <noscript> -| "<!--" -| <body> -| "X" -| <noscript> -| "-->" - -#data -<noscript><iframe></noscript>X -#errors -Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. -#document -| <html> -| <head> -| <noscript> -| "<iframe>" -| <body> -| "X" - -#data -<noframes><!--<noframes></noframes>--></noframes> -#errors -Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE. -Line: 1 Col: 49 Unexpected end tag (noframes). -#document -| <html> -| <head> -| <noframes> -| "<!--<noframes>" -| <body> -| "-->" - -#data -<noframes><body><script><!--...</script></body></noframes></html> -#errors -Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE. -#document -| <html> -| <head> -| <noframes> -| "<body><script><!--...</script></body>" -| <body> - -#data -<textarea><!--<textarea></textarea>--></textarea> -#errors -Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. -Line: 1 Col: 49 Unexpected end tag (textarea). -#document -| <html> -| <head> -| <body> -| <textarea> -| "<!--<textarea>" -| "-->" - -#data -<textarea></textarea></textarea> -#errors -Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| <textarea> -| "</textarea>" - -#data -<iframe><!--<iframe></iframe>--></iframe> -#errors -Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. -Line: 1 Col: 41 Unexpected end tag (iframe). -#document -| <html> -| <head> -| <body> -| <iframe> -| "<!--<iframe>" -| "-->" - -#data -<iframe>...<!--X->...<!--/X->...</iframe> -#errors -Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| <iframe> -| "...<!--X->...<!--/X->..." - -#data -<xmp><!--<xmp></xmp>--></xmp> -#errors -Line: 1 Col: 5 Unexpected start tag (xmp). Expected DOCTYPE. -Line: 1 Col: 29 Unexpected end tag (xmp). -#document -| <html> -| <head> -| <body> -| <xmp> -| "<!--<xmp>" -| "-->" - -#data -<noembed><!--<noembed></noembed>--></noembed> -#errors -Line: 1 Col: 9 Unexpected start tag (noembed). Expected DOCTYPE. -Line: 1 Col: 45 Unexpected end tag (noembed). -#document -| <html> -| <head> -| <body> -| <noembed> -| "<!--<noembed>" -| "-->" - -#data -<!doctype html><table> - -#errors -Line 2 Col 0 Unexpected end of file. Expected table content. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| " -" - -#data -<!doctype html><table><td><span><font></span><span> -#errors -Line 1 Col 26 Unexpected table cell start tag (td) in the table body phase. -Line 1 Col 45 Unexpected end tag (span). -Line 1 Col 51 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <span> -| <font> -| <font> -| <span> - -#data -<!doctype html><form><table></form><form></table></form> -#errors -35: Stray end tag “form”. -41: Start tag “form” seen in “table”. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <table> -| <form> diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat deleted file mode 100644 index 7b555f888de..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests17.dat +++ /dev/null @@ -1,153 +0,0 @@ -#data -<!doctype html><table><tbody><select><tr> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><tr><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <table> -| <tbody> -| <tr> -| <td> - -#data -<!doctype html><table><tr><td><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <select> -| <td> - -#data -<!doctype html><table><tr><th><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <th> -| <select> -| <td> - -#data -<!doctype html><table><caption><select><tr> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| <select> -| <tbody> -| <tr> - -#data -<!doctype html><select><tr> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><th> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><tbody> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><thead> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><tfoot> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><select><caption> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><table><tr></table>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| "a" diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat deleted file mode 100644 index 680e1f068a6..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests18.dat +++ /dev/null @@ -1,269 +0,0 @@ -#data -<!doctype html><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" - -#data -<!doctype html><table><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> - -#data -<!doctype html><table><tbody><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> -| <tbody> - -#data -<!doctype html><table><tbody><tr><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><tbody><tr><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><td><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <plaintext> -| "</plaintext>" - -#data -<!doctype html><table><caption><plaintext></plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| <plaintext> -| "</plaintext>" - -#data -<!doctype html><table><tr><style></script></style>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "abc" -| <table> -| <tbody> -| <tr> -| <style> -| "</script>" - -#data -<!doctype html><table><tr><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "abc" -| <table> -| <tbody> -| <tr> -| <script> -| "</style>" - -#data -<!doctype html><table><caption><style></script></style>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| <style> -| "</script>" -| "abc" - -#data -<!doctype html><table><td><style></script></style>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <style> -| "</script>" -| "abc" - -#data -<!doctype html><select><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <script> -| "</style>" -| "abc" - -#data -<!doctype html><table><select><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <script> -| "</style>" -| "abc" -| <table> - -#data -<!doctype html><table><tr><select><script></style></script>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <script> -| "</style>" -| "abc" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><frameset></frameset><noframes>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" - -#data -<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" -| <!-- abc --> - -#data -<!doctype html><frameset></frameset></html><noframes>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" - -#data -<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <noframes> -| "abc" -| <!-- abc --> - -#data -<!doctype html><table><tr></tbody><tfoot> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <tfoot> - -#data -<!doctype html><table><td><svg></svg>abc<td> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <svg svg> -| "abc" -| <td> diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat deleted file mode 100644 index 0d62f5a5b02..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests19.dat +++ /dev/null @@ -1,1237 +0,0 @@ -#data -<!doctype html><math><mn DefinitionUrl="foo"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <math math> -| <math mn> -| definitionURL="foo" - -#data -<!doctype html><html></p><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <!-- foo --> -| <head> -| <body> - -#data -<!doctype html><head></head></p><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <!-- foo --> -| <body> - -#data -<!doctype html><body><p><pre> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <pre> - -#data -<!doctype html><body><p><listing> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <listing> - -#data -<!doctype html><p><plaintext> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <plaintext> - -#data -<!doctype html><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <h1> - -#data -<!doctype html><form><isindex> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> - -#data -<!doctype html><isindex action="POST"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| action="POST" -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| <hr> - -#data -<!doctype html><isindex prompt="this is isindex"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "this is isindex" -| <input> -| name="isindex" -| <hr> - -#data -<!doctype html><isindex type="hidden"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| type="hidden" -| <hr> - -#data -<!doctype html><isindex name="foo"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| <hr> - -#data -<!doctype html><ruby><p><rp> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <p> -| <rp> - -#data -<!doctype html><ruby><div><span><rp> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <span> -| <rp> - -#data -<!doctype html><ruby><div><p><rp> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <p> -| <rp> - -#data -<!doctype html><ruby><p><rt> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <p> -| <rt> - -#data -<!doctype html><ruby><div><span><rt> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <span> -| <rt> - -#data -<!doctype html><ruby><div><p><rt> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <ruby> -| <div> -| <p> -| <rt> - -#data -<!doctype html><math/><foo> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <math math> -| <foo> - -#data -<!doctype html><svg/><foo> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <svg svg> -| <foo> - -#data -<!doctype html><div></body><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> -| <!-- foo --> - -#data -<!doctype html><h1><div><h3><span></h1>foo -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <h1> -| <div> -| <h3> -| <span> -| "foo" - -#data -<!doctype html><p></h3>foo -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| "foo" - -#data -<!doctype html><h3><li>abc</h2>foo -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <h3> -| <li> -| "abc" -| "foo" - -#data -<!doctype html><table>abc<!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "abc" -| <table> -| <!-- foo --> - -#data -<!doctype html><table> <!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| " " -| <!-- foo --> - -#data -<!doctype html><table> b <!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| " b " -| <table> -| <!-- foo --> - -#data -<!doctype html><select><option><option> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> -| <option> - -#data -<!doctype html><select><option></optgroup> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> - -#data -<!doctype html><select><option></optgroup> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> - -#data -<!doctype html><p><math><mi><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mi> -| <p> -| <h1> - -#data -<!doctype html><p><math><mo><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mo> -| <p> -| <h1> - -#data -<!doctype html><p><math><mn><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mn> -| <p> -| <h1> - -#data -<!doctype html><p><math><ms><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math ms> -| <p> -| <h1> - -#data -<!doctype html><p><math><mtext><p><h1> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mtext> -| <p> -| <h1> - -#data -<!doctype html><frameset></noframes> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><html c=d><body></html><html a=b> -#errors -#document -| <!DOCTYPE html> -| <html> -| a="b" -| c="d" -| <head> -| <body> - -#data -<!doctype html><html c=d><frameset></frameset></html><html a=b> -#errors -#document -| <!DOCTYPE html> -| <html> -| a="b" -| c="d" -| <head> -| <frameset> - -#data -<!doctype html><html><frameset></frameset></html><!--foo--> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <!-- foo --> - -#data -<!doctype html><html><frameset></frameset></html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| " " - -#data -<!doctype html><html><frameset></frameset></html>abc -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><html><frameset></frameset></html><p> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><html><frameset></frameset></html></p> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<html><frameset></frameset></html><!doctype html> -#errors -#document -| <html> -| <head> -| <frameset> - -#data -<!doctype html><body><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> - -#data -<!doctype html><p><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><p>a<frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| "a" - -#data -<!doctype html><p> <frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><pre><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <pre> - -#data -<!doctype html><listing><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <listing> - -#data -<!doctype html><li><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <li> - -#data -<!doctype html><dd><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <dd> - -#data -<!doctype html><dt><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <dt> - -#data -<!doctype html><button><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <button> - -#data -<!doctype html><applet><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <applet> - -#data -<!doctype html><marquee><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <marquee> - -#data -<!doctype html><object><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <object> - -#data -<!doctype html><table><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> - -#data -<!doctype html><area><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <area> - -#data -<!doctype html><basefont><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <basefont> -| <frameset> - -#data -<!doctype html><bgsound><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <bgsound> -| <frameset> - -#data -<!doctype html><br><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <br> - -#data -<!doctype html><embed><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <embed> - -#data -<!doctype html><img><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <img> - -#data -<!doctype html><input><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <input> - -#data -<!doctype html><keygen><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <keygen> - -#data -<!doctype html><wbr><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <wbr> - -#data -<!doctype html><hr><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <hr> - -#data -<!doctype html><textarea></textarea><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <textarea> - -#data -<!doctype html><xmp></xmp><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <xmp> - -#data -<!doctype html><iframe></iframe><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <iframe> - -#data -<!doctype html><select></select><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> - -#data -<!doctype html><svg></svg><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><math></math><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><svg><foreignObject><div> <frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<!doctype html><svg>a</svg><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <svg svg> -| "a" - -#data -<!doctype html><svg> </svg><frameset><frame> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> -| <frame> - -#data -<html>aaa<frameset></frameset> -#errors -#document -| <html> -| <head> -| <body> -| "aaa" - -#data -<html> a <frameset></frameset> -#errors -#document -| <html> -| <head> -| <body> -| "a " - -#data -<!doctype html><div><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!doctype html><div><body><frameset> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> - -#data -<!doctype html><p><math></p>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| "a" - -#data -<!doctype html><p><math><mn><span></p>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <math math> -| <math mn> -| <span> -| <p> -| "a" - -#data -<!doctype html><math></html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <math math> - -#data -<!doctype html><meta charset="ascii"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <meta> -| charset="ascii" -| <body> - -#data -<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <meta> -| content="text/html;charset=ascii" -| http-equiv="content-type" -| <body> - -#data -<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8"> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --> -| <meta> -| charset="utf8" -| <body> - -#data -<!doctype html><html a=b><head></head><html c=d> -#errors -#document -| <!DOCTYPE html> -| <html> -| a="b" -| c="d" -| <head> -| <body> - -#data -<!doctype html><image/> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <img> - -#data -<!doctype html>a<i>b<table>c<b>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "a" -| <i> -| "bc" -| <b> -| "de" -| "f" -| <table> - -#data -<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <b> -| <i> -| "c" -| <a> -| "d" -| <a> -| "e" -| <a> -| "f" -| <table> - -#data -<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <b> -| <i> -| "c" -| <a> -| "d" -| <a> -| "e" -| <a> -| "f" - -#data -<!doctype html><table><i>a<b>b<div>c</i> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <i> -| "c" -| <table> - -#data -<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <b> -| "b" -| <b> -| <div> -| <b> -| <i> -| "c" -| <a> -| "d" -| <a> -| "e" -| <a> -| "f" -| <table> - -#data -<!doctype html><table><i>a<div>b<tr>c<b>d</i>e -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <i> -| "a" -| <div> -| "b" -| <i> -| "c" -| <b> -| "d" -| <b> -| "e" -| <table> -| <tbody> -| <tr> - -#data -<!doctype html><table><td><table><i>a<div>b<b>c</i>d -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| <i> -| "a" -| <div> -| <i> -| "b" -| <b> -| "c" -| <b> -| "d" -| <table> - -#data -<!doctype html><body><bgsound> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <bgsound> - -#data -<!doctype html><body><basefont> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <basefont> - -#data -<!doctype html><a><b></a><basefont> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <a> -| <b> -| <basefont> - -#data -<!doctype html><a><b></a><bgsound> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <a> -| <b> -| <bgsound> - -#data -<!doctype html><figcaption><article></figcaption>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <figcaption> -| <article> -| "a" - -#data -<!doctype html><summary><article></summary>a -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <summary> -| <article> -| "a" - -#data -<!doctype html><p><a><plaintext>b -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <a> -| <plaintext> -| <a> -| "b" - -#data -<!DOCTYPE html><div>a<a></div>b<p>c</p>d -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <div> -| "a" -| <a> -| <a> -| "b" -| <p> -| "c" -| "d" diff --git a/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat b/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat deleted file mode 100644 index 60d85922162..00000000000 --- a/vendor/golang.org/x/net/html/testdata/webkit/tests2.dat +++ /dev/null @@ -1,763 +0,0 @@ -#data -<!DOCTYPE html>Test -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "Test" - -#data -<textarea>test</div>test -#errors -Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. -Line: 1 Col: 24 Expected closing tag. Unexpected end of file. -#document -| <html> -| <head> -| <body> -| <textarea> -| "test</div>test" - -#data -<table><td> -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase. -Line: 1 Col: 11 Expected closing tag. Unexpected end of file. -#document -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> - -#data -<table><td>test</tbody></table> -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase. -#document -| <html> -| <head> -| <body> -| <table> -| <tbody> -| <tr> -| <td> -| "test" - -#data -<frame>test -#errors -Line: 1 Col: 7 Unexpected start tag (frame). Expected DOCTYPE. -Line: 1 Col: 7 Unexpected start tag frame. Ignored. -#document -| <html> -| <head> -| <body> -| "test" - -#data -<!DOCTYPE html><frameset>test -#errors -Line: 1 Col: 29 Unepxected characters in the frameset phase. Characters ignored. -Line: 1 Col: 29 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!DOCTYPE html><frameset><!DOCTYPE html> -#errors -Line: 1 Col: 40 Unexpected DOCTYPE. Ignored. -Line: 1 Col: 40 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <frameset> - -#data -<!DOCTYPE html><font><p><b>test</font> -#errors -Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. -Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <font> -| <p> -| <font> -| <b> -| "test" - -#data -<!DOCTYPE html><dt><div><dd> -#errors -Line: 1 Col: 28 Missing end tag (div, dt). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <dt> -| <div> -| <dd> - -#data -<script></x -#errors -Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. -Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). -#document -| <html> -| <head> -| <script> -| "</x" -| <body> - -#data -<table><plaintext><td> -#errors -Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. -Line: 1 Col: 18 Unexpected start tag (plaintext) in table context caused voodoo mode. -Line: 1 Col: 22 Unexpected end of file. Expected table content. -#document -| <html> -| <head> -| <body> -| <plaintext> -| "<td>" -| <table> - -#data -<plaintext></plaintext> -#errors -Line: 1 Col: 11 Unexpected start tag (plaintext). Expected DOCTYPE. -Line: 1 Col: 23 Expected closing tag. Unexpected end of file. -#document -| <html> -| <head> -| <body> -| <plaintext> -| "</plaintext>" - -#data -<!DOCTYPE html><table><tr>TEST -#errors -Line: 1 Col: 30 Unexpected non-space characters in table context caused voodoo mode. -Line: 1 Col: 30 Unexpected end of file. Expected table content. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "TEST" -| <table> -| <tbody> -| <tr> - -#data -<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4> -#errors -Line: 1 Col: 37 Unexpected start tag (body). -Line: 1 Col: 53 Unexpected start tag (body). -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| t1="1" -| t2="2" -| t3="3" -| t4="4" - -#data -</b test -#errors -Line: 1 Col: 8 Unexpected end of file in attribute name. -Line: 1 Col: 8 End tag contains unexpected attributes. -Line: 1 Col: 8 Unexpected end tag (b). Expected DOCTYPE. -Line: 1 Col: 8 Unexpected end tag (b) after the (implied) root element. -#document -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html></b test<b &=&>X -#errors -Line: 1 Col: 32 Named entity didn't end with ';'. -Line: 1 Col: 33 End tag contains unexpected attributes. -Line: 1 Col: 33 Unexpected end tag (b) after the (implied) root element. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "X" - -#data -<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -Line: 1 Col: 54 Unexpected end of file in the tag name. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <script> -| type="text/x-foobar;baz" -| "X</SCRipt" -| <body> - -#data -& -#errors -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&" - -#data -&# -#errors -Line: 1 Col: 1 Numeric entity expected. Got end of file instead. -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&#" - -#data -&#X -#errors -Line: 1 Col: 3 Numeric entity expected but none found. -Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&#X" - -#data -&#x -#errors -Line: 1 Col: 3 Numeric entity expected but none found. -Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&#x" - -#data -- -#errors -Line: 1 Col: 4 Numeric entity didn't end with ';'. -Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "-" - -#data -&x-test -#errors -Line: 1 Col: 1 Named entity expected. Got none. -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&x-test" - -#data -<!doctypehtml><p><li> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <li> - -#data -<!doctypehtml><p><dt> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <dt> - -#data -<!doctypehtml><p><dd> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <dd> - -#data -<!doctypehtml><p><form> -#errors -Line: 1 Col: 9 No space after literal string 'DOCTYPE'. -Line: 1 Col: 23 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| <form> - -#data -<!DOCTYPE html><p></P>X -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <p> -| "X" - -#data -& -#errors -Line: 1 Col: 4 Named entity didn't end with ';'. -Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&" - -#data -&AMp; -#errors -Line: 1 Col: 1 Named entity expected. Got none. -Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "&AMp;" - -#data -<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY> -#errors -Line: 1 Col: 110 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly> - -#data -<!DOCTYPE html>X</body>X -#errors -Line: 1 Col: 24 Unexpected non-space characters in the after body phase. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| "XX" - -#data -<!DOCTYPE html><!-- X -#errors -Line: 1 Col: 21 Unexpected end of file in comment. -#document -| <!DOCTYPE html> -| <!-- X --> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><table><caption>test TEST</caption><td>test -#errors -Line: 1 Col: 54 Unexpected table cell start tag (td) in the table body phase. -Line: 1 Col: 58 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <table> -| <caption> -| "test TEST" -| <tbody> -| <tr> -| <td> -| "test" - -#data -<!DOCTYPE html><select><option><optgroup> -#errors -Line: 1 Col: 41 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <option> -| <optgroup> - -#data -<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option> -#errors -Line: 1 Col: 68 Unexpected select start tag in the select phase treated as select end tag. -Line: 1 Col: 76 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <optgroup> -| <option> -| <option> -| <option> - -#data -<!DOCTYPE html><select><optgroup><option><optgroup> -#errors -Line: 1 Col: 51 Expected closing tag. Unexpected end of file. -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <optgroup> -| <option> -| <optgroup> - -#data -<!DOCTYPE html><datalist><option>foo</datalist>bar -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <datalist> -| <option> -| "foo" -| "bar" - -#data -<!DOCTYPE html><font><input><input></font> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <font> -| <input> -| <input> - -#data -<!DOCTYPE html><!-- XXX - XXX --> -#errors -#document -| <!DOCTYPE html> -| <!-- XXX - XXX --> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><!-- XXX - XXX -#errors -Line: 1 Col: 29 Unexpected end of file in comment (-) -#document -| <!DOCTYPE html> -| <!-- XXX - XXX --> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><!-- XXX - XXX - XXX --> -#errors -#document -| <!DOCTYPE html> -| <!-- XXX - XXX - XXX --> -| <html> -| <head> -| <body> - -#data -<isindex test=x name=x> -#errors -Line: 1 Col: 23 Unexpected start tag (isindex). Expected DOCTYPE. -Line: 1 Col: 23 Unexpected start tag isindex. Don't use it! -#document -| <html> -| <head> -| <body> -| <form> -| <hr> -| <label> -| "This is a searchable index. Enter search keywords: " -| <input> -| name="isindex" -| test="x" -| <hr> - -#data -test -test -#errors -Line: 2 Col: 4 Unexpected non-space characters. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> -| "test -test" - -#data -<!DOCTYPE html><body><title>test</body> -#errors -#document -| -| -| -| -| -| "test</body>" - -#data -<!DOCTYPE html><body><title>X -#errors -#document -| -| -| -| -| -| "X" -| <meta> -| name="z" -| <link> -| rel="foo" -| <style> -| " -x { content:"</style" } " - -#data -<!DOCTYPE html><select><optgroup></optgroup></select> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> -| <select> -| <optgroup> - -#data - - -#errors -Line: 2 Col: 1 Unexpected End of file. Expected DOCTYPE. -#document -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html> <html> -#errors -#document -| <!DOCTYPE html> -| <html> -| <head> -| <body> - -#data -<!DOCTYPE html><script> -</script> <title>x -#errors -#document -| -| -| -| -#errors -Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. -Line: 1 Col: 21 Unexpected start tag (script) that can be in head. Moved. -#document -| -| -| -#errors -Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. -Line: 1 Col: 28 Unexpected start tag (style) that can be in head. Moved. -#document -| -| -| -#errors -Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. -#document -| -| -| -| -| "x" -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -Line: 1 Col: 22 Unexpected end of file. Expected end tag (style). -#document -| -| -| --> x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -| x -#errors -Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. -#document -| -| -|

-#errors -#document -| -| -| -| -| -| ddd -#errors -#document -| -| -| -#errors -#document -| -| -| -| -|
  • -| -| - - -

    /debug/events

    - -
  • - {{range $i, $fam := .Families}} - - - - {{range $j, $bucket := $.Buckets}} - {{$n := index $.Counts $i $j}} - - {{end}} - - {{end}} -
    {{$fam}} - {{if $n}}{{end}} - [{{$n}} {{$bucket.String}}] - {{if $n}}{{end}} -
    - -{{if $.EventLogs}} -


    -

    Family: {{$.Family}}

    - -{{if $.Expanded}}
    {{end}} -[Summary]{{if $.Expanded}}{{end}} - -{{if not $.Expanded}}{{end}} -[Expanded]{{if not $.Expanded}}{{end}} - - - - {{range $el := $.EventLogs}} - - - - - {{if $.Expanded}} - - - - - - {{range $el.Events}} - - - - - - {{end}} - {{end}} - {{end}} -
    WhenElapsed
    {{$el.When}}{{$el.ElapsedTime}}{{$el.Title}} -
    {{$el.Stack|trimSpace}}
    {{.WhenString}}{{elapsed .Elapsed}}.{{if .IsErr}}E{{else}}.{{end}}. {{.What}}
    -{{end}} - - -` diff --git a/vendor/golang.org/x/net/trace/histogram.go b/vendor/golang.org/x/net/trace/histogram.go deleted file mode 100644 index 9bf4286c794..00000000000 --- a/vendor/golang.org/x/net/trace/histogram.go +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2015 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 trace - -// This file implements histogramming for RPC statistics collection. - -import ( - "bytes" - "fmt" - "html/template" - "log" - "math" - "sync" - - "golang.org/x/net/internal/timeseries" -) - -const ( - bucketCount = 38 -) - -// histogram keeps counts of values in buckets that are spaced -// out in powers of 2: 0-1, 2-3, 4-7... -// histogram implements timeseries.Observable -type histogram struct { - sum int64 // running total of measurements - sumOfSquares float64 // square of running total - buckets []int64 // bucketed values for histogram - value int // holds a single value as an optimization - valueCount int64 // number of values recorded for single value -} - -// AddMeasurement records a value measurement observation to the histogram. -func (h *histogram) addMeasurement(value int64) { - // TODO: assert invariant - h.sum += value - h.sumOfSquares += float64(value) * float64(value) - - bucketIndex := getBucket(value) - - if h.valueCount == 0 || (h.valueCount > 0 && h.value == bucketIndex) { - h.value = bucketIndex - h.valueCount++ - } else { - h.allocateBuckets() - h.buckets[bucketIndex]++ - } -} - -func (h *histogram) allocateBuckets() { - if h.buckets == nil { - h.buckets = make([]int64, bucketCount) - h.buckets[h.value] = h.valueCount - h.value = 0 - h.valueCount = -1 - } -} - -func log2(i int64) int { - n := 0 - for ; i >= 0x100; i >>= 8 { - n += 8 - } - for ; i > 0; i >>= 1 { - n += 1 - } - return n -} - -func getBucket(i int64) (index int) { - index = log2(i) - 1 - if index < 0 { - index = 0 - } - if index >= bucketCount { - index = bucketCount - 1 - } - return -} - -// Total returns the number of recorded observations. -func (h *histogram) total() (total int64) { - if h.valueCount >= 0 { - total = h.valueCount - } - for _, val := range h.buckets { - total += int64(val) - } - return -} - -// Average returns the average value of recorded observations. -func (h *histogram) average() float64 { - t := h.total() - if t == 0 { - return 0 - } - return float64(h.sum) / float64(t) -} - -// Variance returns the variance of recorded observations. -func (h *histogram) variance() float64 { - t := float64(h.total()) - if t == 0 { - return 0 - } - s := float64(h.sum) / t - return h.sumOfSquares/t - s*s -} - -// StandardDeviation returns the standard deviation of recorded observations. -func (h *histogram) standardDeviation() float64 { - return math.Sqrt(h.variance()) -} - -// PercentileBoundary estimates the value that the given fraction of recorded -// observations are less than. -func (h *histogram) percentileBoundary(percentile float64) int64 { - total := h.total() - - // Corner cases (make sure result is strictly less than Total()) - if total == 0 { - return 0 - } else if total == 1 { - return int64(h.average()) - } - - percentOfTotal := round(float64(total) * percentile) - var runningTotal int64 - - for i := range h.buckets { - value := h.buckets[i] - runningTotal += value - if runningTotal == percentOfTotal { - // We hit an exact bucket boundary. If the next bucket has data, it is a - // good estimate of the value. If the bucket is empty, we interpolate the - // midpoint between the next bucket's boundary and the next non-zero - // bucket. If the remaining buckets are all empty, then we use the - // boundary for the next bucket as the estimate. - j := uint8(i + 1) - min := bucketBoundary(j) - if runningTotal < total { - for h.buckets[j] == 0 { - j++ - } - } - max := bucketBoundary(j) - return min + round(float64(max-min)/2) - } else if runningTotal > percentOfTotal { - // The value is in this bucket. Interpolate the value. - delta := runningTotal - percentOfTotal - percentBucket := float64(value-delta) / float64(value) - bucketMin := bucketBoundary(uint8(i)) - nextBucketMin := bucketBoundary(uint8(i + 1)) - bucketSize := nextBucketMin - bucketMin - return bucketMin + round(percentBucket*float64(bucketSize)) - } - } - return bucketBoundary(bucketCount - 1) -} - -// Median returns the estimated median of the observed values. -func (h *histogram) median() int64 { - return h.percentileBoundary(0.5) -} - -// Add adds other to h. -func (h *histogram) Add(other timeseries.Observable) { - o := other.(*histogram) - if o.valueCount == 0 { - // Other histogram is empty - } else if h.valueCount >= 0 && o.valueCount > 0 && h.value == o.value { - // Both have a single bucketed value, aggregate them - h.valueCount += o.valueCount - } else { - // Two different values necessitate buckets in this histogram - h.allocateBuckets() - if o.valueCount >= 0 { - h.buckets[o.value] += o.valueCount - } else { - for i := range h.buckets { - h.buckets[i] += o.buckets[i] - } - } - } - h.sumOfSquares += o.sumOfSquares - h.sum += o.sum -} - -// Clear resets the histogram to an empty state, removing all observed values. -func (h *histogram) Clear() { - h.buckets = nil - h.value = 0 - h.valueCount = 0 - h.sum = 0 - h.sumOfSquares = 0 -} - -// CopyFrom copies from other, which must be a *histogram, into h. -func (h *histogram) CopyFrom(other timeseries.Observable) { - o := other.(*histogram) - if o.valueCount == -1 { - h.allocateBuckets() - copy(h.buckets, o.buckets) - } - h.sum = o.sum - h.sumOfSquares = o.sumOfSquares - h.value = o.value - h.valueCount = o.valueCount -} - -// Multiply scales the histogram by the specified ratio. -func (h *histogram) Multiply(ratio float64) { - if h.valueCount == -1 { - for i := range h.buckets { - h.buckets[i] = int64(float64(h.buckets[i]) * ratio) - } - } else { - h.valueCount = int64(float64(h.valueCount) * ratio) - } - h.sum = int64(float64(h.sum) * ratio) - h.sumOfSquares = h.sumOfSquares * ratio -} - -// New creates a new histogram. -func (h *histogram) New() timeseries.Observable { - r := new(histogram) - r.Clear() - return r -} - -func (h *histogram) String() string { - return fmt.Sprintf("%d, %f, %d, %d, %v", - h.sum, h.sumOfSquares, h.value, h.valueCount, h.buckets) -} - -// round returns the closest int64 to the argument -func round(in float64) int64 { - return int64(math.Floor(in + 0.5)) -} - -// bucketBoundary returns the first value in the bucket. -func bucketBoundary(bucket uint8) int64 { - if bucket == 0 { - return 0 - } - return 1 << bucket -} - -// bucketData holds data about a specific bucket for use in distTmpl. -type bucketData struct { - Lower, Upper int64 - N int64 - Pct, CumulativePct float64 - GraphWidth int -} - -// data holds data about a Distribution for use in distTmpl. -type data struct { - Buckets []*bucketData - Count, Median int64 - Mean, StandardDeviation float64 -} - -// maxHTMLBarWidth is the maximum width of the HTML bar for visualizing buckets. -const maxHTMLBarWidth = 350.0 - -// newData returns data representing h for use in distTmpl. -func (h *histogram) newData() *data { - // Force the allocation of buckets to simplify the rendering implementation - h.allocateBuckets() - // We scale the bars on the right so that the largest bar is - // maxHTMLBarWidth pixels in width. - maxBucket := int64(0) - for _, n := range h.buckets { - if n > maxBucket { - maxBucket = n - } - } - total := h.total() - barsizeMult := maxHTMLBarWidth / float64(maxBucket) - var pctMult float64 - if total == 0 { - pctMult = 1.0 - } else { - pctMult = 100.0 / float64(total) - } - - buckets := make([]*bucketData, len(h.buckets)) - runningTotal := int64(0) - for i, n := range h.buckets { - if n == 0 { - continue - } - runningTotal += n - var upperBound int64 - if i < bucketCount-1 { - upperBound = bucketBoundary(uint8(i + 1)) - } else { - upperBound = math.MaxInt64 - } - buckets[i] = &bucketData{ - Lower: bucketBoundary(uint8(i)), - Upper: upperBound, - N: n, - Pct: float64(n) * pctMult, - CumulativePct: float64(runningTotal) * pctMult, - GraphWidth: int(float64(n) * barsizeMult), - } - } - return &data{ - Buckets: buckets, - Count: total, - Median: h.median(), - Mean: h.average(), - StandardDeviation: h.standardDeviation(), - } -} - -func (h *histogram) html() template.HTML { - buf := new(bytes.Buffer) - if err := distTmpl().Execute(buf, h.newData()); err != nil { - buf.Reset() - log.Printf("net/trace: couldn't execute template: %v", err) - } - return template.HTML(buf.String()) -} - -var distTmplCache *template.Template -var distTmplOnce sync.Once - -func distTmpl() *template.Template { - distTmplOnce.Do(func() { - // Input: data - distTmplCache = template.Must(template.New("distTmpl").Parse(` - - - - - - - -
    Count: {{.Count}}Mean: {{printf "%.0f" .Mean}}StdDev: {{printf "%.0f" .StandardDeviation}}Median: {{.Median}}
    -
    - -{{range $b := .Buckets}} -{{if $b}} - - - - - - - - - -{{end}} -{{end}} -
    [{{.Lower}},{{.Upper}}){{.N}}{{printf "%#.3f" .Pct}}%{{printf "%#.3f" .CumulativePct}}%
    -`)) - }) - return distTmplCache -} diff --git a/vendor/golang.org/x/net/trace/trace.go b/vendor/golang.org/x/net/trace/trace.go deleted file mode 100644 index 3d9b646111f..00000000000 --- a/vendor/golang.org/x/net/trace/trace.go +++ /dev/null @@ -1,1066 +0,0 @@ -// Copyright 2015 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 trace implements tracing of requests and long-lived objects. -It exports HTTP interfaces on /debug/requests and /debug/events. - -A trace.Trace provides tracing for short-lived objects, usually requests. -A request handler might be implemented like this: - - func fooHandler(w http.ResponseWriter, req *http.Request) { - tr := trace.New("mypkg.Foo", req.URL.Path) - defer tr.Finish() - ... - tr.LazyPrintf("some event %q happened", str) - ... - if err := somethingImportant(); err != nil { - tr.LazyPrintf("somethingImportant failed: %v", err) - tr.SetError() - } - } - -The /debug/requests HTTP endpoint organizes the traces by family, -errors, and duration. It also provides histogram of request duration -for each family. - -A trace.EventLog provides tracing for long-lived objects, such as RPC -connections. - - // A Fetcher fetches URL paths for a single domain. - type Fetcher struct { - domain string - events trace.EventLog - } - - func NewFetcher(domain string) *Fetcher { - return &Fetcher{ - domain, - trace.NewEventLog("mypkg.Fetcher", domain), - } - } - - func (f *Fetcher) Fetch(path string) (string, error) { - resp, err := http.Get("http://" + f.domain + "/" + path) - if err != nil { - f.events.Errorf("Get(%q) = %v", path, err) - return "", err - } - f.events.Printf("Get(%q) = %s", path, resp.Status) - ... - } - - func (f *Fetcher) Close() error { - f.events.Finish() - return nil - } - -The /debug/events HTTP endpoint organizes the event logs by family and -by time since the last error. The expanded view displays recent log -entries and the log's call stack. -*/ -package trace // import "golang.org/x/net/trace" - -import ( - "bytes" - "fmt" - "html/template" - "io" - "log" - "net" - "net/http" - "runtime" - "sort" - "strconv" - "sync" - "sync/atomic" - "time" - - "golang.org/x/net/internal/timeseries" -) - -// DebugUseAfterFinish controls whether to debug uses of Trace values after finishing. -// FOR DEBUGGING ONLY. This will slow down the program. -var DebugUseAfterFinish = false - -// AuthRequest determines whether a specific request is permitted to load the -// /debug/requests or /debug/events pages. -// -// It returns two bools; the first indicates whether the page may be viewed at all, -// and the second indicates whether sensitive events will be shown. -// -// AuthRequest may be replaced by a program to customize its authorization requirements. -// -// The default AuthRequest function returns (true, true) if and only if the request -// comes from localhost/127.0.0.1/[::1]. -var AuthRequest = func(req *http.Request) (any, sensitive bool) { - // RemoteAddr is commonly in the form "IP" or "IP:port". - // If it is in the form "IP:port", split off the port. - host, _, err := net.SplitHostPort(req.RemoteAddr) - if err != nil { - host = req.RemoteAddr - } - switch host { - case "localhost", "127.0.0.1", "::1": - return true, true - default: - return false, false - } -} - -func init() { - http.HandleFunc("/debug/requests", func(w http.ResponseWriter, req *http.Request) { - any, sensitive := AuthRequest(req) - if !any { - http.Error(w, "not allowed", http.StatusUnauthorized) - return - } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - Render(w, req, sensitive) - }) - http.HandleFunc("/debug/events", func(w http.ResponseWriter, req *http.Request) { - any, sensitive := AuthRequest(req) - if !any { - http.Error(w, "not allowed", http.StatusUnauthorized) - return - } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - RenderEvents(w, req, sensitive) - }) -} - -// Render renders the HTML page typically served at /debug/requests. -// It does not do any auth checking; see AuthRequest for the default auth check -// used by the handler registered on http.DefaultServeMux. -// req may be nil. -func Render(w io.Writer, req *http.Request, sensitive bool) { - data := &struct { - Families []string - ActiveTraceCount map[string]int - CompletedTraces map[string]*family - - // Set when a bucket has been selected. - Traces traceList - Family string - Bucket int - Expanded bool - Traced bool - Active bool - ShowSensitive bool // whether to show sensitive events - - Histogram template.HTML - HistogramWindow string // e.g. "last minute", "last hour", "all time" - - // If non-zero, the set of traces is a partial set, - // and this is the total number. - Total int - }{ - CompletedTraces: completedTraces, - } - - data.ShowSensitive = sensitive - if req != nil { - // Allow show_sensitive=0 to force hiding of sensitive data for testing. - // This only goes one way; you can't use show_sensitive=1 to see things. - if req.FormValue("show_sensitive") == "0" { - data.ShowSensitive = false - } - - if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil { - data.Expanded = exp - } - if exp, err := strconv.ParseBool(req.FormValue("rtraced")); err == nil { - data.Traced = exp - } - } - - completedMu.RLock() - data.Families = make([]string, 0, len(completedTraces)) - for fam := range completedTraces { - data.Families = append(data.Families, fam) - } - completedMu.RUnlock() - sort.Strings(data.Families) - - // We are careful here to minimize the time spent locking activeMu, - // since that lock is required every time an RPC starts and finishes. - data.ActiveTraceCount = make(map[string]int, len(data.Families)) - activeMu.RLock() - for fam, s := range activeTraces { - data.ActiveTraceCount[fam] = s.Len() - } - activeMu.RUnlock() - - var ok bool - data.Family, data.Bucket, ok = parseArgs(req) - switch { - case !ok: - // No-op - case data.Bucket == -1: - data.Active = true - n := data.ActiveTraceCount[data.Family] - data.Traces = getActiveTraces(data.Family) - if len(data.Traces) < n { - data.Total = n - } - case data.Bucket < bucketsPerFamily: - if b := lookupBucket(data.Family, data.Bucket); b != nil { - data.Traces = b.Copy(data.Traced) - } - default: - if f := getFamily(data.Family, false); f != nil { - var obs timeseries.Observable - f.LatencyMu.RLock() - switch o := data.Bucket - bucketsPerFamily; o { - case 0: - obs = f.Latency.Minute() - data.HistogramWindow = "last minute" - case 1: - obs = f.Latency.Hour() - data.HistogramWindow = "last hour" - case 2: - obs = f.Latency.Total() - data.HistogramWindow = "all time" - } - f.LatencyMu.RUnlock() - if obs != nil { - data.Histogram = obs.(*histogram).html() - } - } - } - - if data.Traces != nil { - defer data.Traces.Free() - sort.Sort(data.Traces) - } - - completedMu.RLock() - defer completedMu.RUnlock() - if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil { - log.Printf("net/trace: Failed executing template: %v", err) - } -} - -func parseArgs(req *http.Request) (fam string, b int, ok bool) { - if req == nil { - return "", 0, false - } - fam, bStr := req.FormValue("fam"), req.FormValue("b") - if fam == "" || bStr == "" { - return "", 0, false - } - b, err := strconv.Atoi(bStr) - if err != nil || b < -1 { - return "", 0, false - } - - return fam, b, true -} - -func lookupBucket(fam string, b int) *traceBucket { - f := getFamily(fam, false) - if f == nil || b < 0 || b >= len(f.Buckets) { - return nil - } - return f.Buckets[b] -} - -type contextKeyT string - -var contextKey = contextKeyT("golang.org/x/net/trace.Trace") - -// Trace represents an active request. -type Trace interface { - // LazyLog adds x to the event log. It will be evaluated each time the - // /debug/requests page is rendered. Any memory referenced by x will be - // pinned until the trace is finished and later discarded. - LazyLog(x fmt.Stringer, sensitive bool) - - // LazyPrintf evaluates its arguments with fmt.Sprintf each time the - // /debug/requests page is rendered. Any memory referenced by a will be - // pinned until the trace is finished and later discarded. - LazyPrintf(format string, a ...interface{}) - - // SetError declares that this trace resulted in an error. - SetError() - - // SetRecycler sets a recycler for the trace. - // f will be called for each event passed to LazyLog at a time when - // it is no longer required, whether while the trace is still active - // and the event is discarded, or when a completed trace is discarded. - SetRecycler(f func(interface{})) - - // SetTraceInfo sets the trace info for the trace. - // This is currently unused. - SetTraceInfo(traceID, spanID uint64) - - // SetMaxEvents sets the maximum number of events that will be stored - // in the trace. This has no effect if any events have already been - // added to the trace. - SetMaxEvents(m int) - - // Finish declares that this trace is complete. - // The trace should not be used after calling this method. - Finish() -} - -type lazySprintf struct { - format string - a []interface{} -} - -func (l *lazySprintf) String() string { - return fmt.Sprintf(l.format, l.a...) -} - -// New returns a new Trace with the specified family and title. -func New(family, title string) Trace { - tr := newTrace() - tr.ref() - tr.Family, tr.Title = family, title - tr.Start = time.Now() - tr.maxEvents = maxEventsPerTrace - tr.events = tr.eventsBuf[:0] - - activeMu.RLock() - s := activeTraces[tr.Family] - activeMu.RUnlock() - if s == nil { - activeMu.Lock() - s = activeTraces[tr.Family] // check again - if s == nil { - s = new(traceSet) - activeTraces[tr.Family] = s - } - activeMu.Unlock() - } - s.Add(tr) - - // Trigger allocation of the completed trace structure for this family. - // This will cause the family to be present in the request page during - // the first trace of this family. We don't care about the return value, - // nor is there any need for this to run inline, so we execute it in its - // own goroutine, but only if the family isn't allocated yet. - completedMu.RLock() - if _, ok := completedTraces[tr.Family]; !ok { - go allocFamily(tr.Family) - } - completedMu.RUnlock() - - return tr -} - -func (tr *trace) Finish() { - tr.Elapsed = time.Now().Sub(tr.Start) - if DebugUseAfterFinish { - buf := make([]byte, 4<<10) // 4 KB should be enough - n := runtime.Stack(buf, false) - tr.finishStack = buf[:n] - } - - activeMu.RLock() - m := activeTraces[tr.Family] - activeMu.RUnlock() - m.Remove(tr) - - f := getFamily(tr.Family, true) - for _, b := range f.Buckets { - if b.Cond.match(tr) { - b.Add(tr) - } - } - // Add a sample of elapsed time as microseconds to the family's timeseries - h := new(histogram) - h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3) - f.LatencyMu.Lock() - f.Latency.Add(h) - f.LatencyMu.Unlock() - - tr.unref() // matches ref in New -} - -const ( - bucketsPerFamily = 9 - tracesPerBucket = 10 - maxActiveTraces = 20 // Maximum number of active traces to show. - maxEventsPerTrace = 10 - numHistogramBuckets = 38 -) - -var ( - // The active traces. - activeMu sync.RWMutex - activeTraces = make(map[string]*traceSet) // family -> traces - - // Families of completed traces. - completedMu sync.RWMutex - completedTraces = make(map[string]*family) // family -> traces -) - -type traceSet struct { - mu sync.RWMutex - m map[*trace]bool - - // We could avoid the entire map scan in FirstN by having a slice of all the traces - // ordered by start time, and an index into that from the trace struct, with a periodic - // repack of the slice after enough traces finish; we could also use a skip list or similar. - // However, that would shift some of the expense from /debug/requests time to RPC time, - // which is probably the wrong trade-off. -} - -func (ts *traceSet) Len() int { - ts.mu.RLock() - defer ts.mu.RUnlock() - return len(ts.m) -} - -func (ts *traceSet) Add(tr *trace) { - ts.mu.Lock() - if ts.m == nil { - ts.m = make(map[*trace]bool) - } - ts.m[tr] = true - ts.mu.Unlock() -} - -func (ts *traceSet) Remove(tr *trace) { - ts.mu.Lock() - delete(ts.m, tr) - ts.mu.Unlock() -} - -// FirstN returns the first n traces ordered by time. -func (ts *traceSet) FirstN(n int) traceList { - ts.mu.RLock() - defer ts.mu.RUnlock() - - if n > len(ts.m) { - n = len(ts.m) - } - trl := make(traceList, 0, n) - - // Fast path for when no selectivity is needed. - if n == len(ts.m) { - for tr := range ts.m { - tr.ref() - trl = append(trl, tr) - } - sort.Sort(trl) - return trl - } - - // Pick the oldest n traces. - // This is inefficient. See the comment in the traceSet struct. - for tr := range ts.m { - // Put the first n traces into trl in the order they occur. - // When we have n, sort trl, and thereafter maintain its order. - if len(trl) < n { - tr.ref() - trl = append(trl, tr) - if len(trl) == n { - // This is guaranteed to happen exactly once during this loop. - sort.Sort(trl) - } - continue - } - if tr.Start.After(trl[n-1].Start) { - continue - } - - // Find where to insert this one. - tr.ref() - i := sort.Search(n, func(i int) bool { return trl[i].Start.After(tr.Start) }) - trl[n-1].unref() - copy(trl[i+1:], trl[i:]) - trl[i] = tr - } - - return trl -} - -func getActiveTraces(fam string) traceList { - activeMu.RLock() - s := activeTraces[fam] - activeMu.RUnlock() - if s == nil { - return nil - } - return s.FirstN(maxActiveTraces) -} - -func getFamily(fam string, allocNew bool) *family { - completedMu.RLock() - f := completedTraces[fam] - completedMu.RUnlock() - if f == nil && allocNew { - f = allocFamily(fam) - } - return f -} - -func allocFamily(fam string) *family { - completedMu.Lock() - defer completedMu.Unlock() - f := completedTraces[fam] - if f == nil { - f = newFamily() - completedTraces[fam] = f - } - return f -} - -// family represents a set of trace buckets and associated latency information. -type family struct { - // traces may occur in multiple buckets. - Buckets [bucketsPerFamily]*traceBucket - - // latency time series - LatencyMu sync.RWMutex - Latency *timeseries.MinuteHourSeries -} - -func newFamily() *family { - return &family{ - Buckets: [bucketsPerFamily]*traceBucket{ - {Cond: minCond(0)}, - {Cond: minCond(50 * time.Millisecond)}, - {Cond: minCond(100 * time.Millisecond)}, - {Cond: minCond(200 * time.Millisecond)}, - {Cond: minCond(500 * time.Millisecond)}, - {Cond: minCond(1 * time.Second)}, - {Cond: minCond(10 * time.Second)}, - {Cond: minCond(100 * time.Second)}, - {Cond: errorCond{}}, - }, - Latency: timeseries.NewMinuteHourSeries(func() timeseries.Observable { return new(histogram) }), - } -} - -// traceBucket represents a size-capped bucket of historic traces, -// along with a condition for a trace to belong to the bucket. -type traceBucket struct { - Cond cond - - // Ring buffer implementation of a fixed-size FIFO queue. - mu sync.RWMutex - buf [tracesPerBucket]*trace - start int // < tracesPerBucket - length int // <= tracesPerBucket -} - -func (b *traceBucket) Add(tr *trace) { - b.mu.Lock() - defer b.mu.Unlock() - - i := b.start + b.length - if i >= tracesPerBucket { - i -= tracesPerBucket - } - if b.length == tracesPerBucket { - // "Remove" an element from the bucket. - b.buf[i].unref() - b.start++ - if b.start == tracesPerBucket { - b.start = 0 - } - } - b.buf[i] = tr - if b.length < tracesPerBucket { - b.length++ - } - tr.ref() -} - -// Copy returns a copy of the traces in the bucket. -// If tracedOnly is true, only the traces with trace information will be returned. -// The logs will be ref'd before returning; the caller should call -// the Free method when it is done with them. -// TODO(dsymonds): keep track of traced requests in separate buckets. -func (b *traceBucket) Copy(tracedOnly bool) traceList { - b.mu.RLock() - defer b.mu.RUnlock() - - trl := make(traceList, 0, b.length) - for i, x := 0, b.start; i < b.length; i++ { - tr := b.buf[x] - if !tracedOnly || tr.spanID != 0 { - tr.ref() - trl = append(trl, tr) - } - x++ - if x == b.length { - x = 0 - } - } - return trl -} - -func (b *traceBucket) Empty() bool { - b.mu.RLock() - defer b.mu.RUnlock() - return b.length == 0 -} - -// cond represents a condition on a trace. -type cond interface { - match(t *trace) bool - String() string -} - -type minCond time.Duration - -func (m minCond) match(t *trace) bool { return t.Elapsed >= time.Duration(m) } -func (m minCond) String() string { return fmt.Sprintf("≥%gs", time.Duration(m).Seconds()) } - -type errorCond struct{} - -func (e errorCond) match(t *trace) bool { return t.IsError } -func (e errorCond) String() string { return "errors" } - -type traceList []*trace - -// Free calls unref on each element of the list. -func (trl traceList) Free() { - for _, t := range trl { - t.unref() - } -} - -// traceList may be sorted in reverse chronological order. -func (trl traceList) Len() int { return len(trl) } -func (trl traceList) Less(i, j int) bool { return trl[i].Start.After(trl[j].Start) } -func (trl traceList) Swap(i, j int) { trl[i], trl[j] = trl[j], trl[i] } - -// An event is a timestamped log entry in a trace. -type event struct { - When time.Time - Elapsed time.Duration // since previous event in trace - NewDay bool // whether this event is on a different day to the previous event - Recyclable bool // whether this event was passed via LazyLog - Sensitive bool // whether this event contains sensitive information - What interface{} // string or fmt.Stringer -} - -// WhenString returns a string representation of the elapsed time of the event. -// It will include the date if midnight was crossed. -func (e event) WhenString() string { - if e.NewDay { - return e.When.Format("2006/01/02 15:04:05.000000") - } - return e.When.Format("15:04:05.000000") -} - -// discarded represents a number of discarded events. -// It is stored as *discarded to make it easier to update in-place. -type discarded int - -func (d *discarded) String() string { - return fmt.Sprintf("(%d events discarded)", int(*d)) -} - -// trace represents an active or complete request, -// either sent or received by this program. -type trace struct { - // Family is the top-level grouping of traces to which this belongs. - Family string - - // Title is the title of this trace. - Title string - - // Timing information. - Start time.Time - Elapsed time.Duration // zero while active - - // Trace information if non-zero. - traceID uint64 - spanID uint64 - - // Whether this trace resulted in an error. - IsError bool - - // Append-only sequence of events (modulo discards). - mu sync.RWMutex - events []event - maxEvents int - - refs int32 // how many buckets this is in - recycler func(interface{}) - disc discarded // scratch space to avoid allocation - - finishStack []byte // where finish was called, if DebugUseAfterFinish is set - - eventsBuf [4]event // preallocated buffer in case we only log a few events -} - -func (tr *trace) reset() { - // Clear all but the mutex. Mutexes may not be copied, even when unlocked. - tr.Family = "" - tr.Title = "" - tr.Start = time.Time{} - tr.Elapsed = 0 - tr.traceID = 0 - tr.spanID = 0 - tr.IsError = false - tr.maxEvents = 0 - tr.events = nil - tr.refs = 0 - tr.recycler = nil - tr.disc = 0 - tr.finishStack = nil - for i := range tr.eventsBuf { - tr.eventsBuf[i] = event{} - } -} - -// delta returns the elapsed time since the last event or the trace start, -// and whether it spans midnight. -// L >= tr.mu -func (tr *trace) delta(t time.Time) (time.Duration, bool) { - if len(tr.events) == 0 { - return t.Sub(tr.Start), false - } - prev := tr.events[len(tr.events)-1].When - return t.Sub(prev), prev.Day() != t.Day() -} - -func (tr *trace) addEvent(x interface{}, recyclable, sensitive bool) { - if DebugUseAfterFinish && tr.finishStack != nil { - buf := make([]byte, 4<<10) // 4 KB should be enough - n := runtime.Stack(buf, false) - log.Printf("net/trace: trace used after finish:\nFinished at:\n%s\nUsed at:\n%s", tr.finishStack, buf[:n]) - } - - /* - NOTE TO DEBUGGERS - - If you are here because your program panicked in this code, - it is almost definitely the fault of code using this package, - and very unlikely to be the fault of this code. - - The most likely scenario is that some code elsewhere is using - a trace.Trace after its Finish method is called. - You can temporarily set the DebugUseAfterFinish var - to help discover where that is; do not leave that var set, - since it makes this package much less efficient. - */ - - e := event{When: time.Now(), What: x, Recyclable: recyclable, Sensitive: sensitive} - tr.mu.Lock() - e.Elapsed, e.NewDay = tr.delta(e.When) - if len(tr.events) < tr.maxEvents { - tr.events = append(tr.events, e) - } else { - // Discard the middle events. - di := int((tr.maxEvents - 1) / 2) - if d, ok := tr.events[di].What.(*discarded); ok { - (*d)++ - } else { - // disc starts at two to count for the event it is replacing, - // plus the next one that we are about to drop. - tr.disc = 2 - if tr.recycler != nil && tr.events[di].Recyclable { - go tr.recycler(tr.events[di].What) - } - tr.events[di].What = &tr.disc - } - // The timestamp of the discarded meta-event should be - // the time of the last event it is representing. - tr.events[di].When = tr.events[di+1].When - - if tr.recycler != nil && tr.events[di+1].Recyclable { - go tr.recycler(tr.events[di+1].What) - } - copy(tr.events[di+1:], tr.events[di+2:]) - tr.events[tr.maxEvents-1] = e - } - tr.mu.Unlock() -} - -func (tr *trace) LazyLog(x fmt.Stringer, sensitive bool) { - tr.addEvent(x, true, sensitive) -} - -func (tr *trace) LazyPrintf(format string, a ...interface{}) { - tr.addEvent(&lazySprintf{format, a}, false, false) -} - -func (tr *trace) SetError() { tr.IsError = true } - -func (tr *trace) SetRecycler(f func(interface{})) { - tr.recycler = f -} - -func (tr *trace) SetTraceInfo(traceID, spanID uint64) { - tr.traceID, tr.spanID = traceID, spanID -} - -func (tr *trace) SetMaxEvents(m int) { - // Always keep at least three events: first, discarded count, last. - if len(tr.events) == 0 && m > 3 { - tr.maxEvents = m - } -} - -func (tr *trace) ref() { - atomic.AddInt32(&tr.refs, 1) -} - -func (tr *trace) unref() { - if atomic.AddInt32(&tr.refs, -1) == 0 { - if tr.recycler != nil { - // freeTrace clears tr, so we hold tr.recycler and tr.events here. - go func(f func(interface{}), es []event) { - for _, e := range es { - if e.Recyclable { - f(e.What) - } - } - }(tr.recycler, tr.events) - } - - freeTrace(tr) - } -} - -func (tr *trace) When() string { - return tr.Start.Format("2006/01/02 15:04:05.000000") -} - -func (tr *trace) ElapsedTime() string { - t := tr.Elapsed - if t == 0 { - // Active trace. - t = time.Since(tr.Start) - } - return fmt.Sprintf("%.6f", t.Seconds()) -} - -func (tr *trace) Events() []event { - tr.mu.RLock() - defer tr.mu.RUnlock() - return tr.events -} - -var traceFreeList = make(chan *trace, 1000) // TODO(dsymonds): Use sync.Pool? - -// newTrace returns a trace ready to use. -func newTrace() *trace { - select { - case tr := <-traceFreeList: - return tr - default: - return new(trace) - } -} - -// freeTrace adds tr to traceFreeList if there's room. -// This is non-blocking. -func freeTrace(tr *trace) { - if DebugUseAfterFinish { - return // never reuse - } - tr.reset() - select { - case traceFreeList <- tr: - default: - } -} - -func elapsed(d time.Duration) string { - b := []byte(fmt.Sprintf("%.6f", d.Seconds())) - - // For subsecond durations, blank all zeros before decimal point, - // and all zeros between the decimal point and the first non-zero digit. - if d < time.Second { - dot := bytes.IndexByte(b, '.') - for i := 0; i < dot; i++ { - b[i] = ' ' - } - for i := dot + 1; i < len(b); i++ { - if b[i] == '0' { - b[i] = ' ' - } else { - break - } - } - } - - return string(b) -} - -var pageTmplCache *template.Template -var pageTmplOnce sync.Once - -func pageTmpl() *template.Template { - pageTmplOnce.Do(func() { - pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{ - "elapsed": elapsed, - "add": func(a, b int) int { return a + b }, - }).Parse(pageHTML)) - }) - return pageTmplCache -} - -const pageHTML = ` -{{template "Prolog" .}} -{{template "StatusTable" .}} -{{template "Epilog" .}} - -{{define "Prolog"}} - - - /debug/requests - - - - -

    /debug/requests

    -{{end}} {{/* end of Prolog */}} - -{{define "StatusTable"}} - - {{range $fam := .Families}} - - - - {{$n := index $.ActiveTraceCount $fam}} - - - {{$f := index $.CompletedTraces $fam}} - {{range $i, $b := $f.Buckets}} - {{$empty := $b.Empty}} - - {{end}} - - {{$nb := len $f.Buckets}} - - - - - - {{end}} -
    {{$fam}} - {{if $n}}{{end}} - [{{$n}} active] - {{if $n}}{{end}} - - {{if not $empty}}{{end}} - [{{.Cond}}] - {{if not $empty}}{{end}} - - [minute] - - [hour] - - [total] -
    -{{end}} {{/* end of StatusTable */}} - -{{define "Epilog"}} -{{if $.Traces}} -
    -

    Family: {{$.Family}}

    - -{{if or $.Expanded $.Traced}} - [Normal/Summary] -{{else}} - [Normal/Summary] -{{end}} - -{{if or (not $.Expanded) $.Traced}} - [Normal/Expanded] -{{else}} - [Normal/Expanded] -{{end}} - -{{if not $.Active}} - {{if or $.Expanded (not $.Traced)}} - [Traced/Summary] - {{else}} - [Traced/Summary] - {{end}} - {{if or (not $.Expanded) (not $.Traced)}} - [Traced/Expanded] - {{else}} - [Traced/Expanded] - {{end}} -{{end}} - -{{if $.Total}} -

    Showing {{len $.Traces}} of {{$.Total}} traces.

    -{{end}} - - - - - {{range $tr := $.Traces}} - - - - - {{/* TODO: include traceID/spanID */}} - - {{if $.Expanded}} - {{range $tr.Events}} - - - - - - {{end}} - {{end}} - {{end}} -
    - {{if $.Active}}Active{{else}}Completed{{end}} Requests -
    WhenElapsed (s)
    {{$tr.When}}{{$tr.ElapsedTime}}{{$tr.Title}}
    {{.WhenString}}{{elapsed .Elapsed}}{{if or $.ShowSensitive (not .Sensitive)}}... {{.What}}{{else}}[redacted]{{end}}
    -{{end}} {{/* if $.Traces */}} - -{{if $.Histogram}} -

    Latency (µs) of {{$.Family}} over {{$.HistogramWindow}}

    -{{$.Histogram}} -{{end}} {{/* if $.Histogram */}} - - - -{{end}} {{/* end of Epilog */}} -` diff --git a/vendor/golang.org/x/net/trace/trace_go16.go b/vendor/golang.org/x/net/trace/trace_go16.go deleted file mode 100644 index d6081911853..00000000000 --- a/vendor/golang.org/x/net/trace/trace_go16.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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 file. - -// +build !go1.7 - -package trace - -import "golang.org/x/net/context" - -// NewContext returns a copy of the parent context -// and associates it with a Trace. -func NewContext(ctx context.Context, tr Trace) context.Context { - return context.WithValue(ctx, contextKey, tr) -} - -// FromContext returns the Trace bound to the context, if any. -func FromContext(ctx context.Context) (tr Trace, ok bool) { - tr, ok = ctx.Value(contextKey).(Trace) - return -} diff --git a/vendor/golang.org/x/net/trace/trace_go17.go b/vendor/golang.org/x/net/trace/trace_go17.go deleted file mode 100644 index df6e1fba7ca..00000000000 --- a/vendor/golang.org/x/net/trace/trace_go17.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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 file. - -// +build go1.7 - -package trace - -import "context" - -// NewContext returns a copy of the parent context -// and associates it with a Trace. -func NewContext(ctx context.Context, tr Trace) context.Context { - return context.WithValue(ctx, contextKey, tr) -} - -// FromContext returns the Trace bound to the context, if any. -func FromContext(ctx context.Context) (tr Trace, ok bool) { - tr, ok = ctx.Value(contextKey).(Trace) - return -} diff --git a/vendor/golang.org/x/net/webdav/file.go b/vendor/golang.org/x/net/webdav/file.go deleted file mode 100644 index 748118dd38c..00000000000 --- a/vendor/golang.org/x/net/webdav/file.go +++ /dev/null @@ -1,796 +0,0 @@ -// Copyright 2014 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 webdav - -import ( - "encoding/xml" - "io" - "net/http" - "os" - "path" - "path/filepath" - "strings" - "sync" - "time" - - "golang.org/x/net/context" -) - -// slashClean is equivalent to but slightly more efficient than -// path.Clean("/" + name). -func slashClean(name string) string { - if name == "" || name[0] != '/' { - name = "/" + name - } - return path.Clean(name) -} - -// A FileSystem implements access to a collection of named files. The elements -// in a file path are separated by slash ('/', U+002F) characters, regardless -// of host operating system convention. -// -// Each method has the same semantics as the os package's function of the same -// name. -// -// Note that the os.Rename documentation says that "OS-specific restrictions -// might apply". In particular, whether or not renaming a file or directory -// overwriting another existing file or directory is an error is OS-dependent. -type FileSystem interface { - Mkdir(ctx context.Context, name string, perm os.FileMode) error - OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) - RemoveAll(ctx context.Context, name string) error - Rename(ctx context.Context, oldName, newName string) error - Stat(ctx context.Context, name string) (os.FileInfo, error) -} - -// A File is returned by a FileSystem's OpenFile method and can be served by a -// Handler. -// -// A File may optionally implement the DeadPropsHolder interface, if it can -// load and save dead properties. -type File interface { - http.File - io.Writer -} - -// A Dir implements FileSystem using the native file system restricted to a -// specific directory tree. -// -// While the FileSystem.OpenFile method takes '/'-separated paths, a Dir's -// string value is a filename on the native file system, not a URL, so it is -// separated by filepath.Separator, which isn't necessarily '/'. -// -// An empty Dir is treated as ".". -type Dir string - -func (d Dir) resolve(name string) string { - // This implementation is based on Dir.Open's code in the standard net/http package. - if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || - strings.Contains(name, "\x00") { - return "" - } - dir := string(d) - if dir == "" { - dir = "." - } - return filepath.Join(dir, filepath.FromSlash(slashClean(name))) -} - -func (d Dir) Mkdir(ctx context.Context, name string, perm os.FileMode) error { - if name = d.resolve(name); name == "" { - return os.ErrNotExist - } - return os.Mkdir(name, perm) -} - -func (d Dir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) { - if name = d.resolve(name); name == "" { - return nil, os.ErrNotExist - } - f, err := os.OpenFile(name, flag, perm) - if err != nil { - return nil, err - } - return f, nil -} - -func (d Dir) RemoveAll(ctx context.Context, name string) error { - if name = d.resolve(name); name == "" { - return os.ErrNotExist - } - if name == filepath.Clean(string(d)) { - // Prohibit removing the virtual root directory. - return os.ErrInvalid - } - return os.RemoveAll(name) -} - -func (d Dir) Rename(ctx context.Context, oldName, newName string) error { - if oldName = d.resolve(oldName); oldName == "" { - return os.ErrNotExist - } - if newName = d.resolve(newName); newName == "" { - return os.ErrNotExist - } - if root := filepath.Clean(string(d)); root == oldName || root == newName { - // Prohibit renaming from or to the virtual root directory. - return os.ErrInvalid - } - return os.Rename(oldName, newName) -} - -func (d Dir) Stat(ctx context.Context, name string) (os.FileInfo, error) { - if name = d.resolve(name); name == "" { - return nil, os.ErrNotExist - } - return os.Stat(name) -} - -// NewMemFS returns a new in-memory FileSystem implementation. -func NewMemFS() FileSystem { - return &memFS{ - root: memFSNode{ - children: make(map[string]*memFSNode), - mode: 0660 | os.ModeDir, - modTime: time.Now(), - }, - } -} - -// A memFS implements FileSystem, storing all metadata and actual file data -// in-memory. No limits on filesystem size are used, so it is not recommended -// this be used where the clients are untrusted. -// -// Concurrent access is permitted. The tree structure is protected by a mutex, -// and each node's contents and metadata are protected by a per-node mutex. -// -// TODO: Enforce file permissions. -type memFS struct { - mu sync.Mutex - root memFSNode -} - -// TODO: clean up and rationalize the walk/find code. - -// walk walks the directory tree for the fullname, calling f at each step. If f -// returns an error, the walk will be aborted and return that same error. -// -// dir is the directory at that step, frag is the name fragment, and final is -// whether it is the final step. For example, walking "/foo/bar/x" will result -// in 3 calls to f: -// - "/", "foo", false -// - "/foo/", "bar", false -// - "/foo/bar/", "x", true -// The frag argument will be empty only if dir is the root node and the walk -// ends at that root node. -func (fs *memFS) walk(op, fullname string, f func(dir *memFSNode, frag string, final bool) error) error { - original := fullname - fullname = slashClean(fullname) - - // Strip any leading "/"s to make fullname a relative path, as the walk - // starts at fs.root. - if fullname[0] == '/' { - fullname = fullname[1:] - } - dir := &fs.root - - for { - frag, remaining := fullname, "" - i := strings.IndexRune(fullname, '/') - final := i < 0 - if !final { - frag, remaining = fullname[:i], fullname[i+1:] - } - if frag == "" && dir != &fs.root { - panic("webdav: empty path fragment for a clean path") - } - if err := f(dir, frag, final); err != nil { - return &os.PathError{ - Op: op, - Path: original, - Err: err, - } - } - if final { - break - } - child := dir.children[frag] - if child == nil { - return &os.PathError{ - Op: op, - Path: original, - Err: os.ErrNotExist, - } - } - if !child.mode.IsDir() { - return &os.PathError{ - Op: op, - Path: original, - Err: os.ErrInvalid, - } - } - dir, fullname = child, remaining - } - return nil -} - -// find returns the parent of the named node and the relative name fragment -// from the parent to the child. For example, if finding "/foo/bar/baz" then -// parent will be the node for "/foo/bar" and frag will be "baz". -// -// If the fullname names the root node, then parent, frag and err will be zero. -// -// find returns an error if the parent does not already exist or the parent -// isn't a directory, but it will not return an error per se if the child does -// not already exist. The error returned is either nil or an *os.PathError -// whose Op is op. -func (fs *memFS) find(op, fullname string) (parent *memFSNode, frag string, err error) { - err = fs.walk(op, fullname, func(parent0 *memFSNode, frag0 string, final bool) error { - if !final { - return nil - } - if frag0 != "" { - parent, frag = parent0, frag0 - } - return nil - }) - return parent, frag, err -} - -func (fs *memFS) Mkdir(ctx context.Context, name string, perm os.FileMode) error { - fs.mu.Lock() - defer fs.mu.Unlock() - - dir, frag, err := fs.find("mkdir", name) - if err != nil { - return err - } - if dir == nil { - // We can't create the root. - return os.ErrInvalid - } - if _, ok := dir.children[frag]; ok { - return os.ErrExist - } - dir.children[frag] = &memFSNode{ - children: make(map[string]*memFSNode), - mode: perm.Perm() | os.ModeDir, - modTime: time.Now(), - } - return nil -} - -func (fs *memFS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (File, error) { - fs.mu.Lock() - defer fs.mu.Unlock() - - dir, frag, err := fs.find("open", name) - if err != nil { - return nil, err - } - var n *memFSNode - if dir == nil { - // We're opening the root. - if flag&(os.O_WRONLY|os.O_RDWR) != 0 { - return nil, os.ErrPermission - } - n, frag = &fs.root, "/" - - } else { - n = dir.children[frag] - if flag&(os.O_SYNC|os.O_APPEND) != 0 { - // memFile doesn't support these flags yet. - return nil, os.ErrInvalid - } - if flag&os.O_CREATE != 0 { - if flag&os.O_EXCL != 0 && n != nil { - return nil, os.ErrExist - } - if n == nil { - n = &memFSNode{ - mode: perm.Perm(), - } - dir.children[frag] = n - } - } - if n == nil { - return nil, os.ErrNotExist - } - if flag&(os.O_WRONLY|os.O_RDWR) != 0 && flag&os.O_TRUNC != 0 { - n.mu.Lock() - n.data = nil - n.mu.Unlock() - } - } - - children := make([]os.FileInfo, 0, len(n.children)) - for cName, c := range n.children { - children = append(children, c.stat(cName)) - } - return &memFile{ - n: n, - nameSnapshot: frag, - childrenSnapshot: children, - }, nil -} - -func (fs *memFS) RemoveAll(ctx context.Context, name string) error { - fs.mu.Lock() - defer fs.mu.Unlock() - - dir, frag, err := fs.find("remove", name) - if err != nil { - return err - } - if dir == nil { - // We can't remove the root. - return os.ErrInvalid - } - delete(dir.children, frag) - return nil -} - -func (fs *memFS) Rename(ctx context.Context, oldName, newName string) error { - fs.mu.Lock() - defer fs.mu.Unlock() - - oldName = slashClean(oldName) - newName = slashClean(newName) - if oldName == newName { - return nil - } - if strings.HasPrefix(newName, oldName+"/") { - // We can't rename oldName to be a sub-directory of itself. - return os.ErrInvalid - } - - oDir, oFrag, err := fs.find("rename", oldName) - if err != nil { - return err - } - if oDir == nil { - // We can't rename from the root. - return os.ErrInvalid - } - - nDir, nFrag, err := fs.find("rename", newName) - if err != nil { - return err - } - if nDir == nil { - // We can't rename to the root. - return os.ErrInvalid - } - - oNode, ok := oDir.children[oFrag] - if !ok { - return os.ErrNotExist - } - if oNode.children != nil { - if nNode, ok := nDir.children[nFrag]; ok { - if nNode.children == nil { - return errNotADirectory - } - if len(nNode.children) != 0 { - return errDirectoryNotEmpty - } - } - } - delete(oDir.children, oFrag) - nDir.children[nFrag] = oNode - return nil -} - -func (fs *memFS) Stat(ctx context.Context, name string) (os.FileInfo, error) { - fs.mu.Lock() - defer fs.mu.Unlock() - - dir, frag, err := fs.find("stat", name) - if err != nil { - return nil, err - } - if dir == nil { - // We're stat'ting the root. - return fs.root.stat("/"), nil - } - if n, ok := dir.children[frag]; ok { - return n.stat(path.Base(name)), nil - } - return nil, os.ErrNotExist -} - -// A memFSNode represents a single entry in the in-memory filesystem and also -// implements os.FileInfo. -type memFSNode struct { - // children is protected by memFS.mu. - children map[string]*memFSNode - - mu sync.Mutex - data []byte - mode os.FileMode - modTime time.Time - deadProps map[xml.Name]Property -} - -func (n *memFSNode) stat(name string) *memFileInfo { - n.mu.Lock() - defer n.mu.Unlock() - return &memFileInfo{ - name: name, - size: int64(len(n.data)), - mode: n.mode, - modTime: n.modTime, - } -} - -func (n *memFSNode) DeadProps() (map[xml.Name]Property, error) { - n.mu.Lock() - defer n.mu.Unlock() - if len(n.deadProps) == 0 { - return nil, nil - } - ret := make(map[xml.Name]Property, len(n.deadProps)) - for k, v := range n.deadProps { - ret[k] = v - } - return ret, nil -} - -func (n *memFSNode) Patch(patches []Proppatch) ([]Propstat, error) { - n.mu.Lock() - defer n.mu.Unlock() - pstat := Propstat{Status: http.StatusOK} - for _, patch := range patches { - for _, p := range patch.Props { - pstat.Props = append(pstat.Props, Property{XMLName: p.XMLName}) - if patch.Remove { - delete(n.deadProps, p.XMLName) - continue - } - if n.deadProps == nil { - n.deadProps = map[xml.Name]Property{} - } - n.deadProps[p.XMLName] = p - } - } - return []Propstat{pstat}, nil -} - -type memFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (f *memFileInfo) Name() string { return f.name } -func (f *memFileInfo) Size() int64 { return f.size } -func (f *memFileInfo) Mode() os.FileMode { return f.mode } -func (f *memFileInfo) ModTime() time.Time { return f.modTime } -func (f *memFileInfo) IsDir() bool { return f.mode.IsDir() } -func (f *memFileInfo) Sys() interface{} { return nil } - -// A memFile is a File implementation for a memFSNode. It is a per-file (not -// per-node) read/write position, and a snapshot of the memFS' tree structure -// (a node's name and children) for that node. -type memFile struct { - n *memFSNode - nameSnapshot string - childrenSnapshot []os.FileInfo - // pos is protected by n.mu. - pos int -} - -// A *memFile implements the optional DeadPropsHolder interface. -var _ DeadPropsHolder = (*memFile)(nil) - -func (f *memFile) DeadProps() (map[xml.Name]Property, error) { return f.n.DeadProps() } -func (f *memFile) Patch(patches []Proppatch) ([]Propstat, error) { return f.n.Patch(patches) } - -func (f *memFile) Close() error { - return nil -} - -func (f *memFile) Read(p []byte) (int, error) { - f.n.mu.Lock() - defer f.n.mu.Unlock() - if f.n.mode.IsDir() { - return 0, os.ErrInvalid - } - if f.pos >= len(f.n.data) { - return 0, io.EOF - } - n := copy(p, f.n.data[f.pos:]) - f.pos += n - return n, nil -} - -func (f *memFile) Readdir(count int) ([]os.FileInfo, error) { - f.n.mu.Lock() - defer f.n.mu.Unlock() - if !f.n.mode.IsDir() { - return nil, os.ErrInvalid - } - old := f.pos - if old >= len(f.childrenSnapshot) { - // The os.File Readdir docs say that at the end of a directory, - // the error is io.EOF if count > 0 and nil if count <= 0. - if count > 0 { - return nil, io.EOF - } - return nil, nil - } - if count > 0 { - f.pos += count - if f.pos > len(f.childrenSnapshot) { - f.pos = len(f.childrenSnapshot) - } - } else { - f.pos = len(f.childrenSnapshot) - old = 0 - } - return f.childrenSnapshot[old:f.pos], nil -} - -func (f *memFile) Seek(offset int64, whence int) (int64, error) { - f.n.mu.Lock() - defer f.n.mu.Unlock() - npos := f.pos - // TODO: How to handle offsets greater than the size of system int? - switch whence { - case os.SEEK_SET: - npos = int(offset) - case os.SEEK_CUR: - npos += int(offset) - case os.SEEK_END: - npos = len(f.n.data) + int(offset) - default: - npos = -1 - } - if npos < 0 { - return 0, os.ErrInvalid - } - f.pos = npos - return int64(f.pos), nil -} - -func (f *memFile) Stat() (os.FileInfo, error) { - return f.n.stat(f.nameSnapshot), nil -} - -func (f *memFile) Write(p []byte) (int, error) { - lenp := len(p) - f.n.mu.Lock() - defer f.n.mu.Unlock() - - if f.n.mode.IsDir() { - return 0, os.ErrInvalid - } - if f.pos < len(f.n.data) { - n := copy(f.n.data[f.pos:], p) - f.pos += n - p = p[n:] - } else if f.pos > len(f.n.data) { - // Write permits the creation of holes, if we've seek'ed past the - // existing end of file. - if f.pos <= cap(f.n.data) { - oldLen := len(f.n.data) - f.n.data = f.n.data[:f.pos] - hole := f.n.data[oldLen:] - for i := range hole { - hole[i] = 0 - } - } else { - d := make([]byte, f.pos, f.pos+len(p)) - copy(d, f.n.data) - f.n.data = d - } - } - - if len(p) > 0 { - // We should only get here if f.pos == len(f.n.data). - f.n.data = append(f.n.data, p...) - f.pos = len(f.n.data) - } - f.n.modTime = time.Now() - return lenp, nil -} - -// moveFiles moves files and/or directories from src to dst. -// -// See section 9.9.4 for when various HTTP status codes apply. -func moveFiles(ctx context.Context, fs FileSystem, src, dst string, overwrite bool) (status int, err error) { - created := false - if _, err := fs.Stat(ctx, dst); err != nil { - if !os.IsNotExist(err) { - return http.StatusForbidden, err - } - created = true - } else if overwrite { - // Section 9.9.3 says that "If a resource exists at the destination - // and the Overwrite header is "T", then prior to performing the move, - // the server must perform a DELETE with "Depth: infinity" on the - // destination resource. - if err := fs.RemoveAll(ctx, dst); err != nil { - return http.StatusForbidden, err - } - } else { - return http.StatusPreconditionFailed, os.ErrExist - } - if err := fs.Rename(ctx, src, dst); err != nil { - return http.StatusForbidden, err - } - if created { - return http.StatusCreated, nil - } - return http.StatusNoContent, nil -} - -func copyProps(dst, src File) error { - d, ok := dst.(DeadPropsHolder) - if !ok { - return nil - } - s, ok := src.(DeadPropsHolder) - if !ok { - return nil - } - m, err := s.DeadProps() - if err != nil { - return err - } - props := make([]Property, 0, len(m)) - for _, prop := range m { - props = append(props, prop) - } - _, err = d.Patch([]Proppatch{{Props: props}}) - return err -} - -// copyFiles copies files and/or directories from src to dst. -// -// See section 9.8.5 for when various HTTP status codes apply. -func copyFiles(ctx context.Context, fs FileSystem, src, dst string, overwrite bool, depth int, recursion int) (status int, err error) { - if recursion == 1000 { - return http.StatusInternalServerError, errRecursionTooDeep - } - recursion++ - - // TODO: section 9.8.3 says that "Note that an infinite-depth COPY of /A/ - // into /A/B/ could lead to infinite recursion if not handled correctly." - - srcFile, err := fs.OpenFile(ctx, src, os.O_RDONLY, 0) - if err != nil { - if os.IsNotExist(err) { - return http.StatusNotFound, err - } - return http.StatusInternalServerError, err - } - defer srcFile.Close() - srcStat, err := srcFile.Stat() - if err != nil { - if os.IsNotExist(err) { - return http.StatusNotFound, err - } - return http.StatusInternalServerError, err - } - srcPerm := srcStat.Mode() & os.ModePerm - - created := false - if _, err := fs.Stat(ctx, dst); err != nil { - if os.IsNotExist(err) { - created = true - } else { - return http.StatusForbidden, err - } - } else { - if !overwrite { - return http.StatusPreconditionFailed, os.ErrExist - } - if err := fs.RemoveAll(ctx, dst); err != nil && !os.IsNotExist(err) { - return http.StatusForbidden, err - } - } - - if srcStat.IsDir() { - if err := fs.Mkdir(ctx, dst, srcPerm); err != nil { - return http.StatusForbidden, err - } - if depth == infiniteDepth { - children, err := srcFile.Readdir(-1) - if err != nil { - return http.StatusForbidden, err - } - for _, c := range children { - name := c.Name() - s := path.Join(src, name) - d := path.Join(dst, name) - cStatus, cErr := copyFiles(ctx, fs, s, d, overwrite, depth, recursion) - if cErr != nil { - // TODO: MultiStatus. - return cStatus, cErr - } - } - } - - } else { - dstFile, err := fs.OpenFile(ctx, dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, srcPerm) - if err != nil { - if os.IsNotExist(err) { - return http.StatusConflict, err - } - return http.StatusForbidden, err - - } - _, copyErr := io.Copy(dstFile, srcFile) - propsErr := copyProps(dstFile, srcFile) - closeErr := dstFile.Close() - if copyErr != nil { - return http.StatusInternalServerError, copyErr - } - if propsErr != nil { - return http.StatusInternalServerError, propsErr - } - if closeErr != nil { - return http.StatusInternalServerError, closeErr - } - } - - if created { - return http.StatusCreated, nil - } - return http.StatusNoContent, nil -} - -// walkFS traverses filesystem fs starting at name up to depth levels. -// -// Allowed values for depth are 0, 1 or infiniteDepth. For each visited node, -// walkFS calls walkFn. If a visited file system node is a directory and -// walkFn returns filepath.SkipDir, walkFS will skip traversal of this node. -func walkFS(ctx context.Context, fs FileSystem, depth int, name string, info os.FileInfo, walkFn filepath.WalkFunc) error { - // This implementation is based on Walk's code in the standard path/filepath package. - err := walkFn(name, info, nil) - if err != nil { - if info.IsDir() && err == filepath.SkipDir { - return nil - } - return err - } - if !info.IsDir() || depth == 0 { - return nil - } - if depth == 1 { - depth = 0 - } - - // Read directory names. - f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0) - if err != nil { - return walkFn(name, info, err) - } - fileInfos, err := f.Readdir(0) - f.Close() - if err != nil { - return walkFn(name, info, err) - } - - for _, fileInfo := range fileInfos { - filename := path.Join(name, fileInfo.Name()) - fileInfo, err := fs.Stat(ctx, filename) - if err != nil { - if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { - return err - } - } else { - err = walkFS(ctx, fs, depth, filename, fileInfo, walkFn) - if err != nil { - if !fileInfo.IsDir() || err != filepath.SkipDir { - return err - } - } - } - } - return nil -} diff --git a/vendor/golang.org/x/net/webdav/file_go1.6.go b/vendor/golang.org/x/net/webdav/file_go1.6.go deleted file mode 100644 index fa387700d1b..00000000000 --- a/vendor/golang.org/x/net/webdav/file_go1.6.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 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 !go1.7 - -package webdav - -import ( - "net/http" - - "golang.org/x/net/context" -) - -func getContext(r *http.Request) context.Context { - return context.Background() -} diff --git a/vendor/golang.org/x/net/webdav/file_go1.7.go b/vendor/golang.org/x/net/webdav/file_go1.7.go deleted file mode 100644 index d1c3de83278..00000000000 --- a/vendor/golang.org/x/net/webdav/file_go1.7.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2016 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 go1.7 - -package webdav - -import ( - "context" - "net/http" -) - -func getContext(r *http.Request) context.Context { - return r.Context() -} diff --git a/vendor/golang.org/x/net/webdav/if.go b/vendor/golang.org/x/net/webdav/if.go deleted file mode 100644 index 416e81cdfdd..00000000000 --- a/vendor/golang.org/x/net/webdav/if.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2014 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 webdav - -// The If header is covered by Section 10.4. -// http://www.webdav.org/specs/rfc4918.html#HEADER_If - -import ( - "strings" -) - -// ifHeader is a disjunction (OR) of ifLists. -type ifHeader struct { - lists []ifList -} - -// ifList is a conjunction (AND) of Conditions, and an optional resource tag. -type ifList struct { - resourceTag string - conditions []Condition -} - -// parseIfHeader parses the "If: foo bar" HTTP header. The httpHeader string -// should omit the "If:" prefix and have any "\r\n"s collapsed to a " ", as is -// returned by req.Header.Get("If") for a http.Request req. -func parseIfHeader(httpHeader string) (h ifHeader, ok bool) { - s := strings.TrimSpace(httpHeader) - switch tokenType, _, _ := lex(s); tokenType { - case '(': - return parseNoTagLists(s) - case angleTokenType: - return parseTaggedLists(s) - default: - return ifHeader{}, false - } -} - -func parseNoTagLists(s string) (h ifHeader, ok bool) { - for { - l, remaining, ok := parseList(s) - if !ok { - return ifHeader{}, false - } - h.lists = append(h.lists, l) - if remaining == "" { - return h, true - } - s = remaining - } -} - -func parseTaggedLists(s string) (h ifHeader, ok bool) { - resourceTag, n := "", 0 - for first := true; ; first = false { - tokenType, tokenStr, remaining := lex(s) - switch tokenType { - case angleTokenType: - if !first && n == 0 { - return ifHeader{}, false - } - resourceTag, n = tokenStr, 0 - s = remaining - case '(': - n++ - l, remaining, ok := parseList(s) - if !ok { - return ifHeader{}, false - } - l.resourceTag = resourceTag - h.lists = append(h.lists, l) - if remaining == "" { - return h, true - } - s = remaining - default: - return ifHeader{}, false - } - } -} - -func parseList(s string) (l ifList, remaining string, ok bool) { - tokenType, _, s := lex(s) - if tokenType != '(' { - return ifList{}, "", false - } - for { - tokenType, _, remaining = lex(s) - if tokenType == ')' { - if len(l.conditions) == 0 { - return ifList{}, "", false - } - return l, remaining, true - } - c, remaining, ok := parseCondition(s) - if !ok { - return ifList{}, "", false - } - l.conditions = append(l.conditions, c) - s = remaining - } -} - -func parseCondition(s string) (c Condition, remaining string, ok bool) { - tokenType, tokenStr, s := lex(s) - if tokenType == notTokenType { - c.Not = true - tokenType, tokenStr, s = lex(s) - } - switch tokenType { - case strTokenType, angleTokenType: - c.Token = tokenStr - case squareTokenType: - c.ETag = tokenStr - default: - return Condition{}, "", false - } - return c, s, true -} - -// Single-rune tokens like '(' or ')' have a token type equal to their rune. -// All other tokens have a negative token type. -const ( - errTokenType = rune(-1) - eofTokenType = rune(-2) - strTokenType = rune(-3) - notTokenType = rune(-4) - angleTokenType = rune(-5) - squareTokenType = rune(-6) -) - -func lex(s string) (tokenType rune, tokenStr string, remaining string) { - // The net/textproto Reader that parses the HTTP header will collapse - // Linear White Space that spans multiple "\r\n" lines to a single " ", - // so we don't need to look for '\r' or '\n'. - for len(s) > 0 && (s[0] == '\t' || s[0] == ' ') { - s = s[1:] - } - if len(s) == 0 { - return eofTokenType, "", "" - } - i := 0 -loop: - for ; i < len(s); i++ { - switch s[i] { - case '\t', ' ', '(', ')', '<', '>', '[', ']': - break loop - } - } - - if i != 0 { - tokenStr, remaining = s[:i], s[i:] - if tokenStr == "Not" { - return notTokenType, "", remaining - } - return strTokenType, tokenStr, remaining - } - - j := 0 - switch s[0] { - case '<': - j, tokenType = strings.IndexByte(s, '>'), angleTokenType - case '[': - j, tokenType = strings.IndexByte(s, ']'), squareTokenType - default: - return rune(s[0]), "", s[1:] - } - if j < 0 { - return errTokenType, "", "" - } - return tokenType, s[1:j], s[j+1:] -} diff --git a/vendor/golang.org/x/net/webdav/internal/xml/README b/vendor/golang.org/x/net/webdav/internal/xml/README deleted file mode 100644 index 89656f48962..00000000000 --- a/vendor/golang.org/x/net/webdav/internal/xml/README +++ /dev/null @@ -1,11 +0,0 @@ -This is a fork of the encoding/xml package at ca1d6c4, the last commit before -https://go.googlesource.com/go/+/c0d6d33 "encoding/xml: restore Go 1.4 name -space behavior" made late in the lead-up to the Go 1.5 release. - -The list of encoding/xml changes is at -https://go.googlesource.com/go/+log/master/src/encoding/xml - -This fork is temporary, and I (nigeltao) expect to revert it after Go 1.6 is -released. - -See http://golang.org/issue/11841 diff --git a/vendor/golang.org/x/net/webdav/internal/xml/marshal.go b/vendor/golang.org/x/net/webdav/internal/xml/marshal.go deleted file mode 100644 index cb82ec21434..00000000000 --- a/vendor/golang.org/x/net/webdav/internal/xml/marshal.go +++ /dev/null @@ -1,1223 +0,0 @@ -// Copyright 2011 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 xml - -import ( - "bufio" - "bytes" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "strings" -) - -const ( - // A generic XML header suitable for use with the output of Marshal. - // This is not automatically added to any output of this package, - // it is provided as a convenience. - Header = `` + "\n" -) - -// Marshal returns the XML encoding of v. -// -// Marshal handles an array or slice by marshalling each of the elements. -// Marshal handles a pointer by marshalling the value it points at or, if the -// pointer is nil, by writing nothing. Marshal handles an interface value by -// marshalling the value it contains or, if the interface value is nil, by -// writing nothing. Marshal handles all other data by writing one or more XML -// elements containing the data. -// -// The name for the XML elements is taken from, in order of preference: -// - the tag on the XMLName field, if the data is a struct -// - the value of the XMLName field of type xml.Name -// - the tag of the struct field used to obtain the data -// - the name of the struct field used to obtain the data -// - the name of the marshalled type -// -// The XML element for a struct contains marshalled elements for each of the -// exported fields of the struct, with these exceptions: -// - the XMLName field, described above, is omitted. -// - a field with tag "-" is omitted. -// - a field with tag "name,attr" becomes an attribute with -// the given name in the XML element. -// - a field with tag ",attr" becomes an attribute with the -// field name in the XML element. -// - a field with tag ",chardata" is written as character data, -// not as an XML element. -// - a field with tag ",innerxml" is written verbatim, not subject -// to the usual marshalling procedure. -// - a field with tag ",comment" is written as an XML comment, not -// subject to the usual marshalling procedure. It must not contain -// the "--" string within it. -// - a field with a tag including the "omitempty" option is omitted -// if the field value is empty. The empty values are false, 0, any -// nil pointer or interface value, and any array, slice, map, or -// string of length zero. -// - an anonymous struct field is handled as if the fields of its -// value were part of the outer struct. -// -// If a field uses a tag "a>b>c", then the element c will be nested inside -// parent elements a and b. Fields that appear next to each other that name -// the same parent will be enclosed in one XML element. -// -// See MarshalIndent for an example. -// -// Marshal will return an error if asked to marshal a channel, function, or map. -func Marshal(v interface{}) ([]byte, error) { - var b bytes.Buffer - if err := NewEncoder(&b).Encode(v); err != nil { - return nil, err - } - return b.Bytes(), nil -} - -// Marshaler is the interface implemented by objects that can marshal -// themselves into valid XML elements. -// -// MarshalXML encodes the receiver as zero or more XML elements. -// By convention, arrays or slices are typically encoded as a sequence -// of elements, one per entry. -// Using start as the element tag is not required, but doing so -// will enable Unmarshal to match the XML elements to the correct -// struct field. -// One common implementation strategy is to construct a separate -// value with a layout corresponding to the desired XML and then -// to encode it using e.EncodeElement. -// Another common strategy is to use repeated calls to e.EncodeToken -// to generate the XML output one token at a time. -// The sequence of encoded tokens must make up zero or more valid -// XML elements. -type Marshaler interface { - MarshalXML(e *Encoder, start StartElement) error -} - -// MarshalerAttr is the interface implemented by objects that can marshal -// themselves into valid XML attributes. -// -// MarshalXMLAttr returns an XML attribute with the encoded value of the receiver. -// Using name as the attribute name is not required, but doing so -// will enable Unmarshal to match the attribute to the correct -// struct field. -// If MarshalXMLAttr returns the zero attribute Attr{}, no attribute -// will be generated in the output. -// MarshalXMLAttr is used only for struct fields with the -// "attr" option in the field tag. -type MarshalerAttr interface { - MarshalXMLAttr(name Name) (Attr, error) -} - -// MarshalIndent works like Marshal, but each XML element begins on a new -// indented line that starts with prefix and is followed by one or more -// copies of indent according to the nesting depth. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { - var b bytes.Buffer - enc := NewEncoder(&b) - enc.Indent(prefix, indent) - if err := enc.Encode(v); err != nil { - return nil, err - } - return b.Bytes(), nil -} - -// An Encoder writes XML data to an output stream. -type Encoder struct { - p printer -} - -// NewEncoder returns a new encoder that writes to w. -func NewEncoder(w io.Writer) *Encoder { - e := &Encoder{printer{Writer: bufio.NewWriter(w)}} - e.p.encoder = e - return e -} - -// Indent sets the encoder to generate XML in which each element -// begins on a new indented line that starts with prefix and is followed by -// one or more copies of indent according to the nesting depth. -func (enc *Encoder) Indent(prefix, indent string) { - enc.p.prefix = prefix - enc.p.indent = indent -} - -// Encode writes the XML encoding of v to the stream. -// -// See the documentation for Marshal for details about the conversion -// of Go values to XML. -// -// Encode calls Flush before returning. -func (enc *Encoder) Encode(v interface{}) error { - err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil) - if err != nil { - return err - } - return enc.p.Flush() -} - -// EncodeElement writes the XML encoding of v to the stream, -// using start as the outermost tag in the encoding. -// -// See the documentation for Marshal for details about the conversion -// of Go values to XML. -// -// EncodeElement calls Flush before returning. -func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error { - err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start) - if err != nil { - return err - } - return enc.p.Flush() -} - -var ( - begComment = []byte("") - endProcInst = []byte("?>") - endDirective = []byte(">") -) - -// EncodeToken writes the given XML token to the stream. -// It returns an error if StartElement and EndElement tokens are not -// properly matched. -// -// EncodeToken does not call Flush, because usually it is part of a -// larger operation such as Encode or EncodeElement (or a custom -// Marshaler's MarshalXML invoked during those), and those will call -// Flush when finished. Callers that create an Encoder and then invoke -// EncodeToken directly, without using Encode or EncodeElement, need to -// call Flush when finished to ensure that the XML is written to the -// underlying writer. -// -// EncodeToken allows writing a ProcInst with Target set to "xml" only -// as the first token in the stream. -// -// When encoding a StartElement holding an XML namespace prefix -// declaration for a prefix that is not already declared, contained -// elements (including the StartElement itself) will use the declared -// prefix when encoding names with matching namespace URIs. -func (enc *Encoder) EncodeToken(t Token) error { - - p := &enc.p - switch t := t.(type) { - case StartElement: - if err := p.writeStart(&t); err != nil { - return err - } - case EndElement: - if err := p.writeEnd(t.Name); err != nil { - return err - } - case CharData: - escapeText(p, t, false) - case Comment: - if bytes.Contains(t, endComment) { - return fmt.Errorf("xml: EncodeToken of Comment containing --> marker") - } - p.WriteString("") - return p.cachedWriteError() - case ProcInst: - // First token to be encoded which is also a ProcInst with target of xml - // is the xml declaration. The only ProcInst where target of xml is allowed. - if t.Target == "xml" && p.Buffered() != 0 { - return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded") - } - if !isNameString(t.Target) { - return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target") - } - if bytes.Contains(t.Inst, endProcInst) { - return fmt.Errorf("xml: EncodeToken of ProcInst containing ?> marker") - } - p.WriteString(" 0 { - p.WriteByte(' ') - p.Write(t.Inst) - } - p.WriteString("?>") - case Directive: - if !isValidDirective(t) { - return fmt.Errorf("xml: EncodeToken of Directive containing wrong < or > markers") - } - p.WriteString("") - default: - return fmt.Errorf("xml: EncodeToken of invalid token type") - - } - return p.cachedWriteError() -} - -// isValidDirective reports whether dir is a valid directive text, -// meaning angle brackets are matched, ignoring comments and strings. -func isValidDirective(dir Directive) bool { - var ( - depth int - inquote uint8 - incomment bool - ) - for i, c := range dir { - switch { - case incomment: - if c == '>' { - if n := 1 + i - len(endComment); n >= 0 && bytes.Equal(dir[n:i+1], endComment) { - incomment = false - } - } - // Just ignore anything in comment - case inquote != 0: - if c == inquote { - inquote = 0 - } - // Just ignore anything within quotes - case c == '\'' || c == '"': - inquote = c - case c == '<': - if i+len(begComment) < len(dir) && bytes.Equal(dir[i:i+len(begComment)], begComment) { - incomment = true - } else { - depth++ - } - case c == '>': - if depth == 0 { - return false - } - depth-- - } - } - return depth == 0 && inquote == 0 && !incomment -} - -// Flush flushes any buffered XML to the underlying writer. -// See the EncodeToken documentation for details about when it is necessary. -func (enc *Encoder) Flush() error { - return enc.p.Flush() -} - -type printer struct { - *bufio.Writer - encoder *Encoder - seq int - indent string - prefix string - depth int - indentedIn bool - putNewline bool - defaultNS string - attrNS map[string]string // map prefix -> name space - attrPrefix map[string]string // map name space -> prefix - prefixes []printerPrefix - tags []Name -} - -// printerPrefix holds a namespace undo record. -// When an element is popped, the prefix record -// is set back to the recorded URL. The empty -// prefix records the URL for the default name space. -// -// The start of an element is recorded with an element -// that has mark=true. -type printerPrefix struct { - prefix string - url string - mark bool -} - -func (p *printer) prefixForNS(url string, isAttr bool) string { - // The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml" - // and must be referred to that way. - // (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns", - // but users should not be trying to use that one directly - that's our job.) - if url == xmlURL { - return "xml" - } - if !isAttr && url == p.defaultNS { - // We can use the default name space. - return "" - } - return p.attrPrefix[url] -} - -// defineNS pushes any namespace definition found in the given attribute. -// If ignoreNonEmptyDefault is true, an xmlns="nonempty" -// attribute will be ignored. -func (p *printer) defineNS(attr Attr, ignoreNonEmptyDefault bool) error { - var prefix string - if attr.Name.Local == "xmlns" { - if attr.Name.Space != "" && attr.Name.Space != "xml" && attr.Name.Space != xmlURL { - return fmt.Errorf("xml: cannot redefine xmlns attribute prefix") - } - } else if attr.Name.Space == "xmlns" && attr.Name.Local != "" { - prefix = attr.Name.Local - if attr.Value == "" { - // Technically, an empty XML namespace is allowed for an attribute. - // From http://www.w3.org/TR/xml-names11/#scoping-defaulting: - // - // The attribute value in a namespace declaration for a prefix may be - // empty. This has the effect, within the scope of the declaration, of removing - // any association of the prefix with a namespace name. - // - // However our namespace prefixes here are used only as hints. There's - // no need to respect the removal of a namespace prefix, so we ignore it. - return nil - } - } else { - // Ignore: it's not a namespace definition - return nil - } - if prefix == "" { - if attr.Value == p.defaultNS { - // No need for redefinition. - return nil - } - if attr.Value != "" && ignoreNonEmptyDefault { - // We have an xmlns="..." value but - // it can't define a name space in this context, - // probably because the element has an empty - // name space. In this case, we just ignore - // the name space declaration. - return nil - } - } else if _, ok := p.attrPrefix[attr.Value]; ok { - // There's already a prefix for the given name space, - // so use that. This prevents us from - // having two prefixes for the same name space - // so attrNS and attrPrefix can remain bijective. - return nil - } - p.pushPrefix(prefix, attr.Value) - return nil -} - -// createNSPrefix creates a name space prefix attribute -// to use for the given name space, defining a new prefix -// if necessary. -// If isAttr is true, the prefix is to be created for an attribute -// prefix, which means that the default name space cannot -// be used. -func (p *printer) createNSPrefix(url string, isAttr bool) { - if _, ok := p.attrPrefix[url]; ok { - // We already have a prefix for the given URL. - return - } - switch { - case !isAttr && url == p.defaultNS: - // We can use the default name space. - return - case url == "": - // The only way we can encode names in the empty - // name space is by using the default name space, - // so we must use that. - if p.defaultNS != "" { - // The default namespace is non-empty, so we - // need to set it to empty. - p.pushPrefix("", "") - } - return - case url == xmlURL: - return - } - // TODO If the URL is an existing prefix, we could - // use it as is. That would enable the - // marshaling of elements that had been unmarshaled - // and with a name space prefix that was not found. - // although technically it would be incorrect. - - // Pick a name. We try to use the final element of the path - // but fall back to _. - prefix := strings.TrimRight(url, "/") - if i := strings.LastIndex(prefix, "/"); i >= 0 { - prefix = prefix[i+1:] - } - if prefix == "" || !isName([]byte(prefix)) || strings.Contains(prefix, ":") { - prefix = "_" - } - if strings.HasPrefix(prefix, "xml") { - // xmlanything is reserved. - prefix = "_" + prefix - } - if p.attrNS[prefix] != "" { - // Name is taken. Find a better one. - for p.seq++; ; p.seq++ { - if id := prefix + "_" + strconv.Itoa(p.seq); p.attrNS[id] == "" { - prefix = id - break - } - } - } - - p.pushPrefix(prefix, url) -} - -// writeNamespaces writes xmlns attributes for all the -// namespace prefixes that have been defined in -// the current element. -func (p *printer) writeNamespaces() { - for i := len(p.prefixes) - 1; i >= 0; i-- { - prefix := p.prefixes[i] - if prefix.mark { - return - } - p.WriteString(" ") - if prefix.prefix == "" { - // Default name space. - p.WriteString(`xmlns="`) - } else { - p.WriteString("xmlns:") - p.WriteString(prefix.prefix) - p.WriteString(`="`) - } - EscapeText(p, []byte(p.nsForPrefix(prefix.prefix))) - p.WriteString(`"`) - } -} - -// pushPrefix pushes a new prefix on the prefix stack -// without checking to see if it is already defined. -func (p *printer) pushPrefix(prefix, url string) { - p.prefixes = append(p.prefixes, printerPrefix{ - prefix: prefix, - url: p.nsForPrefix(prefix), - }) - p.setAttrPrefix(prefix, url) -} - -// nsForPrefix returns the name space for the given -// prefix. Note that this is not valid for the -// empty attribute prefix, which always has an empty -// name space. -func (p *printer) nsForPrefix(prefix string) string { - if prefix == "" { - return p.defaultNS - } - return p.attrNS[prefix] -} - -// markPrefix marks the start of an element on the prefix -// stack. -func (p *printer) markPrefix() { - p.prefixes = append(p.prefixes, printerPrefix{ - mark: true, - }) -} - -// popPrefix pops all defined prefixes for the current -// element. -func (p *printer) popPrefix() { - for len(p.prefixes) > 0 { - prefix := p.prefixes[len(p.prefixes)-1] - p.prefixes = p.prefixes[:len(p.prefixes)-1] - if prefix.mark { - break - } - p.setAttrPrefix(prefix.prefix, prefix.url) - } -} - -// setAttrPrefix sets an attribute name space prefix. -// If url is empty, the attribute is removed. -// If prefix is empty, the default name space is set. -func (p *printer) setAttrPrefix(prefix, url string) { - if prefix == "" { - p.defaultNS = url - return - } - if url == "" { - delete(p.attrPrefix, p.attrNS[prefix]) - delete(p.attrNS, prefix) - return - } - if p.attrPrefix == nil { - // Need to define a new name space. - p.attrPrefix = make(map[string]string) - p.attrNS = make(map[string]string) - } - // Remove any old prefix value. This is OK because we maintain a - // strict one-to-one mapping between prefix and URL (see - // defineNS) - delete(p.attrPrefix, p.attrNS[prefix]) - p.attrPrefix[url] = prefix - p.attrNS[prefix] = url -} - -var ( - marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - marshalerAttrType = reflect.TypeOf((*MarshalerAttr)(nil)).Elem() - textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() -) - -// marshalValue writes one or more XML elements representing val. -// If val was obtained from a struct field, finfo must have its details. -func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error { - if startTemplate != nil && startTemplate.Name.Local == "" { - return fmt.Errorf("xml: EncodeElement of StartElement with missing name") - } - - if !val.IsValid() { - return nil - } - if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) { - return nil - } - - // Drill into interfaces and pointers. - // This can turn into an infinite loop given a cyclic chain, - // but it matches the Go 1 behavior. - for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr { - if val.IsNil() { - return nil - } - val = val.Elem() - } - - kind := val.Kind() - typ := val.Type() - - // Check for marshaler. - if val.CanInterface() && typ.Implements(marshalerType) { - return p.marshalInterface(val.Interface().(Marshaler), p.defaultStart(typ, finfo, startTemplate)) - } - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(marshalerType) { - return p.marshalInterface(pv.Interface().(Marshaler), p.defaultStart(pv.Type(), finfo, startTemplate)) - } - } - - // Check for text marshaler. - if val.CanInterface() && typ.Implements(textMarshalerType) { - return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), p.defaultStart(typ, finfo, startTemplate)) - } - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(textMarshalerType) { - return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), p.defaultStart(pv.Type(), finfo, startTemplate)) - } - } - - // Slices and arrays iterate over the elements. They do not have an enclosing tag. - if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 { - for i, n := 0, val.Len(); i < n; i++ { - if err := p.marshalValue(val.Index(i), finfo, startTemplate); err != nil { - return err - } - } - return nil - } - - tinfo, err := getTypeInfo(typ) - if err != nil { - return err - } - - // Create start element. - // Precedence for the XML element name is: - // 0. startTemplate - // 1. XMLName field in underlying struct; - // 2. field name/tag in the struct field; and - // 3. type name - var start StartElement - - // explicitNS records whether the element's name space has been - // explicitly set (for example an XMLName field). - explicitNS := false - - if startTemplate != nil { - start.Name = startTemplate.Name - explicitNS = true - start.Attr = append(start.Attr, startTemplate.Attr...) - } else if tinfo.xmlname != nil { - xmlname := tinfo.xmlname - if xmlname.name != "" { - start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name - } else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" { - start.Name = v - } - explicitNS = true - } - if start.Name.Local == "" && finfo != nil { - start.Name.Local = finfo.name - if finfo.xmlns != "" { - start.Name.Space = finfo.xmlns - explicitNS = true - } - } - if start.Name.Local == "" { - name := typ.Name() - if name == "" { - return &UnsupportedTypeError{typ} - } - start.Name.Local = name - } - - // defaultNS records the default name space as set by a xmlns="..." - // attribute. We don't set p.defaultNS because we want to let - // the attribute writing code (in p.defineNS) be solely responsible - // for maintaining that. - defaultNS := p.defaultNS - - // Attributes - for i := range tinfo.fields { - finfo := &tinfo.fields[i] - if finfo.flags&fAttr == 0 { - continue - } - attr, err := p.fieldAttr(finfo, val) - if err != nil { - return err - } - if attr.Name.Local == "" { - continue - } - start.Attr = append(start.Attr, attr) - if attr.Name.Space == "" && attr.Name.Local == "xmlns" { - defaultNS = attr.Value - } - } - if !explicitNS { - // Historic behavior: elements use the default name space - // they are contained in by default. - start.Name.Space = defaultNS - } - // Historic behaviour: an element that's in a namespace sets - // the default namespace for all elements contained within it. - start.setDefaultNamespace() - - if err := p.writeStart(&start); err != nil { - return err - } - - if val.Kind() == reflect.Struct { - err = p.marshalStruct(tinfo, val) - } else { - s, b, err1 := p.marshalSimple(typ, val) - if err1 != nil { - err = err1 - } else if b != nil { - EscapeText(p, b) - } else { - p.EscapeString(s) - } - } - if err != nil { - return err - } - - if err := p.writeEnd(start.Name); err != nil { - return err - } - - return p.cachedWriteError() -} - -// fieldAttr returns the attribute of the given field. -// If the returned attribute has an empty Name.Local, -// it should not be used. -// The given value holds the value containing the field. -func (p *printer) fieldAttr(finfo *fieldInfo, val reflect.Value) (Attr, error) { - fv := finfo.value(val) - name := Name{Space: finfo.xmlns, Local: finfo.name} - if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) { - return Attr{}, nil - } - if fv.Kind() == reflect.Interface && fv.IsNil() { - return Attr{}, nil - } - if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) { - attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name) - return attr, err - } - if fv.CanAddr() { - pv := fv.Addr() - if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) { - attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name) - return attr, err - } - } - if fv.CanInterface() && fv.Type().Implements(textMarshalerType) { - text, err := fv.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return Attr{}, err - } - return Attr{name, string(text)}, nil - } - if fv.CanAddr() { - pv := fv.Addr() - if pv.CanInterface() && pv.Type().Implements(textMarshalerType) { - text, err := pv.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return Attr{}, err - } - return Attr{name, string(text)}, nil - } - } - // Dereference or skip nil pointer, interface values. - switch fv.Kind() { - case reflect.Ptr, reflect.Interface: - if fv.IsNil() { - return Attr{}, nil - } - fv = fv.Elem() - } - s, b, err := p.marshalSimple(fv.Type(), fv) - if err != nil { - return Attr{}, err - } - if b != nil { - s = string(b) - } - return Attr{name, s}, nil -} - -// defaultStart returns the default start element to use, -// given the reflect type, field info, and start template. -func (p *printer) defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement { - var start StartElement - // Precedence for the XML element name is as above, - // except that we do not look inside structs for the first field. - if startTemplate != nil { - start.Name = startTemplate.Name - start.Attr = append(start.Attr, startTemplate.Attr...) - } else if finfo != nil && finfo.name != "" { - start.Name.Local = finfo.name - start.Name.Space = finfo.xmlns - } else if typ.Name() != "" { - start.Name.Local = typ.Name() - } else { - // Must be a pointer to a named type, - // since it has the Marshaler methods. - start.Name.Local = typ.Elem().Name() - } - // Historic behaviour: elements use the name space of - // the element they are contained in by default. - if start.Name.Space == "" { - start.Name.Space = p.defaultNS - } - start.setDefaultNamespace() - return start -} - -// marshalInterface marshals a Marshaler interface value. -func (p *printer) marshalInterface(val Marshaler, start StartElement) error { - // Push a marker onto the tag stack so that MarshalXML - // cannot close the XML tags that it did not open. - p.tags = append(p.tags, Name{}) - n := len(p.tags) - - err := val.MarshalXML(p.encoder, start) - if err != nil { - return err - } - - // Make sure MarshalXML closed all its tags. p.tags[n-1] is the mark. - if len(p.tags) > n { - return fmt.Errorf("xml: %s.MarshalXML wrote invalid XML: <%s> not closed", receiverType(val), p.tags[len(p.tags)-1].Local) - } - p.tags = p.tags[:n-1] - return nil -} - -// marshalTextInterface marshals a TextMarshaler interface value. -func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartElement) error { - if err := p.writeStart(&start); err != nil { - return err - } - text, err := val.MarshalText() - if err != nil { - return err - } - EscapeText(p, text) - return p.writeEnd(start.Name) -} - -// writeStart writes the given start element. -func (p *printer) writeStart(start *StartElement) error { - if start.Name.Local == "" { - return fmt.Errorf("xml: start tag with no name") - } - - p.tags = append(p.tags, start.Name) - p.markPrefix() - // Define any name spaces explicitly declared in the attributes. - // We do this as a separate pass so that explicitly declared prefixes - // will take precedence over implicitly declared prefixes - // regardless of the order of the attributes. - ignoreNonEmptyDefault := start.Name.Space == "" - for _, attr := range start.Attr { - if err := p.defineNS(attr, ignoreNonEmptyDefault); err != nil { - return err - } - } - // Define any new name spaces implied by the attributes. - for _, attr := range start.Attr { - name := attr.Name - // From http://www.w3.org/TR/xml-names11/#defaulting - // "Default namespace declarations do not apply directly - // to attribute names; the interpretation of unprefixed - // attributes is determined by the element on which they - // appear." - // This means we don't need to create a new namespace - // when an attribute name space is empty. - if name.Space != "" && !name.isNamespace() { - p.createNSPrefix(name.Space, true) - } - } - p.createNSPrefix(start.Name.Space, false) - - p.writeIndent(1) - p.WriteByte('<') - p.writeName(start.Name, false) - p.writeNamespaces() - for _, attr := range start.Attr { - name := attr.Name - if name.Local == "" || name.isNamespace() { - // Namespaces have already been written by writeNamespaces above. - continue - } - p.WriteByte(' ') - p.writeName(name, true) - p.WriteString(`="`) - p.EscapeString(attr.Value) - p.WriteByte('"') - } - p.WriteByte('>') - return nil -} - -// writeName writes the given name. It assumes -// that p.createNSPrefix(name) has already been called. -func (p *printer) writeName(name Name, isAttr bool) { - if prefix := p.prefixForNS(name.Space, isAttr); prefix != "" { - p.WriteString(prefix) - p.WriteByte(':') - } - p.WriteString(name.Local) -} - -func (p *printer) writeEnd(name Name) error { - if name.Local == "" { - return fmt.Errorf("xml: end tag with no name") - } - if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" { - return fmt.Errorf("xml: end tag without start tag", name.Local) - } - if top := p.tags[len(p.tags)-1]; top != name { - if top.Local != name.Local { - return fmt.Errorf("xml: end tag does not match start tag <%s>", name.Local, top.Local) - } - return fmt.Errorf("xml: end tag in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space) - } - p.tags = p.tags[:len(p.tags)-1] - - p.writeIndent(-1) - p.WriteByte('<') - p.WriteByte('/') - p.writeName(name, false) - p.WriteByte('>') - p.popPrefix() - return nil -} - -func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) { - switch val.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return strconv.FormatInt(val.Int(), 10), nil, nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return strconv.FormatUint(val.Uint(), 10), nil, nil - case reflect.Float32, reflect.Float64: - return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil - case reflect.String: - return val.String(), nil, nil - case reflect.Bool: - return strconv.FormatBool(val.Bool()), nil, nil - case reflect.Array: - if typ.Elem().Kind() != reflect.Uint8 { - break - } - // [...]byte - var bytes []byte - if val.CanAddr() { - bytes = val.Slice(0, val.Len()).Bytes() - } else { - bytes = make([]byte, val.Len()) - reflect.Copy(reflect.ValueOf(bytes), val) - } - return "", bytes, nil - case reflect.Slice: - if typ.Elem().Kind() != reflect.Uint8 { - break - } - // []byte - return "", val.Bytes(), nil - } - return "", nil, &UnsupportedTypeError{typ} -} - -var ddBytes = []byte("--") - -func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { - s := parentStack{p: p} - for i := range tinfo.fields { - finfo := &tinfo.fields[i] - if finfo.flags&fAttr != 0 { - continue - } - vf := finfo.value(val) - - // Dereference or skip nil pointer, interface values. - switch vf.Kind() { - case reflect.Ptr, reflect.Interface: - if !vf.IsNil() { - vf = vf.Elem() - } - } - - switch finfo.flags & fMode { - case fCharData: - if err := s.setParents(&noField, reflect.Value{}); err != nil { - return err - } - if vf.CanInterface() && vf.Type().Implements(textMarshalerType) { - data, err := vf.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return err - } - Escape(p, data) - continue - } - if vf.CanAddr() { - pv := vf.Addr() - if pv.CanInterface() && pv.Type().Implements(textMarshalerType) { - data, err := pv.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return err - } - Escape(p, data) - continue - } - } - var scratch [64]byte - switch vf.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10)) - case reflect.Float32, reflect.Float64: - Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits())) - case reflect.Bool: - Escape(p, strconv.AppendBool(scratch[:0], vf.Bool())) - case reflect.String: - if err := EscapeText(p, []byte(vf.String())); err != nil { - return err - } - case reflect.Slice: - if elem, ok := vf.Interface().([]byte); ok { - if err := EscapeText(p, elem); err != nil { - return err - } - } - } - continue - - case fComment: - if err := s.setParents(&noField, reflect.Value{}); err != nil { - return err - } - k := vf.Kind() - if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) { - return fmt.Errorf("xml: bad type for comment field of %s", val.Type()) - } - if vf.Len() == 0 { - continue - } - p.writeIndent(0) - p.WriteString("" is invalid grammar. Make it "- -->" - p.WriteByte(' ') - } - p.WriteString("-->") - continue - - case fInnerXml: - iface := vf.Interface() - switch raw := iface.(type) { - case []byte: - p.Write(raw) - continue - case string: - p.WriteString(raw) - continue - } - - case fElement, fElement | fAny: - if err := s.setParents(finfo, vf); err != nil { - return err - } - } - if err := p.marshalValue(vf, finfo, nil); err != nil { - return err - } - } - if err := s.setParents(&noField, reflect.Value{}); err != nil { - return err - } - return p.cachedWriteError() -} - -var noField fieldInfo - -// return the bufio Writer's cached write error -func (p *printer) cachedWriteError() error { - _, err := p.Write(nil) - return err -} - -func (p *printer) writeIndent(depthDelta int) { - if len(p.prefix) == 0 && len(p.indent) == 0 { - return - } - if depthDelta < 0 { - p.depth-- - if p.indentedIn { - p.indentedIn = false - return - } - p.indentedIn = false - } - if p.putNewline { - p.WriteByte('\n') - } else { - p.putNewline = true - } - if len(p.prefix) > 0 { - p.WriteString(p.prefix) - } - if len(p.indent) > 0 { - for i := 0; i < p.depth; i++ { - p.WriteString(p.indent) - } - } - if depthDelta > 0 { - p.depth++ - p.indentedIn = true - } -} - -type parentStack struct { - p *printer - xmlns string - parents []string -} - -// setParents sets the stack of current parents to those found in finfo. -// It only writes the start elements if vf holds a non-nil value. -// If finfo is &noField, it pops all elements. -func (s *parentStack) setParents(finfo *fieldInfo, vf reflect.Value) error { - xmlns := s.p.defaultNS - if finfo.xmlns != "" { - xmlns = finfo.xmlns - } - commonParents := 0 - if xmlns == s.xmlns { - for ; commonParents < len(finfo.parents) && commonParents < len(s.parents); commonParents++ { - if finfo.parents[commonParents] != s.parents[commonParents] { - break - } - } - } - // Pop off any parents that aren't in common with the previous field. - for i := len(s.parents) - 1; i >= commonParents; i-- { - if err := s.p.writeEnd(Name{ - Space: s.xmlns, - Local: s.parents[i], - }); err != nil { - return err - } - } - s.parents = finfo.parents - s.xmlns = xmlns - if commonParents >= len(s.parents) { - // No new elements to push. - return nil - } - if (vf.Kind() == reflect.Ptr || vf.Kind() == reflect.Interface) && vf.IsNil() { - // The element is nil, so no need for the start elements. - s.parents = s.parents[:commonParents] - return nil - } - // Push any new parents required. - for _, name := range s.parents[commonParents:] { - start := &StartElement{ - Name: Name{ - Space: s.xmlns, - Local: name, - }, - } - // Set the default name space for parent elements - // to match what we do with other elements. - if s.xmlns != s.p.defaultNS { - start.setDefaultNamespace() - } - if err := s.p.writeStart(start); err != nil { - return err - } - } - return nil -} - -// A MarshalXMLError is returned when Marshal encounters a type -// that cannot be converted into XML. -type UnsupportedTypeError struct { - Type reflect.Type -} - -func (e *UnsupportedTypeError) Error() string { - return "xml: unsupported type: " + e.Type.String() -} - -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - 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.Interface, reflect.Ptr: - return v.IsNil() - } - return false -} diff --git a/vendor/golang.org/x/net/webdav/internal/xml/read.go b/vendor/golang.org/x/net/webdav/internal/xml/read.go deleted file mode 100644 index 4089056a1f8..00000000000 --- a/vendor/golang.org/x/net/webdav/internal/xml/read.go +++ /dev/null @@ -1,692 +0,0 @@ -// Copyright 2009 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 xml - -import ( - "bytes" - "encoding" - "errors" - "fmt" - "reflect" - "strconv" - "strings" -) - -// BUG(rsc): Mapping between XML elements and data structures is inherently flawed: -// an XML element is an order-dependent collection of anonymous -// values, while a data structure is an order-independent collection -// of named values. -// See package json for a textual representation more suitable -// to data structures. - -// Unmarshal parses the XML-encoded data and stores the result in -// the value pointed to by v, which must be an arbitrary struct, -// slice, or string. Well-formed data that does not fit into v is -// discarded. -// -// Because Unmarshal uses the reflect package, it can only assign -// to exported (upper case) fields. Unmarshal uses a case-sensitive -// comparison to match XML element names to tag values and struct -// field names. -// -// Unmarshal maps an XML element to a struct using the following rules. -// In the rules, the tag of a field refers to the value associated with the -// key 'xml' in the struct field's tag (see the example above). -// -// * If the struct has a field of type []byte or string with tag -// ",innerxml", Unmarshal accumulates the raw XML nested inside the -// element in that field. The rest of the rules still apply. -// -// * If the struct has a field named XMLName of type xml.Name, -// Unmarshal records the element name in that field. -// -// * If the XMLName field has an associated tag of the form -// "name" or "namespace-URL name", the XML element must have -// the given name (and, optionally, name space) or else Unmarshal -// returns an error. -// -// * If the XML element has an attribute whose name matches a -// struct field name with an associated tag containing ",attr" or -// the explicit name in a struct field tag of the form "name,attr", -// Unmarshal records the attribute value in that field. -// -// * If the XML element contains character data, that data is -// accumulated in the first struct field that has tag ",chardata". -// The struct field may have type []byte or string. -// If there is no such field, the character data is discarded. -// -// * If the XML element contains comments, they are accumulated in -// the first struct field that has tag ",comment". The struct -// field may have type []byte or string. If there is no such -// field, the comments are discarded. -// -// * If the XML element contains a sub-element whose name matches -// the prefix of a tag formatted as "a" or "a>b>c", unmarshal -// will descend into the XML structure looking for elements with the -// given names, and will map the innermost elements to that struct -// field. A tag starting with ">" is equivalent to one starting -// with the field name followed by ">". -// -// * If the XML element contains a sub-element whose name matches -// a struct field's XMLName tag and the struct field has no -// explicit name tag as per the previous rule, unmarshal maps -// the sub-element to that struct field. -// -// * If the XML element contains a sub-element whose name matches a -// field without any mode flags (",attr", ",chardata", etc), Unmarshal -// maps the sub-element to that struct field. -// -// * If the XML element contains a sub-element that hasn't matched any -// of the above rules and the struct has a field with tag ",any", -// unmarshal maps the sub-element to that struct field. -// -// * An anonymous struct field is handled as if the fields of its -// value were part of the outer struct. -// -// * A struct field with tag "-" is never unmarshalled into. -// -// Unmarshal maps an XML element to a string or []byte by saving the -// concatenation of that element's character data in the string or -// []byte. The saved []byte is never nil. -// -// Unmarshal maps an attribute value to a string or []byte by saving -// the value in the string or slice. -// -// Unmarshal maps an XML element to a slice by extending the length of -// the slice and mapping the element to the newly created value. -// -// Unmarshal maps an XML element or attribute value to a bool by -// setting it to the boolean value represented by the string. -// -// Unmarshal maps an XML element or attribute value to an integer or -// floating-point field by setting the field to the result of -// interpreting the string value in decimal. There is no check for -// overflow. -// -// Unmarshal maps an XML element to an xml.Name by recording the -// element name. -// -// Unmarshal maps an XML element to a pointer by setting the pointer -// to a freshly allocated value and then mapping the element to that value. -// -func Unmarshal(data []byte, v interface{}) error { - return NewDecoder(bytes.NewReader(data)).Decode(v) -} - -// Decode works like xml.Unmarshal, except it reads the decoder -// stream to find the start element. -func (d *Decoder) Decode(v interface{}) error { - return d.DecodeElement(v, nil) -} - -// DecodeElement works like xml.Unmarshal except that it takes -// a pointer to the start XML element to decode into v. -// It is useful when a client reads some raw XML tokens itself -// but also wants to defer to Unmarshal for some elements. -func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error { - val := reflect.ValueOf(v) - if val.Kind() != reflect.Ptr { - return errors.New("non-pointer passed to Unmarshal") - } - return d.unmarshal(val.Elem(), start) -} - -// An UnmarshalError represents an error in the unmarshalling process. -type UnmarshalError string - -func (e UnmarshalError) Error() string { return string(e) } - -// Unmarshaler is the interface implemented by objects that can unmarshal -// an XML element description of themselves. -// -// UnmarshalXML decodes a single XML element -// beginning with the given start element. -// If it returns an error, the outer call to Unmarshal stops and -// returns that error. -// UnmarshalXML must consume exactly one XML element. -// One common implementation strategy is to unmarshal into -// a separate value with a layout matching the expected XML -// using d.DecodeElement, and then to copy the data from -// that value into the receiver. -// Another common strategy is to use d.Token to process the -// XML object one token at a time. -// UnmarshalXML may not use d.RawToken. -type Unmarshaler interface { - UnmarshalXML(d *Decoder, start StartElement) error -} - -// UnmarshalerAttr is the interface implemented by objects that can unmarshal -// an XML attribute description of themselves. -// -// UnmarshalXMLAttr decodes a single XML attribute. -// If it returns an error, the outer call to Unmarshal stops and -// returns that error. -// UnmarshalXMLAttr is used only for struct fields with the -// "attr" option in the field tag. -type UnmarshalerAttr interface { - UnmarshalXMLAttr(attr Attr) error -} - -// receiverType returns the receiver type to use in an expression like "%s.MethodName". -func receiverType(val interface{}) string { - t := reflect.TypeOf(val) - if t.Name() != "" { - return t.String() - } - return "(" + t.String() + ")" -} - -// unmarshalInterface unmarshals a single XML element into val. -// start is the opening tag of the element. -func (p *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error { - // Record that decoder must stop at end tag corresponding to start. - p.pushEOF() - - p.unmarshalDepth++ - err := val.UnmarshalXML(p, *start) - p.unmarshalDepth-- - if err != nil { - p.popEOF() - return err - } - - if !p.popEOF() { - return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local) - } - - return nil -} - -// unmarshalTextInterface unmarshals a single XML element into val. -// The chardata contained in the element (but not its children) -// is passed to the text unmarshaler. -func (p *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler, start *StartElement) error { - var buf []byte - depth := 1 - for depth > 0 { - t, err := p.Token() - if err != nil { - return err - } - switch t := t.(type) { - case CharData: - if depth == 1 { - buf = append(buf, t...) - } - case StartElement: - depth++ - case EndElement: - depth-- - } - } - return val.UnmarshalText(buf) -} - -// unmarshalAttr unmarshals a single XML attribute into val. -func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { - if val.Kind() == reflect.Ptr { - if val.IsNil() { - val.Set(reflect.New(val.Type().Elem())) - } - val = val.Elem() - } - - if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) { - // This is an unmarshaler with a non-pointer receiver, - // so it's likely to be incorrect, but we do what we're told. - return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr) - } - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) { - return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr) - } - } - - // Not an UnmarshalerAttr; try encoding.TextUnmarshaler. - if val.CanInterface() && val.Type().Implements(textUnmarshalerType) { - // This is an unmarshaler with a non-pointer receiver, - // so it's likely to be incorrect, but we do what we're told. - return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value)) - } - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { - return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value)) - } - } - - copyValue(val, []byte(attr.Value)) - return nil -} - -var ( - unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() - unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem() - textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() -) - -// Unmarshal a single XML element into val. -func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error { - // Find start element if we need it. - if start == nil { - for { - tok, err := p.Token() - if err != nil { - return err - } - if t, ok := tok.(StartElement); ok { - start = &t - break - } - } - } - - // Load value from interface, but only if the result will be - // usefully addressable. - if val.Kind() == reflect.Interface && !val.IsNil() { - e := val.Elem() - if e.Kind() == reflect.Ptr && !e.IsNil() { - val = e - } - } - - if val.Kind() == reflect.Ptr { - if val.IsNil() { - val.Set(reflect.New(val.Type().Elem())) - } - val = val.Elem() - } - - if val.CanInterface() && val.Type().Implements(unmarshalerType) { - // This is an unmarshaler with a non-pointer receiver, - // so it's likely to be incorrect, but we do what we're told. - return p.unmarshalInterface(val.Interface().(Unmarshaler), start) - } - - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(unmarshalerType) { - return p.unmarshalInterface(pv.Interface().(Unmarshaler), start) - } - } - - if val.CanInterface() && val.Type().Implements(textUnmarshalerType) { - return p.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler), start) - } - - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { - return p.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler), start) - } - } - - var ( - data []byte - saveData reflect.Value - comment []byte - saveComment reflect.Value - saveXML reflect.Value - saveXMLIndex int - saveXMLData []byte - saveAny reflect.Value - sv reflect.Value - tinfo *typeInfo - err error - ) - - switch v := val; v.Kind() { - default: - return errors.New("unknown type " + v.Type().String()) - - case reflect.Interface: - // TODO: For now, simply ignore the field. In the near - // future we may choose to unmarshal the start - // element on it, if not nil. - return p.Skip() - - case reflect.Slice: - typ := v.Type() - if typ.Elem().Kind() == reflect.Uint8 { - // []byte - saveData = v - break - } - - // Slice of element values. - // Grow slice. - n := v.Len() - if n >= v.Cap() { - ncap := 2 * n - if ncap < 4 { - ncap = 4 - } - new := reflect.MakeSlice(typ, n, ncap) - reflect.Copy(new, v) - v.Set(new) - } - v.SetLen(n + 1) - - // Recur to read element into slice. - if err := p.unmarshal(v.Index(n), start); err != nil { - v.SetLen(n) - return err - } - return nil - - case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.String: - saveData = v - - case reflect.Struct: - typ := v.Type() - if typ == nameType { - v.Set(reflect.ValueOf(start.Name)) - break - } - - sv = v - tinfo, err = getTypeInfo(typ) - if err != nil { - return err - } - - // Validate and assign element name. - if tinfo.xmlname != nil { - finfo := tinfo.xmlname - if finfo.name != "" && finfo.name != start.Name.Local { - return UnmarshalError("expected element type <" + finfo.name + "> but have <" + start.Name.Local + ">") - } - if finfo.xmlns != "" && finfo.xmlns != start.Name.Space { - e := "expected element <" + finfo.name + "> in name space " + finfo.xmlns + " but have " - if start.Name.Space == "" { - e += "no name space" - } else { - e += start.Name.Space - } - return UnmarshalError(e) - } - fv := finfo.value(sv) - if _, ok := fv.Interface().(Name); ok { - fv.Set(reflect.ValueOf(start.Name)) - } - } - - // Assign attributes. - // Also, determine whether we need to save character data or comments. - for i := range tinfo.fields { - finfo := &tinfo.fields[i] - switch finfo.flags & fMode { - case fAttr: - strv := finfo.value(sv) - // Look for attribute. - for _, a := range start.Attr { - if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) { - if err := p.unmarshalAttr(strv, a); err != nil { - return err - } - break - } - } - - case fCharData: - if !saveData.IsValid() { - saveData = finfo.value(sv) - } - - case fComment: - if !saveComment.IsValid() { - saveComment = finfo.value(sv) - } - - case fAny, fAny | fElement: - if !saveAny.IsValid() { - saveAny = finfo.value(sv) - } - - case fInnerXml: - if !saveXML.IsValid() { - saveXML = finfo.value(sv) - if p.saved == nil { - saveXMLIndex = 0 - p.saved = new(bytes.Buffer) - } else { - saveXMLIndex = p.savedOffset() - } - } - } - } - } - - // Find end element. - // Process sub-elements along the way. -Loop: - for { - var savedOffset int - if saveXML.IsValid() { - savedOffset = p.savedOffset() - } - tok, err := p.Token() - if err != nil { - return err - } - switch t := tok.(type) { - case StartElement: - consumed := false - if sv.IsValid() { - consumed, err = p.unmarshalPath(tinfo, sv, nil, &t) - if err != nil { - return err - } - if !consumed && saveAny.IsValid() { - consumed = true - if err := p.unmarshal(saveAny, &t); err != nil { - return err - } - } - } - if !consumed { - if err := p.Skip(); err != nil { - return err - } - } - - case EndElement: - if saveXML.IsValid() { - saveXMLData = p.saved.Bytes()[saveXMLIndex:savedOffset] - if saveXMLIndex == 0 { - p.saved = nil - } - } - break Loop - - case CharData: - if saveData.IsValid() { - data = append(data, t...) - } - - case Comment: - if saveComment.IsValid() { - comment = append(comment, t...) - } - } - } - - if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) { - if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { - return err - } - saveData = reflect.Value{} - } - - if saveData.IsValid() && saveData.CanAddr() { - pv := saveData.Addr() - if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { - if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { - return err - } - saveData = reflect.Value{} - } - } - - if err := copyValue(saveData, data); err != nil { - return err - } - - switch t := saveComment; t.Kind() { - case reflect.String: - t.SetString(string(comment)) - case reflect.Slice: - t.Set(reflect.ValueOf(comment)) - } - - switch t := saveXML; t.Kind() { - case reflect.String: - t.SetString(string(saveXMLData)) - case reflect.Slice: - t.Set(reflect.ValueOf(saveXMLData)) - } - - return nil -} - -func copyValue(dst reflect.Value, src []byte) (err error) { - dst0 := dst - - if dst.Kind() == reflect.Ptr { - if dst.IsNil() { - dst.Set(reflect.New(dst.Type().Elem())) - } - dst = dst.Elem() - } - - // Save accumulated data. - switch dst.Kind() { - case reflect.Invalid: - // Probably a comment. - default: - return errors.New("cannot unmarshal into " + dst0.Type().String()) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits()) - if err != nil { - return err - } - dst.SetInt(itmp) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - utmp, err := strconv.ParseUint(string(src), 10, dst.Type().Bits()) - if err != nil { - return err - } - dst.SetUint(utmp) - case reflect.Float32, reflect.Float64: - ftmp, err := strconv.ParseFloat(string(src), dst.Type().Bits()) - if err != nil { - return err - } - dst.SetFloat(ftmp) - case reflect.Bool: - value, err := strconv.ParseBool(strings.TrimSpace(string(src))) - if err != nil { - return err - } - dst.SetBool(value) - case reflect.String: - dst.SetString(string(src)) - case reflect.Slice: - if len(src) == 0 { - // non-nil to flag presence - src = []byte{} - } - dst.SetBytes(src) - } - return nil -} - -// unmarshalPath walks down an XML structure looking for wanted -// paths, and calls unmarshal on them. -// The consumed result tells whether XML elements have been consumed -// from the Decoder until start's matching end element, or if it's -// still untouched because start is uninteresting for sv's fields. -func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) { - recurse := false -Loop: - for i := range tinfo.fields { - finfo := &tinfo.fields[i] - if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) || finfo.xmlns != "" && finfo.xmlns != start.Name.Space { - continue - } - for j := range parents { - if parents[j] != finfo.parents[j] { - continue Loop - } - } - if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local { - // It's a perfect match, unmarshal the field. - return true, p.unmarshal(finfo.value(sv), start) - } - if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local { - // It's a prefix for the field. Break and recurse - // since it's not ok for one field path to be itself - // the prefix for another field path. - recurse = true - - // We can reuse the same slice as long as we - // don't try to append to it. - parents = finfo.parents[:len(parents)+1] - break - } - } - if !recurse { - // We have no business with this element. - return false, nil - } - // The element is not a perfect match for any field, but one - // or more fields have the path to this element as a parent - // prefix. Recurse and attempt to match these. - for { - var tok Token - tok, err = p.Token() - if err != nil { - return true, err - } - switch t := tok.(type) { - case StartElement: - consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t) - if err != nil { - return true, err - } - if !consumed2 { - if err := p.Skip(); err != nil { - return true, err - } - } - case EndElement: - return true, nil - } - } -} - -// Skip reads tokens until it has consumed the end element -// matching the most recent start element already consumed. -// It recurs if it encounters a start element, so it can be used to -// skip nested structures. -// It returns nil if it finds an end element matching the start -// element; otherwise it returns an error describing the problem. -func (d *Decoder) Skip() error { - for { - tok, err := d.Token() - if err != nil { - return err - } - switch tok.(type) { - case StartElement: - if err := d.Skip(); err != nil { - return err - } - case EndElement: - return nil - } - } -} diff --git a/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go b/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go deleted file mode 100644 index fdde288bc37..00000000000 --- a/vendor/golang.org/x/net/webdav/internal/xml/typeinfo.go +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2011 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 xml - -import ( - "fmt" - "reflect" - "strings" - "sync" -) - -// typeInfo holds details for the xml representation of a type. -type typeInfo struct { - xmlname *fieldInfo - fields []fieldInfo -} - -// fieldInfo holds details for the xml representation of a single field. -type fieldInfo struct { - idx []int - name string - xmlns string - flags fieldFlags - parents []string -} - -type fieldFlags int - -const ( - fElement fieldFlags = 1 << iota - fAttr - fCharData - fInnerXml - fComment - fAny - - fOmitEmpty - - fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny -) - -var tinfoMap = make(map[reflect.Type]*typeInfo) -var tinfoLock sync.RWMutex - -var nameType = reflect.TypeOf(Name{}) - -// getTypeInfo returns the typeInfo structure with details necessary -// for marshalling and unmarshalling typ. -func getTypeInfo(typ reflect.Type) (*typeInfo, error) { - tinfoLock.RLock() - tinfo, ok := tinfoMap[typ] - tinfoLock.RUnlock() - if ok { - return tinfo, nil - } - tinfo = &typeInfo{} - if typ.Kind() == reflect.Struct && typ != nameType { - n := typ.NumField() - for i := 0; i < n; i++ { - f := typ.Field(i) - if f.PkgPath != "" || f.Tag.Get("xml") == "-" { - continue // Private field - } - - // For embedded structs, embed its fields. - if f.Anonymous { - t := f.Type - if t.Kind() == reflect.Ptr { - t = t.Elem() - } - if t.Kind() == reflect.Struct { - inner, err := getTypeInfo(t) - if err != nil { - return nil, err - } - if tinfo.xmlname == nil { - tinfo.xmlname = inner.xmlname - } - for _, finfo := range inner.fields { - finfo.idx = append([]int{i}, finfo.idx...) - if err := addFieldInfo(typ, tinfo, &finfo); err != nil { - return nil, err - } - } - continue - } - } - - finfo, err := structFieldInfo(typ, &f) - if err != nil { - return nil, err - } - - if f.Name == "XMLName" { - tinfo.xmlname = finfo - continue - } - - // Add the field if it doesn't conflict with other fields. - if err := addFieldInfo(typ, tinfo, finfo); err != nil { - return nil, err - } - } - } - tinfoLock.Lock() - tinfoMap[typ] = tinfo - tinfoLock.Unlock() - return tinfo, nil -} - -// structFieldInfo builds and returns a fieldInfo for f. -func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, error) { - finfo := &fieldInfo{idx: f.Index} - - // Split the tag from the xml namespace if necessary. - tag := f.Tag.Get("xml") - if i := strings.Index(tag, " "); i >= 0 { - finfo.xmlns, tag = tag[:i], tag[i+1:] - } - - // Parse flags. - tokens := strings.Split(tag, ",") - if len(tokens) == 1 { - finfo.flags = fElement - } else { - tag = tokens[0] - for _, flag := range tokens[1:] { - switch flag { - case "attr": - finfo.flags |= fAttr - case "chardata": - finfo.flags |= fCharData - case "innerxml": - finfo.flags |= fInnerXml - case "comment": - finfo.flags |= fComment - case "any": - finfo.flags |= fAny - case "omitempty": - finfo.flags |= fOmitEmpty - } - } - - // Validate the flags used. - valid := true - switch mode := finfo.flags & fMode; mode { - case 0: - finfo.flags |= fElement - case fAttr, fCharData, fInnerXml, fComment, fAny: - if f.Name == "XMLName" || tag != "" && mode != fAttr { - valid = false - } - default: - // This will also catch multiple modes in a single field. - valid = false - } - if finfo.flags&fMode == fAny { - finfo.flags |= fElement - } - if finfo.flags&fOmitEmpty != 0 && finfo.flags&(fElement|fAttr) == 0 { - valid = false - } - if !valid { - return nil, fmt.Errorf("xml: invalid tag in field %s of type %s: %q", - f.Name, typ, f.Tag.Get("xml")) - } - } - - // Use of xmlns without a name is not allowed. - if finfo.xmlns != "" && tag == "" { - return nil, fmt.Errorf("xml: namespace without name in field %s of type %s: %q", - f.Name, typ, f.Tag.Get("xml")) - } - - if f.Name == "XMLName" { - // The XMLName field records the XML element name. Don't - // process it as usual because its name should default to - // empty rather than to the field name. - finfo.name = tag - return finfo, nil - } - - if tag == "" { - // If the name part of the tag is completely empty, get - // default from XMLName of underlying struct if feasible, - // or field name otherwise. - if xmlname := lookupXMLName(f.Type); xmlname != nil { - finfo.xmlns, finfo.name = xmlname.xmlns, xmlname.name - } else { - finfo.name = f.Name - } - return finfo, nil - } - - if finfo.xmlns == "" && finfo.flags&fAttr == 0 { - // If it's an element no namespace specified, get the default - // from the XMLName of enclosing struct if possible. - if xmlname := lookupXMLName(typ); xmlname != nil { - finfo.xmlns = xmlname.xmlns - } - } - - // Prepare field name and parents. - parents := strings.Split(tag, ">") - if parents[0] == "" { - parents[0] = f.Name - } - if parents[len(parents)-1] == "" { - return nil, fmt.Errorf("xml: trailing '>' in field %s of type %s", f.Name, typ) - } - finfo.name = parents[len(parents)-1] - if len(parents) > 1 { - if (finfo.flags & fElement) == 0 { - return nil, fmt.Errorf("xml: %s chain not valid with %s flag", tag, strings.Join(tokens[1:], ",")) - } - finfo.parents = parents[:len(parents)-1] - } - - // If the field type has an XMLName field, the names must match - // so that the behavior of both marshalling and unmarshalling - // is straightforward and unambiguous. - if finfo.flags&fElement != 0 { - ftyp := f.Type - xmlname := lookupXMLName(ftyp) - if xmlname != nil && xmlname.name != finfo.name { - return nil, fmt.Errorf("xml: name %q in tag of %s.%s conflicts with name %q in %s.XMLName", - finfo.name, typ, f.Name, xmlname.name, ftyp) - } - } - return finfo, nil -} - -// lookupXMLName returns the fieldInfo for typ's XMLName field -// in case it exists and has a valid xml field tag, otherwise -// it returns nil. -func lookupXMLName(typ reflect.Type) (xmlname *fieldInfo) { - for typ.Kind() == reflect.Ptr { - typ = typ.Elem() - } - if typ.Kind() != reflect.Struct { - return nil - } - for i, n := 0, typ.NumField(); i < n; i++ { - f := typ.Field(i) - if f.Name != "XMLName" { - continue - } - finfo, err := structFieldInfo(typ, &f) - if finfo.name != "" && err == nil { - return finfo - } - // Also consider errors as a non-existent field tag - // and let getTypeInfo itself report the error. - break - } - return nil -} - -func min(a, b int) int { - if a <= b { - return a - } - return b -} - -// addFieldInfo adds finfo to tinfo.fields if there are no -// conflicts, or if conflicts arise from previous fields that were -// obtained from deeper embedded structures than finfo. In the latter -// case, the conflicting entries are dropped. -// A conflict occurs when the path (parent + name) to a field is -// itself a prefix of another path, or when two paths match exactly. -// It is okay for field paths to share a common, shorter prefix. -func addFieldInfo(typ reflect.Type, tinfo *typeInfo, newf *fieldInfo) error { - var conflicts []int -Loop: - // First, figure all conflicts. Most working code will have none. - for i := range tinfo.fields { - oldf := &tinfo.fields[i] - if oldf.flags&fMode != newf.flags&fMode { - continue - } - if oldf.xmlns != "" && newf.xmlns != "" && oldf.xmlns != newf.xmlns { - continue - } - minl := min(len(newf.parents), len(oldf.parents)) - for p := 0; p < minl; p++ { - if oldf.parents[p] != newf.parents[p] { - continue Loop - } - } - if len(oldf.parents) > len(newf.parents) { - if oldf.parents[len(newf.parents)] == newf.name { - conflicts = append(conflicts, i) - } - } else if len(oldf.parents) < len(newf.parents) { - if newf.parents[len(oldf.parents)] == oldf.name { - conflicts = append(conflicts, i) - } - } else { - if newf.name == oldf.name { - conflicts = append(conflicts, i) - } - } - } - // Without conflicts, add the new field and return. - if conflicts == nil { - tinfo.fields = append(tinfo.fields, *newf) - return nil - } - - // If any conflict is shallower, ignore the new field. - // This matches the Go field resolution on embedding. - for _, i := range conflicts { - if len(tinfo.fields[i].idx) < len(newf.idx) { - return nil - } - } - - // Otherwise, if any of them is at the same depth level, it's an error. - for _, i := range conflicts { - oldf := &tinfo.fields[i] - if len(oldf.idx) == len(newf.idx) { - f1 := typ.FieldByIndex(oldf.idx) - f2 := typ.FieldByIndex(newf.idx) - return &TagPathError{typ, f1.Name, f1.Tag.Get("xml"), f2.Name, f2.Tag.Get("xml")} - } - } - - // Otherwise, the new field is shallower, and thus takes precedence, - // so drop the conflicting fields from tinfo and append the new one. - for c := len(conflicts) - 1; c >= 0; c-- { - i := conflicts[c] - copy(tinfo.fields[i:], tinfo.fields[i+1:]) - tinfo.fields = tinfo.fields[:len(tinfo.fields)-1] - } - tinfo.fields = append(tinfo.fields, *newf) - return nil -} - -// A TagPathError represents an error in the unmarshalling process -// caused by the use of field tags with conflicting paths. -type TagPathError struct { - Struct reflect.Type - Field1, Tag1 string - Field2, Tag2 string -} - -func (e *TagPathError) Error() string { - return fmt.Sprintf("%s field %q with tag %q conflicts with field %q with tag %q", e.Struct, e.Field1, e.Tag1, e.Field2, e.Tag2) -} - -// value returns v's field value corresponding to finfo. -// It's equivalent to v.FieldByIndex(finfo.idx), but initializes -// and dereferences pointers as necessary. -func (finfo *fieldInfo) value(v reflect.Value) reflect.Value { - for i, x := range finfo.idx { - if i > 0 { - t := v.Type() - if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct { - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - v = v.Elem() - } - } - v = v.Field(x) - } - return v -} diff --git a/vendor/golang.org/x/net/webdav/internal/xml/xml.go b/vendor/golang.org/x/net/webdav/internal/xml/xml.go deleted file mode 100644 index 5b79cbecb4d..00000000000 --- a/vendor/golang.org/x/net/webdav/internal/xml/xml.go +++ /dev/null @@ -1,1998 +0,0 @@ -// Copyright 2009 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 xml implements a simple XML 1.0 parser that -// understands XML name spaces. -package xml - -// References: -// Annotated XML spec: http://www.xml.com/axml/testaxml.htm -// XML name spaces: http://www.w3.org/TR/REC-xml-names/ - -// TODO(rsc): -// Test error handling. - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "strconv" - "strings" - "unicode" - "unicode/utf8" -) - -// A SyntaxError represents a syntax error in the XML input stream. -type SyntaxError struct { - Msg string - Line int -} - -func (e *SyntaxError) Error() string { - return "XML syntax error on line " + strconv.Itoa(e.Line) + ": " + e.Msg -} - -// A Name represents an XML name (Local) annotated with a name space -// identifier (Space). In tokens returned by Decoder.Token, the Space -// identifier is given as a canonical URL, not the short prefix used in -// the document being parsed. -// -// As a special case, XML namespace declarations will use the literal -// string "xmlns" for the Space field instead of the fully resolved URL. -// See Encoder.EncodeToken for more information on namespace encoding -// behaviour. -type Name struct { - Space, Local string -} - -// isNamespace reports whether the name is a namespace-defining name. -func (name Name) isNamespace() bool { - return name.Local == "xmlns" || name.Space == "xmlns" -} - -// An Attr represents an attribute in an XML element (Name=Value). -type Attr struct { - Name Name - Value string -} - -// A Token is an interface holding one of the token types: -// StartElement, EndElement, CharData, Comment, ProcInst, or Directive. -type Token interface{} - -// A StartElement represents an XML start element. -type StartElement struct { - Name Name - Attr []Attr -} - -func (e StartElement) Copy() StartElement { - attrs := make([]Attr, len(e.Attr)) - copy(attrs, e.Attr) - e.Attr = attrs - return e -} - -// End returns the corresponding XML end element. -func (e StartElement) End() EndElement { - return EndElement{e.Name} -} - -// setDefaultNamespace sets the namespace of the element -// as the default for all elements contained within it. -func (e *StartElement) setDefaultNamespace() { - if e.Name.Space == "" { - // If there's no namespace on the element, don't - // set the default. Strictly speaking this might be wrong, as - // we can't tell if the element had no namespace set - // or was just using the default namespace. - return - } - // Don't add a default name space if there's already one set. - for _, attr := range e.Attr { - if attr.Name.Space == "" && attr.Name.Local == "xmlns" { - return - } - } - e.Attr = append(e.Attr, Attr{ - Name: Name{ - Local: "xmlns", - }, - Value: e.Name.Space, - }) -} - -// An EndElement represents an XML end element. -type EndElement struct { - Name Name -} - -// A CharData represents XML character data (raw text), -// in which XML escape sequences have been replaced by -// the characters they represent. -type CharData []byte - -func makeCopy(b []byte) []byte { - b1 := make([]byte, len(b)) - copy(b1, b) - return b1 -} - -func (c CharData) Copy() CharData { return CharData(makeCopy(c)) } - -// A Comment represents an XML comment of the form . -// The bytes do not include the comment markers. -type Comment []byte - -func (c Comment) Copy() Comment { return Comment(makeCopy(c)) } - -// A ProcInst represents an XML processing instruction of the form -type ProcInst struct { - Target string - Inst []byte -} - -func (p ProcInst) Copy() ProcInst { - p.Inst = makeCopy(p.Inst) - return p -} - -// A Directive represents an XML directive of the form . -// The bytes do not include the markers. -type Directive []byte - -func (d Directive) Copy() Directive { return Directive(makeCopy(d)) } - -// CopyToken returns a copy of a Token. -func CopyToken(t Token) Token { - switch v := t.(type) { - case CharData: - return v.Copy() - case Comment: - return v.Copy() - case Directive: - return v.Copy() - case ProcInst: - return v.Copy() - case StartElement: - return v.Copy() - } - return t -} - -// A Decoder represents an XML parser reading a particular input stream. -// The parser assumes that its input is encoded in UTF-8. -type Decoder struct { - // Strict defaults to true, enforcing the requirements - // of the XML specification. - // If set to false, the parser allows input containing common - // mistakes: - // * If an element is missing an end tag, the parser invents - // end tags as necessary to keep the return values from Token - // properly balanced. - // * In attribute values and character data, unknown or malformed - // character entities (sequences beginning with &) are left alone. - // - // Setting: - // - // d.Strict = false; - // d.AutoClose = HTMLAutoClose; - // d.Entity = HTMLEntity - // - // creates a parser that can handle typical HTML. - // - // Strict mode does not enforce the requirements of the XML name spaces TR. - // In particular it does not reject name space tags using undefined prefixes. - // Such tags are recorded with the unknown prefix as the name space URL. - Strict bool - - // When Strict == false, AutoClose indicates a set of elements to - // consider closed immediately after they are opened, regardless - // of whether an end element is present. - AutoClose []string - - // Entity can be used to map non-standard entity names to string replacements. - // The parser behaves as if these standard mappings are present in the map, - // regardless of the actual map content: - // - // "lt": "<", - // "gt": ">", - // "amp": "&", - // "apos": "'", - // "quot": `"`, - Entity map[string]string - - // CharsetReader, if non-nil, defines a function to generate - // charset-conversion readers, converting from the provided - // non-UTF-8 charset into UTF-8. If CharsetReader is nil or - // returns an error, parsing stops with an error. One of the - // the CharsetReader's result values must be non-nil. - CharsetReader func(charset string, input io.Reader) (io.Reader, error) - - // DefaultSpace sets the default name space used for unadorned tags, - // as if the entire XML stream were wrapped in an element containing - // the attribute xmlns="DefaultSpace". - DefaultSpace string - - r io.ByteReader - buf bytes.Buffer - saved *bytes.Buffer - stk *stack - free *stack - needClose bool - toClose Name - nextToken Token - nextByte int - ns map[string]string - err error - line int - offset int64 - unmarshalDepth int -} - -// NewDecoder creates a new XML parser reading from r. -// If r does not implement io.ByteReader, NewDecoder will -// do its own buffering. -func NewDecoder(r io.Reader) *Decoder { - d := &Decoder{ - ns: make(map[string]string), - nextByte: -1, - line: 1, - Strict: true, - } - d.switchToReader(r) - return d -} - -// Token returns the next XML token in the input stream. -// At the end of the input stream, Token returns nil, io.EOF. -// -// Slices of bytes in the returned token data refer to the -// parser's internal buffer and remain valid only until the next -// call to Token. To acquire a copy of the bytes, call CopyToken -// or the token's Copy method. -// -// Token expands self-closing elements such as
    -// into separate start and end elements returned by successive calls. -// -// Token guarantees that the StartElement and EndElement -// tokens it returns are properly nested and matched: -// if Token encounters an unexpected end element, -// it will return an error. -// -// Token implements XML name spaces as described by -// http://www.w3.org/TR/REC-xml-names/. Each of the -// Name structures contained in the Token has the Space -// set to the URL identifying its name space when known. -// If Token encounters an unrecognized name space prefix, -// it uses the prefix as the Space rather than report an error. -func (d *Decoder) Token() (t Token, err error) { - if d.stk != nil && d.stk.kind == stkEOF { - err = io.EOF - return - } - if d.nextToken != nil { - t = d.nextToken - d.nextToken = nil - } else if t, err = d.rawToken(); err != nil { - return - } - - if !d.Strict { - if t1, ok := d.autoClose(t); ok { - d.nextToken = t - t = t1 - } - } - switch t1 := t.(type) { - case StartElement: - // In XML name spaces, the translations listed in the - // attributes apply to the element name and - // to the other attribute names, so process - // the translations first. - for _, a := range t1.Attr { - if a.Name.Space == "xmlns" { - v, ok := d.ns[a.Name.Local] - d.pushNs(a.Name.Local, v, ok) - d.ns[a.Name.Local] = a.Value - } - if a.Name.Space == "" && a.Name.Local == "xmlns" { - // Default space for untagged names - v, ok := d.ns[""] - d.pushNs("", v, ok) - d.ns[""] = a.Value - } - } - - d.translate(&t1.Name, true) - for i := range t1.Attr { - d.translate(&t1.Attr[i].Name, false) - } - d.pushElement(t1.Name) - t = t1 - - case EndElement: - d.translate(&t1.Name, true) - if !d.popElement(&t1) { - return nil, d.err - } - t = t1 - } - return -} - -const xmlURL = "http://www.w3.org/XML/1998/namespace" - -// Apply name space translation to name n. -// The default name space (for Space=="") -// applies only to element names, not to attribute names. -func (d *Decoder) translate(n *Name, isElementName bool) { - switch { - case n.Space == "xmlns": - return - case n.Space == "" && !isElementName: - return - case n.Space == "xml": - n.Space = xmlURL - case n.Space == "" && n.Local == "xmlns": - return - } - if v, ok := d.ns[n.Space]; ok { - n.Space = v - } else if n.Space == "" { - n.Space = d.DefaultSpace - } -} - -func (d *Decoder) switchToReader(r io.Reader) { - // Get efficient byte at a time reader. - // Assume that if reader has its own - // ReadByte, it's efficient enough. - // Otherwise, use bufio. - if rb, ok := r.(io.ByteReader); ok { - d.r = rb - } else { - d.r = bufio.NewReader(r) - } -} - -// Parsing state - stack holds old name space translations -// and the current set of open elements. The translations to pop when -// ending a given tag are *below* it on the stack, which is -// more work but forced on us by XML. -type stack struct { - next *stack - kind int - name Name - ok bool -} - -const ( - stkStart = iota - stkNs - stkEOF -) - -func (d *Decoder) push(kind int) *stack { - s := d.free - if s != nil { - d.free = s.next - } else { - s = new(stack) - } - s.next = d.stk - s.kind = kind - d.stk = s - return s -} - -func (d *Decoder) pop() *stack { - s := d.stk - if s != nil { - d.stk = s.next - s.next = d.free - d.free = s - } - return s -} - -// Record that after the current element is finished -// (that element is already pushed on the stack) -// Token should return EOF until popEOF is called. -func (d *Decoder) pushEOF() { - // Walk down stack to find Start. - // It might not be the top, because there might be stkNs - // entries above it. - start := d.stk - for start.kind != stkStart { - start = start.next - } - // The stkNs entries below a start are associated with that - // element too; skip over them. - for start.next != nil && start.next.kind == stkNs { - start = start.next - } - s := d.free - if s != nil { - d.free = s.next - } else { - s = new(stack) - } - s.kind = stkEOF - s.next = start.next - start.next = s -} - -// Undo a pushEOF. -// The element must have been finished, so the EOF should be at the top of the stack. -func (d *Decoder) popEOF() bool { - if d.stk == nil || d.stk.kind != stkEOF { - return false - } - d.pop() - return true -} - -// Record that we are starting an element with the given name. -func (d *Decoder) pushElement(name Name) { - s := d.push(stkStart) - s.name = name -} - -// Record that we are changing the value of ns[local]. -// The old value is url, ok. -func (d *Decoder) pushNs(local string, url string, ok bool) { - s := d.push(stkNs) - s.name.Local = local - s.name.Space = url - s.ok = ok -} - -// Creates a SyntaxError with the current line number. -func (d *Decoder) syntaxError(msg string) error { - return &SyntaxError{Msg: msg, Line: d.line} -} - -// Record that we are ending an element with the given name. -// The name must match the record at the top of the stack, -// which must be a pushElement record. -// After popping the element, apply any undo records from -// the stack to restore the name translations that existed -// before we saw this element. -func (d *Decoder) popElement(t *EndElement) bool { - s := d.pop() - name := t.Name - switch { - case s == nil || s.kind != stkStart: - d.err = d.syntaxError("unexpected end element ") - return false - case s.name.Local != name.Local: - if !d.Strict { - d.needClose = true - d.toClose = t.Name - t.Name = s.name - return true - } - d.err = d.syntaxError("element <" + s.name.Local + "> closed by ") - return false - case s.name.Space != name.Space: - d.err = d.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space + - "closed by in space " + name.Space) - return false - } - - // Pop stack until a Start or EOF is on the top, undoing the - // translations that were associated with the element we just closed. - for d.stk != nil && d.stk.kind != stkStart && d.stk.kind != stkEOF { - s := d.pop() - if s.ok { - d.ns[s.name.Local] = s.name.Space - } else { - delete(d.ns, s.name.Local) - } - } - - return true -} - -// If the top element on the stack is autoclosing and -// t is not the end tag, invent the end tag. -func (d *Decoder) autoClose(t Token) (Token, bool) { - if d.stk == nil || d.stk.kind != stkStart { - return nil, false - } - name := strings.ToLower(d.stk.name.Local) - for _, s := range d.AutoClose { - if strings.ToLower(s) == name { - // This one should be auto closed if t doesn't close it. - et, ok := t.(EndElement) - if !ok || et.Name.Local != name { - return EndElement{d.stk.name}, true - } - break - } - } - return nil, false -} - -var errRawToken = errors.New("xml: cannot use RawToken from UnmarshalXML method") - -// RawToken is like Token but does not verify that -// start and end elements match and does not translate -// name space prefixes to their corresponding URLs. -func (d *Decoder) RawToken() (Token, error) { - if d.unmarshalDepth > 0 { - return nil, errRawToken - } - return d.rawToken() -} - -func (d *Decoder) rawToken() (Token, error) { - if d.err != nil { - return nil, d.err - } - if d.needClose { - // The last element we read was self-closing and - // we returned just the StartElement half. - // Return the EndElement half now. - d.needClose = false - return EndElement{d.toClose}, nil - } - - b, ok := d.getc() - if !ok { - return nil, d.err - } - - if b != '<' { - // Text section. - d.ungetc(b) - data := d.text(-1, false) - if data == nil { - return nil, d.err - } - return CharData(data), nil - } - - if b, ok = d.mustgetc(); !ok { - return nil, d.err - } - switch b { - case '/': - // ' { - d.err = d.syntaxError("invalid characters between ") - return nil, d.err - } - return EndElement{name}, nil - - case '?': - // ' { - break - } - b0 = b - } - data := d.buf.Bytes() - data = data[0 : len(data)-2] // chop ?> - - if target == "xml" { - content := string(data) - ver := procInst("version", content) - if ver != "" && ver != "1.0" { - d.err = fmt.Errorf("xml: unsupported version %q; only version 1.0 is supported", ver) - return nil, d.err - } - enc := procInst("encoding", content) - if enc != "" && enc != "utf-8" && enc != "UTF-8" { - if d.CharsetReader == nil { - d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc) - return nil, d.err - } - newr, err := d.CharsetReader(enc, d.r.(io.Reader)) - if err != nil { - d.err = fmt.Errorf("xml: opening charset %q: %v", enc, err) - return nil, d.err - } - if newr == nil { - panic("CharsetReader returned a nil Reader for charset " + enc) - } - d.switchToReader(newr) - } - } - return ProcInst{target, data}, nil - - case '!': - // ' { - break - } - b0, b1 = b1, b - } - data := d.buf.Bytes() - data = data[0 : len(data)-3] // chop --> - return Comment(data), nil - - case '[': // . - data := d.text(-1, true) - if data == nil { - return nil, d.err - } - return CharData(data), nil - } - - // Probably a directive: , , etc. - // We don't care, but accumulate for caller. Quoted angle - // brackets do not count for nesting. - d.buf.Reset() - d.buf.WriteByte(b) - inquote := uint8(0) - depth := 0 - for { - if b, ok = d.mustgetc(); !ok { - return nil, d.err - } - if inquote == 0 && b == '>' && depth == 0 { - break - } - HandleB: - d.buf.WriteByte(b) - switch { - case b == inquote: - inquote = 0 - - case inquote != 0: - // in quotes, no special action - - case b == '\'' || b == '"': - inquote = b - - case b == '>' && inquote == 0: - depth-- - - case b == '<' && inquote == 0: - // Look for -// -// the ast.BinaryExpr(+) node is considered to enclose interval B -// even though its [Pos()..End()) is actually only interval A. -// This behaviour makes user interfaces more tolerant of imperfect -// input. -// -// This function treats tokens as nodes, though they are not included -// in the result. e.g. PathEnclosingInterval("+") returns the -// enclosing ast.BinaryExpr("x + y"). -// -// If start==end, the 1-char interval following start is used instead. -// -// The 'exact' result is true if the interval contains only path[0] -// and perhaps some adjacent whitespace. It is false if the interval -// overlaps multiple children of path[0], or if it contains only -// interior whitespace of path[0]. -// In this example: -// -// z := x + y // add them -// <--C--> <---E--> -// ^ -// D -// -// intervals C, D and E are inexact. C is contained by the -// z-assignment statement, because it spans three of its children (:=, -// x, +). So too is the 1-char interval D, because it contains only -// interior whitespace of the assignment. E is considered interior -// whitespace of the BlockStmt containing the assignment. -// -// Precondition: [start, end) both lie within the same file as root. -// TODO(adonovan): return (nil, false) in this case and remove precond. -// Requires FileSet; see loader.tokenFileContainsPos. -// -// Postcondition: path is never nil; it always contains at least 'root'. -// -func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) { - // fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging - - // Precondition: node.[Pos..End) and adjoining whitespace contain [start, end). - var visit func(node ast.Node) bool - visit = func(node ast.Node) bool { - path = append(path, node) - - nodePos := node.Pos() - nodeEnd := node.End() - - // fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging - - // Intersect [start, end) with interval of node. - if start < nodePos { - start = nodePos - } - if end > nodeEnd { - end = nodeEnd - } - - // Find sole child that contains [start, end). - children := childrenOf(node) - l := len(children) - for i, child := range children { - // [childPos, childEnd) is unaugmented interval of child. - childPos := child.Pos() - childEnd := child.End() - - // [augPos, augEnd) is whitespace-augmented interval of child. - augPos := childPos - augEnd := childEnd - if i > 0 { - augPos = children[i-1].End() // start of preceding whitespace - } - if i < l-1 { - nextChildPos := children[i+1].Pos() - // Does [start, end) lie between child and next child? - if start >= augEnd && end <= nextChildPos { - return false // inexact match - } - augEnd = nextChildPos // end of following whitespace - } - - // fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n", - // i, augPos, augEnd, start, end) // debugging - - // Does augmented child strictly contain [start, end)? - if augPos <= start && end <= augEnd { - _, isToken := child.(tokenNode) - return isToken || visit(child) - } - - // Does [start, end) overlap multiple children? - // i.e. left-augmented child contains start - // but LR-augmented child does not contain end. - if start < childEnd && end > augEnd { - break - } - } - - // No single child contained [start, end), - // so node is the result. Is it exact? - - // (It's tempting to put this condition before the - // child loop, but it gives the wrong result in the - // case where a node (e.g. ExprStmt) and its sole - // child have equal intervals.) - if start == nodePos && end == nodeEnd { - return true // exact match - } - - return false // inexact: overlaps multiple children - } - - if start > end { - start, end = end, start - } - - if start < root.End() && end > root.Pos() { - if start == end { - end = start + 1 // empty interval => interval of size 1 - } - exact = visit(root) - - // Reverse the path: - for i, l := 0, len(path); i < l/2; i++ { - path[i], path[l-1-i] = path[l-1-i], path[i] - } - } else { - // Selection lies within whitespace preceding the - // first (or following the last) declaration in the file. - // The result nonetheless always includes the ast.File. - path = append(path, root) - } - - return -} - -// tokenNode is a dummy implementation of ast.Node for a single token. -// They are used transiently by PathEnclosingInterval but never escape -// this package. -// -type tokenNode struct { - pos token.Pos - end token.Pos -} - -func (n tokenNode) Pos() token.Pos { - return n.pos -} - -func (n tokenNode) End() token.Pos { - return n.end -} - -func tok(pos token.Pos, len int) ast.Node { - return tokenNode{pos, pos + token.Pos(len)} -} - -// childrenOf returns the direct non-nil children of ast.Node n. -// It may include fake ast.Node implementations for bare tokens. -// it is not safe to call (e.g.) ast.Walk on such nodes. -// -func childrenOf(n ast.Node) []ast.Node { - var children []ast.Node - - // First add nodes for all true subtrees. - ast.Inspect(n, func(node ast.Node) bool { - if node == n { // push n - return true // recur - } - if node != nil { // push child - children = append(children, node) - } - return false // no recursion - }) - - // Then add fake Nodes for bare tokens. - switch n := n.(type) { - case *ast.ArrayType: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Elt.End(), len("]"))) - - case *ast.AssignStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.BasicLit: - children = append(children, - tok(n.ValuePos, len(n.Value))) - - case *ast.BinaryExpr: - children = append(children, tok(n.OpPos, len(n.Op.String()))) - - case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) - - case *ast.BranchStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.CallExpr: - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - if n.Ellipsis != 0 { - children = append(children, tok(n.Ellipsis, len("..."))) - } - - case *ast.CaseClause: - if n.List == nil { - children = append(children, - tok(n.Case, len("default"))) - } else { - children = append(children, - tok(n.Case, len("case"))) - } - children = append(children, tok(n.Colon, len(":"))) - - case *ast.ChanType: - switch n.Dir { - case ast.RECV: - children = append(children, tok(n.Begin, len("<-chan"))) - case ast.SEND: - children = append(children, tok(n.Begin, len("chan<-"))) - case ast.RECV | ast.SEND: - children = append(children, tok(n.Begin, len("chan"))) - } - - case *ast.CommClause: - if n.Comm == nil { - children = append(children, - tok(n.Case, len("default"))) - } else { - children = append(children, - tok(n.Case, len("case"))) - } - children = append(children, tok(n.Colon, len(":"))) - - case *ast.Comment: - // nop - - case *ast.CommentGroup: - // nop - - case *ast.CompositeLit: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("{"))) - - case *ast.DeclStmt: - // nop - - case *ast.DeferStmt: - children = append(children, - tok(n.Defer, len("defer"))) - - case *ast.Ellipsis: - children = append(children, - tok(n.Ellipsis, len("..."))) - - case *ast.EmptyStmt: - // nop - - case *ast.ExprStmt: - // nop - - case *ast.Field: - // TODO(adonovan): Field.{Doc,Comment,Tag}? - - case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), - tok(n.Closing, len(")"))) - - case *ast.File: - // TODO test: Doc - children = append(children, - tok(n.Package, len("package"))) - - case *ast.ForStmt: - children = append(children, - tok(n.For, len("for"))) - - case *ast.FuncDecl: - // TODO(adonovan): FuncDecl.Comment? - - // Uniquely, FuncDecl breaks the invariant that - // preorder traversal yields tokens in lexical order: - // in fact, FuncDecl.Recv precedes FuncDecl.Type.Func. - // - // As a workaround, we inline the case for FuncType - // here and order things correctly. - // - children = nil // discard ast.Walk(FuncDecl) info subtrees - children = append(children, tok(n.Type.Func, len("func"))) - if n.Recv != nil { - children = append(children, n.Recv) - } - children = append(children, n.Name) - if n.Type.Params != nil { - children = append(children, n.Type.Params) - } - if n.Type.Results != nil { - children = append(children, n.Type.Results) - } - if n.Body != nil { - children = append(children, n.Body) - } - - case *ast.FuncLit: - // nop - - case *ast.FuncType: - if n.Func != 0 { - children = append(children, - tok(n.Func, len("func"))) - } - - case *ast.GenDecl: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - if n.Lparen != 0 { - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - } - - case *ast.GoStmt: - children = append(children, - tok(n.Go, len("go"))) - - case *ast.Ident: - children = append(children, - tok(n.NamePos, len(n.Name))) - - case *ast.IfStmt: - children = append(children, - tok(n.If, len("if"))) - - case *ast.ImportSpec: - // TODO(adonovan): ImportSpec.{Doc,EndPos}? - - case *ast.IncDecStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.IndexExpr: - children = append(children, - tok(n.Lbrack, len("{")), - tok(n.Rbrack, len("}"))) - - case *ast.InterfaceType: - children = append(children, - tok(n.Interface, len("interface"))) - - case *ast.KeyValueExpr: - children = append(children, - tok(n.Colon, len(":"))) - - case *ast.LabeledStmt: - children = append(children, - tok(n.Colon, len(":"))) - - case *ast.MapType: - children = append(children, - tok(n.Map, len("map"))) - - case *ast.ParenExpr: - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - - case *ast.RangeStmt: - children = append(children, - tok(n.For, len("for")), - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.ReturnStmt: - children = append(children, - tok(n.Return, len("return"))) - - case *ast.SelectStmt: - children = append(children, - tok(n.Select, len("select"))) - - case *ast.SelectorExpr: - // nop - - case *ast.SendStmt: - children = append(children, - tok(n.Arrow, len("<-"))) - - case *ast.SliceExpr: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Rbrack, len("]"))) - - case *ast.StarExpr: - children = append(children, tok(n.Star, len("*"))) - - case *ast.StructType: - children = append(children, tok(n.Struct, len("struct"))) - - case *ast.SwitchStmt: - children = append(children, tok(n.Switch, len("switch"))) - - case *ast.TypeAssertExpr: - children = append(children, - tok(n.Lparen-1, len(".")), - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - - case *ast.TypeSpec: - // TODO(adonovan): TypeSpec.{Doc,Comment}? - - case *ast.TypeSwitchStmt: - children = append(children, tok(n.Switch, len("switch"))) - - case *ast.UnaryExpr: - children = append(children, tok(n.OpPos, len(n.Op.String()))) - - case *ast.ValueSpec: - // TODO(adonovan): ValueSpec.{Doc,Comment}? - - case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt: - // nop - } - - // TODO(adonovan): opt: merge the logic of ast.Inspect() into - // the switch above so we can make interleaved callbacks for - // both Nodes and Tokens in the right order and avoid the need - // to sort. - sort.Sort(byPos(children)) - - return children -} - -type byPos []ast.Node - -func (sl byPos) Len() int { - return len(sl) -} -func (sl byPos) Less(i, j int) bool { - return sl[i].Pos() < sl[j].Pos() -} -func (sl byPos) Swap(i, j int) { - sl[i], sl[j] = sl[j], sl[i] -} - -// NodeDescription returns a description of the concrete type of n suitable -// for a user interface. -// -// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident, -// StarExpr) we could be much more specific given the path to the AST -// root. Perhaps we should do that. -// -func NodeDescription(n ast.Node) string { - switch n := n.(type) { - case *ast.ArrayType: - return "array type" - case *ast.AssignStmt: - return "assignment" - case *ast.BadDecl: - return "bad declaration" - case *ast.BadExpr: - return "bad expression" - case *ast.BadStmt: - return "bad statement" - case *ast.BasicLit: - return "basic literal" - case *ast.BinaryExpr: - return fmt.Sprintf("binary %s operation", n.Op) - case *ast.BlockStmt: - return "block" - case *ast.BranchStmt: - switch n.Tok { - case token.BREAK: - return "break statement" - case token.CONTINUE: - return "continue statement" - case token.GOTO: - return "goto statement" - case token.FALLTHROUGH: - return "fall-through statement" - } - case *ast.CallExpr: - return "function call (or conversion)" - case *ast.CaseClause: - return "case clause" - case *ast.ChanType: - return "channel type" - case *ast.CommClause: - return "communication clause" - case *ast.Comment: - return "comment" - case *ast.CommentGroup: - return "comment group" - case *ast.CompositeLit: - return "composite literal" - case *ast.DeclStmt: - return NodeDescription(n.Decl) + " statement" - case *ast.DeferStmt: - return "defer statement" - case *ast.Ellipsis: - return "ellipsis" - case *ast.EmptyStmt: - return "empty statement" - case *ast.ExprStmt: - return "expression statement" - case *ast.Field: - // Can be any of these: - // struct {x, y int} -- struct field(s) - // struct {T} -- anon struct field - // interface {I} -- interface embedding - // interface {f()} -- interface method - // func (A) func(B) C -- receiver, param(s), result(s) - return "field/method/parameter" - case *ast.FieldList: - return "field/method/parameter list" - case *ast.File: - return "source file" - case *ast.ForStmt: - return "for loop" - case *ast.FuncDecl: - return "function declaration" - case *ast.FuncLit: - return "function literal" - case *ast.FuncType: - return "function type" - case *ast.GenDecl: - switch n.Tok { - case token.IMPORT: - return "import declaration" - case token.CONST: - return "constant declaration" - case token.TYPE: - return "type declaration" - case token.VAR: - return "variable declaration" - } - case *ast.GoStmt: - return "go statement" - case *ast.Ident: - return "identifier" - case *ast.IfStmt: - return "if statement" - case *ast.ImportSpec: - return "import specification" - case *ast.IncDecStmt: - if n.Tok == token.INC { - return "increment statement" - } - return "decrement statement" - case *ast.IndexExpr: - return "index expression" - case *ast.InterfaceType: - return "interface type" - case *ast.KeyValueExpr: - return "key/value association" - case *ast.LabeledStmt: - return "statement label" - case *ast.MapType: - return "map type" - case *ast.Package: - return "package" - case *ast.ParenExpr: - return "parenthesized " + NodeDescription(n.X) - case *ast.RangeStmt: - return "range loop" - case *ast.ReturnStmt: - return "return statement" - case *ast.SelectStmt: - return "select statement" - case *ast.SelectorExpr: - return "selector" - case *ast.SendStmt: - return "channel send" - case *ast.SliceExpr: - return "slice expression" - case *ast.StarExpr: - return "*-operation" // load/store expr or pointer type - case *ast.StructType: - return "struct type" - case *ast.SwitchStmt: - return "switch statement" - case *ast.TypeAssertExpr: - return "type assertion" - case *ast.TypeSpec: - return "type specification" - case *ast.TypeSwitchStmt: - return "type switch" - case *ast.UnaryExpr: - return fmt.Sprintf("unary %s operation", n.Op) - case *ast.ValueSpec: - return "value specification" - - } - panic(fmt.Sprintf("unexpected node type: %T", n)) -} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/vendor/golang.org/x/tools/go/ast/astutil/imports.go deleted file mode 100644 index a47bcfa3fb0..00000000000 --- a/vendor/golang.org/x/tools/go/ast/astutil/imports.go +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package astutil contains common utilities for working with the Go AST. -package astutil - -import ( - "fmt" - "go/ast" - "go/token" - "strconv" - "strings" -) - -// AddImport adds the import path to the file f, if absent. -func AddImport(fset *token.FileSet, f *ast.File, ipath string) (added bool) { - return AddNamedImport(fset, f, "", ipath) -} - -// AddNamedImport adds the import path to the file f, if absent. -// If name is not empty, it is used to rename the import. -// -// For example, calling -// AddNamedImport(fset, f, "pathpkg", "path") -// adds -// import pathpkg "path" -func AddNamedImport(fset *token.FileSet, f *ast.File, name, ipath string) (added bool) { - if imports(f, ipath) { - return false - } - - newImport := &ast.ImportSpec{ - Path: &ast.BasicLit{ - Kind: token.STRING, - Value: strconv.Quote(ipath), - }, - } - if name != "" { - newImport.Name = &ast.Ident{Name: name} - } - - // Find an import decl to add to. - // The goal is to find an existing import - // whose import path has the longest shared - // prefix with ipath. - var ( - bestMatch = -1 // length of longest shared prefix - lastImport = -1 // index in f.Decls of the file's final import decl - impDecl *ast.GenDecl // import decl containing the best match - impIndex = -1 // spec index in impDecl containing the best match - ) - for i, decl := range f.Decls { - gen, ok := decl.(*ast.GenDecl) - if ok && gen.Tok == token.IMPORT { - lastImport = i - // Do not add to import "C", to avoid disrupting the - // association with its doc comment, breaking cgo. - if declImports(gen, "C") { - continue - } - - // Match an empty import decl if that's all that is available. - if len(gen.Specs) == 0 && bestMatch == -1 { - impDecl = gen - } - - // Compute longest shared prefix with imports in this group. - for j, spec := range gen.Specs { - impspec := spec.(*ast.ImportSpec) - n := matchLen(importPath(impspec), ipath) - if n > bestMatch { - bestMatch = n - impDecl = gen - impIndex = j - } - } - } - } - - // If no import decl found, add one after the last import. - if impDecl == nil { - impDecl = &ast.GenDecl{ - Tok: token.IMPORT, - } - if lastImport >= 0 { - impDecl.TokPos = f.Decls[lastImport].End() - } else { - // There are no existing imports. - // Our new import goes after the package declaration and after - // the comment, if any, that starts on the same line as the - // package declaration. - impDecl.TokPos = f.Package - - file := fset.File(f.Package) - pkgLine := file.Line(f.Package) - for _, c := range f.Comments { - if file.Line(c.Pos()) > pkgLine { - break - } - impDecl.TokPos = c.End() - } - } - f.Decls = append(f.Decls, nil) - copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:]) - f.Decls[lastImport+1] = impDecl - } - - // Insert new import at insertAt. - insertAt := 0 - if impIndex >= 0 { - // insert after the found import - insertAt = impIndex + 1 - } - impDecl.Specs = append(impDecl.Specs, nil) - copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:]) - impDecl.Specs[insertAt] = newImport - pos := impDecl.Pos() - if insertAt > 0 { - // If there is a comment after an existing import, preserve the comment - // position by adding the new import after the comment. - if spec, ok := impDecl.Specs[insertAt-1].(*ast.ImportSpec); ok && spec.Comment != nil { - pos = spec.Comment.End() - } else { - // Assign same position as the previous import, - // so that the sorter sees it as being in the same block. - pos = impDecl.Specs[insertAt-1].Pos() - } - } - if newImport.Name != nil { - newImport.Name.NamePos = pos - } - newImport.Path.ValuePos = pos - newImport.EndPos = pos - - // Clean up parens. impDecl contains at least one spec. - if len(impDecl.Specs) == 1 { - // Remove unneeded parens. - impDecl.Lparen = token.NoPos - } else if !impDecl.Lparen.IsValid() { - // impDecl needs parens added. - impDecl.Lparen = impDecl.Specs[0].Pos() - } - - f.Imports = append(f.Imports, newImport) - - if len(f.Decls) <= 1 { - return true - } - - // Merge all the import declarations into the first one. - var first *ast.GenDecl - for i, decl := range f.Decls { - gen, ok := decl.(*ast.GenDecl) - if !ok || gen.Tok != token.IMPORT || declImports(gen, "C") { - continue - } - if first == nil { - first = gen - continue // Don't touch the first one. - } - // Move the imports of the other import declaration to the first one. - for _, spec := range gen.Specs { - spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() - first.Specs = append(first.Specs, spec) - } - f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) - } - - return true -} - -// DeleteImport deletes the import path from the file f, if present. -func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) { - return DeleteNamedImport(fset, f, "", path) -} - -// DeleteNamedImport deletes the import with the given name and path from the file f, if present. -func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) { - var delspecs []*ast.ImportSpec - - // Find the import nodes that import path, if any. - for i := 0; i < len(f.Decls); i++ { - decl := f.Decls[i] - gen, ok := decl.(*ast.GenDecl) - if !ok || gen.Tok != token.IMPORT { - continue - } - for j := 0; j < len(gen.Specs); j++ { - spec := gen.Specs[j] - impspec := spec.(*ast.ImportSpec) - if impspec.Name == nil && name != "" { - continue - } - if impspec.Name != nil && impspec.Name.Name != name { - continue - } - if importPath(impspec) != path { - continue - } - - // We found an import spec that imports path. - // Delete it. - delspecs = append(delspecs, impspec) - deleted = true - copy(gen.Specs[j:], gen.Specs[j+1:]) - gen.Specs = gen.Specs[:len(gen.Specs)-1] - - // If this was the last import spec in this decl, - // delete the decl, too. - if len(gen.Specs) == 0 { - copy(f.Decls[i:], f.Decls[i+1:]) - f.Decls = f.Decls[:len(f.Decls)-1] - i-- - break - } else if len(gen.Specs) == 1 { - gen.Lparen = token.NoPos // drop parens - } - if j > 0 { - lastImpspec := gen.Specs[j-1].(*ast.ImportSpec) - lastLine := fset.Position(lastImpspec.Path.ValuePos).Line - line := fset.Position(impspec.Path.ValuePos).Line - - // We deleted an entry but now there may be - // a blank line-sized hole where the import was. - if line-lastLine > 1 { - // There was a blank line immediately preceding the deleted import, - // so there's no need to close the hole. - // Do nothing. - } else { - // There was no blank line. Close the hole. - fset.File(gen.Rparen).MergeLine(line) - } - } - j-- - } - } - - // Delete them from f.Imports. - for i := 0; i < len(f.Imports); i++ { - imp := f.Imports[i] - for j, del := range delspecs { - if imp == del { - copy(f.Imports[i:], f.Imports[i+1:]) - f.Imports = f.Imports[:len(f.Imports)-1] - copy(delspecs[j:], delspecs[j+1:]) - delspecs = delspecs[:len(delspecs)-1] - i-- - break - } - } - } - - if len(delspecs) > 0 { - panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs)) - } - - return -} - -// RewriteImport rewrites any import of path oldPath to path newPath. -func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) { - for _, imp := range f.Imports { - if importPath(imp) == oldPath { - rewrote = true - // record old End, because the default is to compute - // it using the length of imp.Path.Value. - imp.EndPos = imp.End() - imp.Path.Value = strconv.Quote(newPath) - } - } - return -} - -// UsesImport reports whether a given import is used. -func UsesImport(f *ast.File, path string) (used bool) { - spec := importSpec(f, path) - if spec == nil { - return - } - - name := spec.Name.String() - switch name { - case "": - // If the package name is not explicitly specified, - // make an educated guess. This is not guaranteed to be correct. - lastSlash := strings.LastIndex(path, "/") - if lastSlash == -1 { - name = path - } else { - name = path[lastSlash+1:] - } - case "_", ".": - // Not sure if this import is used - err on the side of caution. - return true - } - - ast.Walk(visitFn(func(n ast.Node) { - sel, ok := n.(*ast.SelectorExpr) - if ok && isTopName(sel.X, name) { - used = true - } - }), f) - - return -} - -type visitFn func(node ast.Node) - -func (fn visitFn) Visit(node ast.Node) ast.Visitor { - fn(node) - return fn -} - -// imports returns true if f imports path. -func imports(f *ast.File, path string) bool { - return importSpec(f, path) != nil -} - -// importSpec returns the import spec if f imports path, -// or nil otherwise. -func importSpec(f *ast.File, path string) *ast.ImportSpec { - for _, s := range f.Imports { - if importPath(s) == path { - return s - } - } - return nil -} - -// importPath returns the unquoted import path of s, -// or "" if the path is not properly quoted. -func importPath(s *ast.ImportSpec) string { - t, err := strconv.Unquote(s.Path.Value) - if err == nil { - return t - } - return "" -} - -// declImports reports whether gen contains an import of path. -func declImports(gen *ast.GenDecl, path string) bool { - if gen.Tok != token.IMPORT { - return false - } - for _, spec := range gen.Specs { - impspec := spec.(*ast.ImportSpec) - if importPath(impspec) == path { - return true - } - } - return false -} - -// matchLen returns the length of the longest path segment prefix shared by x and y. -func matchLen(x, y string) int { - n := 0 - for i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ { - if x[i] == '/' { - n++ - } - } - return n -} - -// isTopName returns true if n is a top-level unresolved identifier with the given name. -func isTopName(n ast.Expr, name string) bool { - id, ok := n.(*ast.Ident) - return ok && id.Name == name && id.Obj == nil -} - -// Imports returns the file imports grouped by paragraph. -func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec { - var groups [][]*ast.ImportSpec - - for _, decl := range f.Decls { - genDecl, ok := decl.(*ast.GenDecl) - if !ok || genDecl.Tok != token.IMPORT { - break - } - - group := []*ast.ImportSpec{} - - var lastLine int - for _, spec := range genDecl.Specs { - importSpec := spec.(*ast.ImportSpec) - pos := importSpec.Path.ValuePos - line := fset.Position(pos).Line - if lastLine > 0 && pos > 0 && line-lastLine > 1 { - groups = append(groups, group) - group = []*ast.ImportSpec{} - } - group = append(group, importSpec) - lastLine = line - } - groups = append(groups, group) - } - - return groups -} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/util.go b/vendor/golang.org/x/tools/go/ast/astutil/util.go deleted file mode 100644 index 7630629824a..00000000000 --- a/vendor/golang.org/x/tools/go/ast/astutil/util.go +++ /dev/null @@ -1,14 +0,0 @@ -package astutil - -import "go/ast" - -// Unparen returns e with any enclosing parentheses stripped. -func Unparen(e ast.Expr) ast.Expr { - for { - p, ok := e.(*ast.ParenExpr) - if !ok { - return e - } - e = p.X - } -} diff --git a/vendor/golang.org/x/tools/imports/fix.go b/vendor/golang.org/x/tools/imports/fix.go deleted file mode 100644 index 1b0213743c3..00000000000 --- a/vendor/golang.org/x/tools/imports/fix.go +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package imports - -import ( - "fmt" - "go/ast" - "go/build" - "go/parser" - "go/token" - "os" - "path" - "path/filepath" - "strings" - "sync" - - "golang.org/x/tools/go/ast/astutil" -) - -// importToGroup is a list of functions which map from an import path to -// a group number. -var importToGroup = []func(importPath string) (num int, ok bool){ - func(importPath string) (num int, ok bool) { - if strings.HasPrefix(importPath, "appengine") { - return 2, true - } - return - }, - func(importPath string) (num int, ok bool) { - if strings.Contains(importPath, ".") { - return 1, true - } - return - }, -} - -func importGroup(importPath string) int { - for _, fn := range importToGroup { - if n, ok := fn(importPath); ok { - return n - } - } - return 0 -} - -func fixImports(fset *token.FileSet, f *ast.File, filename string) (added []string, err error) { - // refs are a set of possible package references currently unsatisfied by imports. - // first key: either base package (e.g. "fmt") or renamed package - // second key: referenced package symbol (e.g. "Println") - refs := make(map[string]map[string]bool) - - // decls are the current package imports. key is base package or renamed package. - decls := make(map[string]*ast.ImportSpec) - - // collect potential uses of packages. - var visitor visitFn - visitor = visitFn(func(node ast.Node) ast.Visitor { - if node == nil { - return visitor - } - switch v := node.(type) { - case *ast.ImportSpec: - if v.Name != nil { - decls[v.Name.Name] = v - } else { - local := importPathToName(strings.Trim(v.Path.Value, `\"`)) - decls[local] = v - } - case *ast.SelectorExpr: - xident, ok := v.X.(*ast.Ident) - if !ok { - break - } - if xident.Obj != nil { - // if the parser can resolve it, it's not a package ref - break - } - pkgName := xident.Name - if refs[pkgName] == nil { - refs[pkgName] = make(map[string]bool) - } - if decls[pkgName] == nil { - refs[pkgName][v.Sel.Name] = true - } - } - return visitor - }) - ast.Walk(visitor, f) - - // Nil out any unused ImportSpecs, to be removed in following passes - unusedImport := map[string]string{} - for pkg, is := range decls { - if refs[pkg] == nil && pkg != "_" && pkg != "." { - name := "" - if is.Name != nil { - name = is.Name.Name - } - unusedImport[strings.Trim(is.Path.Value, `"`)] = name - } - } - for ipath, name := range unusedImport { - if ipath == "C" { - // Don't remove cgo stuff. - continue - } - astutil.DeleteNamedImport(fset, f, name, ipath) - } - - // Search for imports matching potential package references. - searches := 0 - type result struct { - ipath string - name string - err error - } - results := make(chan result) - for pkgName, symbols := range refs { - if len(symbols) == 0 { - continue // skip over packages already imported - } - go func(pkgName string, symbols map[string]bool) { - ipath, rename, err := findImport(pkgName, symbols, filename) - r := result{ipath: ipath, err: err} - if rename { - r.name = pkgName - } - results <- r - }(pkgName, symbols) - searches++ - } - for i := 0; i < searches; i++ { - result := <-results - if result.err != nil { - return nil, result.err - } - if result.ipath != "" { - if result.name != "" { - astutil.AddNamedImport(fset, f, result.name, result.ipath) - } else { - astutil.AddImport(fset, f, result.ipath) - } - added = append(added, result.ipath) - } - } - - return added, nil -} - -// importPathToName returns the package name for the given import path. -var importPathToName = importPathToNameGoPath - -// importPathToNameBasic assumes the package name is the base of import path. -func importPathToNameBasic(importPath string) (packageName string) { - return path.Base(importPath) -} - -// importPathToNameGoPath finds out the actual package name, as declared in its .go files. -// If there's a problem, it falls back to using importPathToNameBasic. -func importPathToNameGoPath(importPath string) (packageName string) { - if buildPkg, err := build.Import(importPath, "", 0); err == nil { - return buildPkg.Name - } else { - return importPathToNameBasic(importPath) - } -} - -type pkg struct { - importpath string // full pkg import path, e.g. "net/http" - dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt" -} - -var pkgIndexOnce = &sync.Once{} - -var pkgIndex struct { - sync.Mutex - m map[string][]pkg // shortname => []pkg, e.g "http" => "net/http" -} - -// gate is a semaphore for limiting concurrency. -type gate chan struct{} - -func (g gate) enter() { g <- struct{}{} } -func (g gate) leave() { <-g } - -// fsgate protects the OS & filesystem from too much concurrency. -// Too much disk I/O -> too many threads -> swapping and bad scheduling. -var fsgate = make(gate, 8) - -func loadPkgIndex() { - pkgIndex.Lock() - pkgIndex.m = make(map[string][]pkg) - pkgIndex.Unlock() - - var wg sync.WaitGroup - for _, path := range build.Default.SrcDirs() { - fsgate.enter() - f, err := os.Open(path) - if err != nil { - fsgate.leave() - fmt.Fprint(os.Stderr, err) - continue - } - children, err := f.Readdir(-1) - f.Close() - fsgate.leave() - if err != nil { - fmt.Fprint(os.Stderr, err) - continue - } - for _, child := range children { - if child.IsDir() { - wg.Add(1) - go func(path, name string) { - defer wg.Done() - loadPkg(&wg, path, name) - }(path, child.Name()) - } - } - } - wg.Wait() -} - -func loadPkg(wg *sync.WaitGroup, root, pkgrelpath string) { - importpath := filepath.ToSlash(pkgrelpath) - dir := filepath.Join(root, importpath) - - fsgate.enter() - defer fsgate.leave() - pkgDir, err := os.Open(dir) - if err != nil { - return - } - children, err := pkgDir.Readdir(-1) - pkgDir.Close() - if err != nil { - return - } - // hasGo tracks whether a directory actually appears to be a - // Go source code directory. If $GOPATH == $HOME, and - // $HOME/src has lots of other large non-Go projects in it, - // then the calls to importPathToName below can be expensive. - hasGo := false - for _, child := range children { - // Avoid .foo, _foo, and testdata directory trees. - name := child.Name() - if name == "" || name[0] == '.' || name[0] == '_' || name == "testdata" { - continue - } - if strings.HasSuffix(name, ".go") { - hasGo = true - } - if child.IsDir() { - wg.Add(1) - go func(root, name string) { - defer wg.Done() - loadPkg(wg, root, name) - }(root, filepath.Join(importpath, name)) - } - } - if hasGo { - shortName := importPathToName(importpath) - pkgIndex.Lock() - pkgIndex.m[shortName] = append(pkgIndex.m[shortName], pkg{ - importpath: importpath, - dir: dir, - }) - pkgIndex.Unlock() - } - -} - -// loadExports returns a list exports for a package. -var loadExports = loadExportsGoPath - -func loadExportsGoPath(dir string) map[string]bool { - exports := make(map[string]bool) - buildPkg, err := build.ImportDir(dir, 0) - if err != nil { - if strings.Contains(err.Error(), "no buildable Go source files in") { - return nil - } - fmt.Fprintf(os.Stderr, "could not import %q: %v\n", dir, err) - return nil - } - fset := token.NewFileSet() - for _, files := range [...][]string{buildPkg.GoFiles, buildPkg.CgoFiles} { - for _, file := range files { - f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0) - if err != nil { - fmt.Fprintf(os.Stderr, "could not parse %q: %v\n", file, err) - continue - } - for name := range f.Scope.Objects { - if ast.IsExported(name) { - exports[name] = true - } - } - } - } - return exports -} - -// findImport searches for a package with the given symbols. -// If no package is found, findImport returns "". -// Declared as a variable rather than a function so goimports can be easily -// extended by adding a file with an init function. -var findImport = findImportGoPath - -func findImportGoPath(pkgName string, symbols map[string]bool, filename string) (string, bool, error) { - // Fast path for the standard library. - // In the common case we hopefully never have to scan the GOPATH, which can - // be slow with moving disks. - if pkg, rename, ok := findImportStdlib(pkgName, symbols); ok { - return pkg, rename, nil - } - - // TODO(sameer): look at the import lines for other Go files in the - // local directory, since the user is likely to import the same packages - // in the current Go file. Return rename=true when the other Go files - // use a renamed package that's also used in the current file. - - pkgIndexOnce.Do(loadPkgIndex) - - // Collect exports for packages with matching names. - var ( - wg sync.WaitGroup - mu sync.Mutex - shortest string - ) - pkgIndex.Lock() - for _, pkg := range pkgIndex.m[pkgName] { - if !canUse(filename, pkg.dir) { - continue - } - wg.Add(1) - go func(importpath, dir string) { - defer wg.Done() - exports := loadExports(dir) - if exports == nil { - return - } - // If it doesn't have the right symbols, stop. - for symbol := range symbols { - if !exports[symbol] { - return - } - } - - // Devendorize for use in import statement. - if i := strings.LastIndex(importpath, "/vendor/"); i >= 0 { - importpath = importpath[i+len("/vendor/"):] - } else if strings.HasPrefix(importpath, "vendor/") { - importpath = importpath[len("vendor/"):] - } - - // Save as the answer. - // If there are multiple candidates, the shortest wins, - // to prefer "bytes" over "github.com/foo/bytes". - mu.Lock() - if shortest == "" || len(importpath) < len(shortest) || len(importpath) == len(shortest) && importpath < shortest { - shortest = importpath - } - mu.Unlock() - }(pkg.importpath, pkg.dir) - } - pkgIndex.Unlock() - wg.Wait() - - return shortest, false, nil -} - -func canUse(filename, dir string) bool { - dirSlash := filepath.ToSlash(dir) - if !strings.Contains(dirSlash, "/vendor/") && !strings.Contains(dirSlash, "/internal/") && !strings.HasSuffix(dirSlash, "/internal") { - return true - } - // Vendor or internal directory only visible from children of parent. - // That means the path from the current directory to the target directory - // can contain ../vendor or ../internal but not ../foo/vendor or ../foo/internal - // or bar/vendor or bar/internal. - // After stripping all the leading ../, the only okay place to see vendor or internal - // is at the very beginning of the path. - abs, err := filepath.Abs(filename) - if err != nil { - return false - } - rel, err := filepath.Rel(abs, dir) - if err != nil { - return false - } - relSlash := filepath.ToSlash(rel) - if i := strings.LastIndex(relSlash, "../"); i >= 0 { - relSlash = relSlash[i+len("../"):] - } - return !strings.Contains(relSlash, "/vendor/") && !strings.Contains(relSlash, "/internal/") && !strings.HasSuffix(relSlash, "/internal") -} - -type visitFn func(node ast.Node) ast.Visitor - -func (fn visitFn) Visit(node ast.Node) ast.Visitor { - return fn(node) -} - -func findImportStdlib(shortPkg string, symbols map[string]bool) (importPath string, rename, ok bool) { - for symbol := range symbols { - path := stdlib[shortPkg+"."+symbol] - if path == "" { - return "", false, false - } - if importPath != "" && importPath != path { - // Ambiguous. Symbols pointed to different things. - return "", false, false - } - importPath = path - } - return importPath, false, importPath != "" -} diff --git a/vendor/golang.org/x/tools/imports/imports.go b/vendor/golang.org/x/tools/imports/imports.go deleted file mode 100644 index c097c2b572c..00000000000 --- a/vendor/golang.org/x/tools/imports/imports.go +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package imports implements a Go pretty-printer (like package "go/format") -// that also adds or removes import statements as necessary. -package imports - -import ( - "bufio" - "bytes" - "fmt" - "go/ast" - "go/format" - "go/parser" - "go/printer" - "go/token" - "io" - "regexp" - "strconv" - "strings" - - "golang.org/x/tools/go/ast/astutil" -) - -// Options specifies options for processing files. -type Options struct { - Fragment bool // Accept fragment of a source file (no package statement) - AllErrors bool // Report all errors (not just the first 10 on different lines) - - Comments bool // Print comments (true if nil *Options provided) - TabIndent bool // Use tabs for indent (true if nil *Options provided) - TabWidth int // Tab width (8 if nil *Options provided) - - FormatOnly bool // Disable the insertion and deletion of imports -} - -// Process formats and adjusts imports for the provided file. -// If opt is nil the defaults are used. -// -// Note that filename's directory influences which imports can be chosen, -// so it is important that filename be accurate. -// To process data ``as if'' it were in filename, pass the data as a non-nil src. -func Process(filename string, src []byte, opt *Options) ([]byte, error) { - if opt == nil { - opt = &Options{Comments: true, TabIndent: true, TabWidth: 8} - } - - fileSet := token.NewFileSet() - file, adjust, err := parse(fileSet, filename, src, opt) - if err != nil { - return nil, err - } - - if !opt.FormatOnly { - _, err = fixImports(fileSet, file, filename) - if err != nil { - return nil, err - } - } - - sortImports(fileSet, file) - imps := astutil.Imports(fileSet, file) - - var spacesBefore []string // import paths we need spaces before - for _, impSection := range imps { - // Within each block of contiguous imports, see if any - // import lines are in different group numbers. If so, - // we'll need to put a space between them so it's - // compatible with gofmt. - lastGroup := -1 - for _, importSpec := range impSection { - importPath, _ := strconv.Unquote(importSpec.Path.Value) - groupNum := importGroup(importPath) - if groupNum != lastGroup && lastGroup != -1 { - spacesBefore = append(spacesBefore, importPath) - } - lastGroup = groupNum - } - - } - - printerMode := printer.UseSpaces - if opt.TabIndent { - printerMode |= printer.TabIndent - } - printConfig := &printer.Config{Mode: printerMode, Tabwidth: opt.TabWidth} - - var buf bytes.Buffer - err = printConfig.Fprint(&buf, fileSet, file) - if err != nil { - return nil, err - } - out := buf.Bytes() - if adjust != nil { - out = adjust(src, out) - } - if len(spacesBefore) > 0 { - out = addImportSpaces(bytes.NewReader(out), spacesBefore) - } - - out, err = format.Source(out) - if err != nil { - return nil, err - } - return out, nil -} - -// parse parses src, which was read from filename, -// as a Go source file or statement list. -func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) { - parserMode := parser.Mode(0) - if opt.Comments { - parserMode |= parser.ParseComments - } - if opt.AllErrors { - parserMode |= parser.AllErrors - } - - // Try as whole source file. - file, err := parser.ParseFile(fset, filename, src, parserMode) - if err == nil { - return file, nil, nil - } - // If the error is that the source file didn't begin with a - // package line and we accept fragmented input, fall through to - // try as a source fragment. Stop and return on any other error. - if !opt.Fragment || !strings.Contains(err.Error(), "expected 'package'") { - return nil, nil, err - } - - // If this is a declaration list, make it a source file - // by inserting a package clause. - // Insert using a ;, not a newline, so that the line numbers - // in psrc match the ones in src. - psrc := append([]byte("package main;"), src...) - file, err = parser.ParseFile(fset, filename, psrc, parserMode) - if err == nil { - // If a main function exists, we will assume this is a main - // package and leave the file. - if containsMainFunc(file) { - return file, nil, nil - } - - adjust := func(orig, src []byte) []byte { - // Remove the package clause. - // Gofmt has turned the ; into a \n. - src = src[len("package main\n"):] - return matchSpace(orig, src) - } - return file, adjust, nil - } - // If the error is that the source file didn't begin with a - // declaration, fall through to try as a statement list. - // Stop and return on any other error. - if !strings.Contains(err.Error(), "expected declaration") { - return nil, nil, err - } - - // If this is a statement list, make it a source file - // by inserting a package clause and turning the list - // into a function body. This handles expressions too. - // Insert using a ;, not a newline, so that the line numbers - // in fsrc match the ones in src. - fsrc := append(append([]byte("package p; func _() {"), src...), '}') - file, err = parser.ParseFile(fset, filename, fsrc, parserMode) - if err == nil { - adjust := func(orig, src []byte) []byte { - // Remove the wrapping. - // Gofmt has turned the ; into a \n\n. - src = src[len("package p\n\nfunc _() {"):] - src = src[:len(src)-len("}\n")] - // Gofmt has also indented the function body one level. - // Remove that indent. - src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1) - return matchSpace(orig, src) - } - return file, adjust, nil - } - - // Failed, and out of options. - return nil, nil, err -} - -// containsMainFunc checks if a file contains a function declaration with the -// function signature 'func main()' -func containsMainFunc(file *ast.File) bool { - for _, decl := range file.Decls { - if f, ok := decl.(*ast.FuncDecl); ok { - if f.Name.Name != "main" { - continue - } - - if len(f.Type.Params.List) != 0 { - continue - } - - if f.Type.Results != nil && len(f.Type.Results.List) != 0 { - continue - } - - return true - } - } - - return false -} - -func cutSpace(b []byte) (before, middle, after []byte) { - i := 0 - for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') { - i++ - } - j := len(b) - for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') { - j-- - } - if i <= j { - return b[:i], b[i:j], b[j:] - } - return nil, nil, b[j:] -} - -// matchSpace reformats src to use the same space context as orig. -// 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src. -// 2) matchSpace copies the indentation of the first non-blank line in orig -// to every non-blank line in src. -// 3) matchSpace copies the trailing space from orig and uses it in place -// of src's trailing space. -func matchSpace(orig []byte, src []byte) []byte { - before, _, after := cutSpace(orig) - i := bytes.LastIndex(before, []byte{'\n'}) - before, indent := before[:i+1], before[i+1:] - - _, src, _ = cutSpace(src) - - var b bytes.Buffer - b.Write(before) - for len(src) > 0 { - line := src - if i := bytes.IndexByte(line, '\n'); i >= 0 { - line, src = line[:i+1], line[i+1:] - } else { - src = nil - } - if len(line) > 0 && line[0] != '\n' { // not blank - b.Write(indent) - } - b.Write(line) - } - b.Write(after) - return b.Bytes() -} - -var impLine = regexp.MustCompile(`^\s+(?:[\w\.]+\s+)?"(.+)"`) - -func addImportSpaces(r io.Reader, breaks []string) []byte { - var out bytes.Buffer - sc := bufio.NewScanner(r) - inImports := false - done := false - for sc.Scan() { - s := sc.Text() - - if !inImports && !done && strings.HasPrefix(s, "import") { - inImports = true - } - if inImports && (strings.HasPrefix(s, "var") || - strings.HasPrefix(s, "func") || - strings.HasPrefix(s, "const") || - strings.HasPrefix(s, "type")) { - done = true - inImports = false - } - if inImports && len(breaks) > 0 { - if m := impLine.FindStringSubmatch(s); m != nil { - if m[1] == string(breaks[0]) { - out.WriteByte('\n') - breaks = breaks[1:] - } - } - } - - fmt.Fprintln(&out, s) - } - return out.Bytes() -} diff --git a/vendor/golang.org/x/tools/imports/mkindex.go b/vendor/golang.org/x/tools/imports/mkindex.go deleted file mode 100644 index 755e2394f2d..00000000000 --- a/vendor/golang.org/x/tools/imports/mkindex.go +++ /dev/null @@ -1,173 +0,0 @@ -// +build ignore - -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Command mkindex creates the file "pkgindex.go" containing an index of the Go -// standard library. The file is intended to be built as part of the imports -// package, so that the package may be used in environments where a GOROOT is -// not available (such as App Engine). -package main - -import ( - "bytes" - "fmt" - "go/ast" - "go/build" - "go/format" - "go/parser" - "go/token" - "io/ioutil" - "log" - "os" - "path" - "path/filepath" - "strings" -) - -var ( - pkgIndex = make(map[string][]pkg) - exports = make(map[string]map[string]bool) -) - -func main() { - // Don't use GOPATH. - ctx := build.Default - ctx.GOPATH = "" - - // Populate pkgIndex global from GOROOT. - for _, path := range ctx.SrcDirs() { - f, err := os.Open(path) - if err != nil { - log.Print(err) - continue - } - children, err := f.Readdir(-1) - f.Close() - if err != nil { - log.Print(err) - continue - } - for _, child := range children { - if child.IsDir() { - loadPkg(path, child.Name()) - } - } - } - // Populate exports global. - for _, ps := range pkgIndex { - for _, p := range ps { - e := loadExports(p.dir) - if e != nil { - exports[p.dir] = e - } - } - } - - // Construct source file. - var buf bytes.Buffer - fmt.Fprint(&buf, pkgIndexHead) - fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex) - fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports) - src := buf.Bytes() - - // Replace main.pkg type name with pkg. - src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1) - // Replace actual GOROOT with "/go". - src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1) - // Add some line wrapping. - src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1) - src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1) - - var err error - src, err = format.Source(src) - if err != nil { - log.Fatal(err) - } - - // Write out source file. - err = ioutil.WriteFile("pkgindex.go", src, 0644) - if err != nil { - log.Fatal(err) - } -} - -const pkgIndexHead = `package imports - -func init() { - pkgIndexOnce.Do(func() { - pkgIndex.m = pkgIndexMaster - }) - loadExports = func(dir string) map[string]bool { - return exportsMaster[dir] - } -} -` - -type pkg struct { - importpath string // full pkg import path, e.g. "net/http" - dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt" -} - -var fset = token.NewFileSet() - -func loadPkg(root, importpath string) { - shortName := path.Base(importpath) - if shortName == "testdata" { - return - } - - dir := filepath.Join(root, importpath) - pkgIndex[shortName] = append(pkgIndex[shortName], pkg{ - importpath: importpath, - dir: dir, - }) - - pkgDir, err := os.Open(dir) - if err != nil { - return - } - children, err := pkgDir.Readdir(-1) - pkgDir.Close() - if err != nil { - return - } - for _, child := range children { - name := child.Name() - if name == "" { - continue - } - if c := name[0]; c == '.' || ('0' <= c && c <= '9') { - continue - } - if child.IsDir() { - loadPkg(root, filepath.Join(importpath, name)) - } - } -} - -func loadExports(dir string) map[string]bool { - exports := make(map[string]bool) - buildPkg, err := build.ImportDir(dir, 0) - if err != nil { - if strings.Contains(err.Error(), "no buildable Go source files in") { - return nil - } - log.Printf("could not import %q: %v", dir, err) - return nil - } - for _, file := range buildPkg.GoFiles { - f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0) - if err != nil { - log.Printf("could not parse %q: %v", file, err) - continue - } - for name := range f.Scope.Objects { - if ast.IsExported(name) { - exports[name] = true - } - } - } - return exports -} diff --git a/vendor/golang.org/x/tools/imports/mkstdlib.go b/vendor/golang.org/x/tools/imports/mkstdlib.go deleted file mode 100644 index e2dca760066..00000000000 --- a/vendor/golang.org/x/tools/imports/mkstdlib.go +++ /dev/null @@ -1,93 +0,0 @@ -// +build ignore - -// mkstdlib generates the zstdlib.go file, containing the Go standard -// library API symbols. It's baked into the binary to avoid scanning -// GOPATH in the common case. -package main - -import ( - "bufio" - "bytes" - "fmt" - "go/format" - "io" - "log" - "os" - "path" - "path/filepath" - "regexp" - "sort" - "strings" -) - -func mustOpen(name string) io.Reader { - f, err := os.Open(name) - if err != nil { - log.Fatal(err) - } - return f -} - -func api(base string) string { - return filepath.Join(os.Getenv("GOROOT"), "api", base) -} - -var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`) - -func main() { - var buf bytes.Buffer - outf := func(format string, args ...interface{}) { - fmt.Fprintf(&buf, format, args...) - } - outf("// AUTO-GENERATED BY mkstdlib.go\n\n") - outf("package imports\n") - outf("var stdlib = map[string]string{\n") - f := io.MultiReader( - mustOpen(api("go1.txt")), - mustOpen(api("go1.1.txt")), - mustOpen(api("go1.2.txt")), - mustOpen(api("go1.3.txt")), - mustOpen(api("go1.4.txt")), - mustOpen(api("go1.5.txt")), - ) - sc := bufio.NewScanner(f) - fullImport := map[string]string{} // "zip.NewReader" => "archive/zip" - ambiguous := map[string]bool{} - var keys []string - for sc.Scan() { - l := sc.Text() - has := func(v string) bool { return strings.Contains(l, v) } - if has("struct, ") || has("interface, ") || has(", method (") { - continue - } - if m := sym.FindStringSubmatch(l); m != nil { - full := m[1] - key := path.Base(full) + "." + m[2] - if exist, ok := fullImport[key]; ok { - if exist != full { - ambiguous[key] = true - } - } else { - fullImport[key] = full - keys = append(keys, key) - } - } - } - if err := sc.Err(); err != nil { - log.Fatal(err) - } - sort.Strings(keys) - for _, key := range keys { - if ambiguous[key] { - outf("\t// %q is ambiguous\n", key) - } else { - outf("\t%q: %q,\n", key, fullImport[key]) - } - } - outf("}\n") - fmtbuf, err := format.Source(buf.Bytes()) - if err != nil { - log.Fatal(err) - } - os.Stdout.Write(fmtbuf) -} diff --git a/vendor/golang.org/x/tools/imports/sortimports.go b/vendor/golang.org/x/tools/imports/sortimports.go deleted file mode 100644 index 653afc51776..00000000000 --- a/vendor/golang.org/x/tools/imports/sortimports.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Hacked up copy of go/ast/import.go - -package imports - -import ( - "go/ast" - "go/token" - "sort" - "strconv" -) - -// sortImports sorts runs of consecutive import lines in import blocks in f. -// It also removes duplicate imports when it is possible to do so without data loss. -func sortImports(fset *token.FileSet, f *ast.File) { - for i, d := range f.Decls { - d, ok := d.(*ast.GenDecl) - if !ok || d.Tok != token.IMPORT { - // Not an import declaration, so we're done. - // Imports are always first. - break - } - - if len(d.Specs) == 0 { - // Empty import block, remove it. - f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) - } - - if !d.Lparen.IsValid() { - // Not a block: sorted by default. - continue - } - - // Identify and sort runs of specs on successive lines. - i := 0 - specs := d.Specs[:0] - for j, s := range d.Specs { - if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line { - // j begins a new run. End this one. - specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...) - i = j - } - } - specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...) - d.Specs = specs - - // Deduping can leave a blank line before the rparen; clean that up. - if len(d.Specs) > 0 { - lastSpec := d.Specs[len(d.Specs)-1] - lastLine := fset.Position(lastSpec.Pos()).Line - if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 { - fset.File(d.Rparen).MergeLine(rParenLine - 1) - } - } - } -} - -func importPath(s ast.Spec) string { - t, err := strconv.Unquote(s.(*ast.ImportSpec).Path.Value) - if err == nil { - return t - } - return "" -} - -func importName(s ast.Spec) string { - n := s.(*ast.ImportSpec).Name - if n == nil { - return "" - } - return n.Name -} - -func importComment(s ast.Spec) string { - c := s.(*ast.ImportSpec).Comment - if c == nil { - return "" - } - return c.Text() -} - -// collapse indicates whether prev may be removed, leaving only next. -func collapse(prev, next ast.Spec) bool { - if importPath(next) != importPath(prev) || importName(next) != importName(prev) { - return false - } - return prev.(*ast.ImportSpec).Comment == nil -} - -type posSpan struct { - Start token.Pos - End token.Pos -} - -func sortSpecs(fset *token.FileSet, f *ast.File, specs []ast.Spec) []ast.Spec { - // Can't short-circuit here even if specs are already sorted, - // since they might yet need deduplication. - // A lone import, however, may be safely ignored. - if len(specs) <= 1 { - return specs - } - - // Record positions for specs. - pos := make([]posSpan, len(specs)) - for i, s := range specs { - pos[i] = posSpan{s.Pos(), s.End()} - } - - // Identify comments in this range. - // Any comment from pos[0].Start to the final line counts. - lastLine := fset.Position(pos[len(pos)-1].End).Line - cstart := len(f.Comments) - cend := len(f.Comments) - for i, g := range f.Comments { - if g.Pos() < pos[0].Start { - continue - } - if i < cstart { - cstart = i - } - if fset.Position(g.End()).Line > lastLine { - cend = i - break - } - } - comments := f.Comments[cstart:cend] - - // Assign each comment to the import spec preceding it. - importComment := map[*ast.ImportSpec][]*ast.CommentGroup{} - specIndex := 0 - for _, g := range comments { - for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() { - specIndex++ - } - s := specs[specIndex].(*ast.ImportSpec) - importComment[s] = append(importComment[s], g) - } - - // Sort the import specs by import path. - // Remove duplicates, when possible without data loss. - // Reassign the import paths to have the same position sequence. - // Reassign each comment to abut the end of its spec. - // Sort the comments by new position. - sort.Sort(byImportSpec(specs)) - - // Dedup. Thanks to our sorting, we can just consider - // adjacent pairs of imports. - deduped := specs[:0] - for i, s := range specs { - if i == len(specs)-1 || !collapse(s, specs[i+1]) { - deduped = append(deduped, s) - } else { - p := s.Pos() - fset.File(p).MergeLine(fset.Position(p).Line) - } - } - specs = deduped - - // Fix up comment positions - for i, s := range specs { - s := s.(*ast.ImportSpec) - if s.Name != nil { - s.Name.NamePos = pos[i].Start - } - s.Path.ValuePos = pos[i].Start - s.EndPos = pos[i].End - for _, g := range importComment[s] { - for _, c := range g.List { - c.Slash = pos[i].End - } - } - } - - sort.Sort(byCommentPos(comments)) - - return specs -} - -type byImportSpec []ast.Spec // slice of *ast.ImportSpec - -func (x byImportSpec) Len() int { return len(x) } -func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x byImportSpec) Less(i, j int) bool { - ipath := importPath(x[i]) - jpath := importPath(x[j]) - - igroup := importGroup(ipath) - jgroup := importGroup(jpath) - if igroup != jgroup { - return igroup < jgroup - } - - if ipath != jpath { - return ipath < jpath - } - iname := importName(x[i]) - jname := importName(x[j]) - - if iname != jname { - return iname < jname - } - return importComment(x[i]) < importComment(x[j]) -} - -type byCommentPos []*ast.CommentGroup - -func (x byCommentPos) Len() int { return len(x) } -func (x byCommentPos) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() } diff --git a/vendor/golang.org/x/tools/imports/zstdlib.go b/vendor/golang.org/x/tools/imports/zstdlib.go deleted file mode 100644 index 39eb3c74b1c..00000000000 --- a/vendor/golang.org/x/tools/imports/zstdlib.go +++ /dev/null @@ -1,9038 +0,0 @@ -// AUTO-GENERATED BY mkstdlib.go - -package imports - -var stdlib = map[string]string{ - "adler32.Checksum": "hash/adler32", - "adler32.New": "hash/adler32", - "adler32.Size": "hash/adler32", - "aes.BlockSize": "crypto/aes", - "aes.KeySizeError": "crypto/aes", - "aes.NewCipher": "crypto/aes", - "ascii85.CorruptInputError": "encoding/ascii85", - "ascii85.Decode": "encoding/ascii85", - "ascii85.Encode": "encoding/ascii85", - "ascii85.MaxEncodedLen": "encoding/ascii85", - "ascii85.NewDecoder": "encoding/ascii85", - "ascii85.NewEncoder": "encoding/ascii85", - "asn1.BitString": "encoding/asn1", - "asn1.Enumerated": "encoding/asn1", - "asn1.Flag": "encoding/asn1", - "asn1.Marshal": "encoding/asn1", - "asn1.ObjectIdentifier": "encoding/asn1", - "asn1.RawContent": "encoding/asn1", - "asn1.RawValue": "encoding/asn1", - "asn1.StructuralError": "encoding/asn1", - "asn1.SyntaxError": "encoding/asn1", - "asn1.Unmarshal": "encoding/asn1", - "asn1.UnmarshalWithParams": "encoding/asn1", - "ast.ArrayType": "go/ast", - "ast.AssignStmt": "go/ast", - "ast.Bad": "go/ast", - "ast.BadDecl": "go/ast", - "ast.BadExpr": "go/ast", - "ast.BadStmt": "go/ast", - "ast.BasicLit": "go/ast", - "ast.BinaryExpr": "go/ast", - "ast.BlockStmt": "go/ast", - "ast.BranchStmt": "go/ast", - "ast.CallExpr": "go/ast", - "ast.CaseClause": "go/ast", - "ast.ChanDir": "go/ast", - "ast.ChanType": "go/ast", - "ast.CommClause": "go/ast", - "ast.Comment": "go/ast", - "ast.CommentGroup": "go/ast", - "ast.CommentMap": "go/ast", - "ast.CompositeLit": "go/ast", - "ast.Con": "go/ast", - "ast.DeclStmt": "go/ast", - "ast.DeferStmt": "go/ast", - "ast.Ellipsis": "go/ast", - "ast.EmptyStmt": "go/ast", - "ast.ExprStmt": "go/ast", - "ast.Field": "go/ast", - "ast.FieldFilter": "go/ast", - "ast.FieldList": "go/ast", - "ast.File": "go/ast", - "ast.FileExports": "go/ast", - "ast.Filter": "go/ast", - "ast.FilterDecl": "go/ast", - "ast.FilterFile": "go/ast", - "ast.FilterFuncDuplicates": "go/ast", - "ast.FilterImportDuplicates": "go/ast", - "ast.FilterPackage": "go/ast", - "ast.FilterUnassociatedComments": "go/ast", - "ast.ForStmt": "go/ast", - "ast.Fprint": "go/ast", - "ast.Fun": "go/ast", - "ast.FuncDecl": "go/ast", - "ast.FuncLit": "go/ast", - "ast.FuncType": "go/ast", - "ast.GenDecl": "go/ast", - "ast.GoStmt": "go/ast", - "ast.Ident": "go/ast", - "ast.IfStmt": "go/ast", - "ast.ImportSpec": "go/ast", - "ast.Importer": "go/ast", - "ast.IncDecStmt": "go/ast", - "ast.IndexExpr": "go/ast", - "ast.Inspect": "go/ast", - "ast.InterfaceType": "go/ast", - "ast.IsExported": "go/ast", - "ast.KeyValueExpr": "go/ast", - "ast.LabeledStmt": "go/ast", - "ast.Lbl": "go/ast", - "ast.MapType": "go/ast", - "ast.MergeMode": "go/ast", - "ast.MergePackageFiles": "go/ast", - "ast.NewCommentMap": "go/ast", - "ast.NewIdent": "go/ast", - "ast.NewObj": "go/ast", - "ast.NewPackage": "go/ast", - "ast.NewScope": "go/ast", - "ast.Node": "go/ast", - "ast.NotNilFilter": "go/ast", - "ast.ObjKind": "go/ast", - "ast.Object": "go/ast", - "ast.Package": "go/ast", - "ast.PackageExports": "go/ast", - "ast.ParenExpr": "go/ast", - "ast.Pkg": "go/ast", - "ast.Print": "go/ast", - "ast.RECV": "go/ast", - "ast.RangeStmt": "go/ast", - "ast.ReturnStmt": "go/ast", - "ast.SEND": "go/ast", - "ast.Scope": "go/ast", - "ast.SelectStmt": "go/ast", - "ast.SelectorExpr": "go/ast", - "ast.SendStmt": "go/ast", - "ast.SliceExpr": "go/ast", - "ast.SortImports": "go/ast", - "ast.StarExpr": "go/ast", - "ast.StructType": "go/ast", - "ast.SwitchStmt": "go/ast", - "ast.Typ": "go/ast", - "ast.TypeAssertExpr": "go/ast", - "ast.TypeSpec": "go/ast", - "ast.TypeSwitchStmt": "go/ast", - "ast.UnaryExpr": "go/ast", - "ast.ValueSpec": "go/ast", - "ast.Var": "go/ast", - "ast.Visitor": "go/ast", - "ast.Walk": "go/ast", - "atomic.AddInt32": "sync/atomic", - "atomic.AddInt64": "sync/atomic", - "atomic.AddUint32": "sync/atomic", - "atomic.AddUint64": "sync/atomic", - "atomic.AddUintptr": "sync/atomic", - "atomic.CompareAndSwapInt32": "sync/atomic", - "atomic.CompareAndSwapInt64": "sync/atomic", - "atomic.CompareAndSwapPointer": "sync/atomic", - "atomic.CompareAndSwapUint32": "sync/atomic", - "atomic.CompareAndSwapUint64": "sync/atomic", - "atomic.CompareAndSwapUintptr": "sync/atomic", - "atomic.LoadInt32": "sync/atomic", - "atomic.LoadInt64": "sync/atomic", - "atomic.LoadPointer": "sync/atomic", - "atomic.LoadUint32": "sync/atomic", - "atomic.LoadUint64": "sync/atomic", - "atomic.LoadUintptr": "sync/atomic", - "atomic.StoreInt32": "sync/atomic", - "atomic.StoreInt64": "sync/atomic", - "atomic.StorePointer": "sync/atomic", - "atomic.StoreUint32": "sync/atomic", - "atomic.StoreUint64": "sync/atomic", - "atomic.StoreUintptr": "sync/atomic", - "atomic.SwapInt32": "sync/atomic", - "atomic.SwapInt64": "sync/atomic", - "atomic.SwapPointer": "sync/atomic", - "atomic.SwapUint32": "sync/atomic", - "atomic.SwapUint64": "sync/atomic", - "atomic.SwapUintptr": "sync/atomic", - "atomic.Value": "sync/atomic", - "base32.CorruptInputError": "encoding/base32", - "base32.Encoding": "encoding/base32", - "base32.HexEncoding": "encoding/base32", - "base32.NewDecoder": "encoding/base32", - "base32.NewEncoder": "encoding/base32", - "base32.NewEncoding": "encoding/base32", - "base32.StdEncoding": "encoding/base32", - "base64.CorruptInputError": "encoding/base64", - "base64.Encoding": "encoding/base64", - "base64.NewDecoder": "encoding/base64", - "base64.NewEncoder": "encoding/base64", - "base64.NewEncoding": "encoding/base64", - "base64.NoPadding": "encoding/base64", - "base64.RawStdEncoding": "encoding/base64", - "base64.RawURLEncoding": "encoding/base64", - "base64.StdEncoding": "encoding/base64", - "base64.StdPadding": "encoding/base64", - "base64.URLEncoding": "encoding/base64", - "big.Above": "math/big", - "big.Accuracy": "math/big", - "big.AwayFromZero": "math/big", - "big.Below": "math/big", - "big.ErrNaN": "math/big", - "big.Exact": "math/big", - "big.Float": "math/big", - "big.Int": "math/big", - "big.Jacobi": "math/big", - "big.MaxBase": "math/big", - "big.MaxExp": "math/big", - "big.MaxPrec": "math/big", - "big.MinExp": "math/big", - "big.NewFloat": "math/big", - "big.NewInt": "math/big", - "big.NewRat": "math/big", - "big.ParseFloat": "math/big", - "big.Rat": "math/big", - "big.RoundingMode": "math/big", - "big.ToNearestAway": "math/big", - "big.ToNearestEven": "math/big", - "big.ToNegativeInf": "math/big", - "big.ToPositiveInf": "math/big", - "big.ToZero": "math/big", - "big.Word": "math/big", - "binary.BigEndian": "encoding/binary", - "binary.ByteOrder": "encoding/binary", - "binary.LittleEndian": "encoding/binary", - "binary.MaxVarintLen16": "encoding/binary", - "binary.MaxVarintLen32": "encoding/binary", - "binary.MaxVarintLen64": "encoding/binary", - "binary.PutUvarint": "encoding/binary", - "binary.PutVarint": "encoding/binary", - "binary.Read": "encoding/binary", - "binary.ReadUvarint": "encoding/binary", - "binary.ReadVarint": "encoding/binary", - "binary.Size": "encoding/binary", - "binary.Uvarint": "encoding/binary", - "binary.Varint": "encoding/binary", - "binary.Write": "encoding/binary", - "bufio.ErrAdvanceTooFar": "bufio", - "bufio.ErrBufferFull": "bufio", - "bufio.ErrInvalidUnreadByte": "bufio", - "bufio.ErrInvalidUnreadRune": "bufio", - "bufio.ErrNegativeAdvance": "bufio", - "bufio.ErrNegativeCount": "bufio", - "bufio.ErrTooLong": "bufio", - "bufio.MaxScanTokenSize": "bufio", - "bufio.NewReadWriter": "bufio", - "bufio.NewReader": "bufio", - "bufio.NewReaderSize": "bufio", - "bufio.NewScanner": "bufio", - "bufio.NewWriter": "bufio", - "bufio.NewWriterSize": "bufio", - "bufio.ReadWriter": "bufio", - "bufio.Reader": "bufio", - "bufio.ScanBytes": "bufio", - "bufio.ScanLines": "bufio", - "bufio.ScanRunes": "bufio", - "bufio.ScanWords": "bufio", - "bufio.Scanner": "bufio", - "bufio.SplitFunc": "bufio", - "bufio.Writer": "bufio", - "build.AllowBinary": "go/build", - "build.ArchChar": "go/build", - "build.Context": "go/build", - "build.Default": "go/build", - "build.FindOnly": "go/build", - "build.Import": "go/build", - "build.ImportComment": "go/build", - "build.ImportDir": "go/build", - "build.ImportMode": "go/build", - "build.IsLocalImport": "go/build", - "build.MultiplePackageError": "go/build", - "build.NoGoError": "go/build", - "build.Package": "go/build", - "build.ToolDir": "go/build", - "bytes.Buffer": "bytes", - "bytes.Compare": "bytes", - "bytes.Contains": "bytes", - "bytes.Count": "bytes", - "bytes.Equal": "bytes", - "bytes.EqualFold": "bytes", - "bytes.ErrTooLarge": "bytes", - "bytes.Fields": "bytes", - "bytes.FieldsFunc": "bytes", - "bytes.HasPrefix": "bytes", - "bytes.HasSuffix": "bytes", - "bytes.Index": "bytes", - "bytes.IndexAny": "bytes", - "bytes.IndexByte": "bytes", - "bytes.IndexFunc": "bytes", - "bytes.IndexRune": "bytes", - "bytes.Join": "bytes", - "bytes.LastIndex": "bytes", - "bytes.LastIndexAny": "bytes", - "bytes.LastIndexByte": "bytes", - "bytes.LastIndexFunc": "bytes", - "bytes.Map": "bytes", - "bytes.MinRead": "bytes", - "bytes.NewBuffer": "bytes", - "bytes.NewBufferString": "bytes", - "bytes.NewReader": "bytes", - "bytes.Reader": "bytes", - "bytes.Repeat": "bytes", - "bytes.Replace": "bytes", - "bytes.Runes": "bytes", - "bytes.Split": "bytes", - "bytes.SplitAfter": "bytes", - "bytes.SplitAfterN": "bytes", - "bytes.SplitN": "bytes", - "bytes.Title": "bytes", - "bytes.ToLower": "bytes", - "bytes.ToLowerSpecial": "bytes", - "bytes.ToTitle": "bytes", - "bytes.ToTitleSpecial": "bytes", - "bytes.ToUpper": "bytes", - "bytes.ToUpperSpecial": "bytes", - "bytes.Trim": "bytes", - "bytes.TrimFunc": "bytes", - "bytes.TrimLeft": "bytes", - "bytes.TrimLeftFunc": "bytes", - "bytes.TrimPrefix": "bytes", - "bytes.TrimRight": "bytes", - "bytes.TrimRightFunc": "bytes", - "bytes.TrimSpace": "bytes", - "bytes.TrimSuffix": "bytes", - "bzip2.NewReader": "compress/bzip2", - "bzip2.StructuralError": "compress/bzip2", - "cgi.Handler": "net/http/cgi", - "cgi.Request": "net/http/cgi", - "cgi.RequestFromMap": "net/http/cgi", - "cgi.Serve": "net/http/cgi", - "cipher.AEAD": "crypto/cipher", - "cipher.Block": "crypto/cipher", - "cipher.BlockMode": "crypto/cipher", - "cipher.NewCBCDecrypter": "crypto/cipher", - "cipher.NewCBCEncrypter": "crypto/cipher", - "cipher.NewCFBDecrypter": "crypto/cipher", - "cipher.NewCFBEncrypter": "crypto/cipher", - "cipher.NewCTR": "crypto/cipher", - "cipher.NewGCM": "crypto/cipher", - "cipher.NewGCMWithNonceSize": "crypto/cipher", - "cipher.NewOFB": "crypto/cipher", - "cipher.Stream": "crypto/cipher", - "cipher.StreamReader": "crypto/cipher", - "cipher.StreamWriter": "crypto/cipher", - "cmplx.Abs": "math/cmplx", - "cmplx.Acos": "math/cmplx", - "cmplx.Acosh": "math/cmplx", - "cmplx.Asin": "math/cmplx", - "cmplx.Asinh": "math/cmplx", - "cmplx.Atan": "math/cmplx", - "cmplx.Atanh": "math/cmplx", - "cmplx.Conj": "math/cmplx", - "cmplx.Cos": "math/cmplx", - "cmplx.Cosh": "math/cmplx", - "cmplx.Cot": "math/cmplx", - "cmplx.Exp": "math/cmplx", - "cmplx.Inf": "math/cmplx", - "cmplx.IsInf": "math/cmplx", - "cmplx.IsNaN": "math/cmplx", - "cmplx.Log": "math/cmplx", - "cmplx.Log10": "math/cmplx", - "cmplx.NaN": "math/cmplx", - "cmplx.Phase": "math/cmplx", - "cmplx.Polar": "math/cmplx", - "cmplx.Pow": "math/cmplx", - "cmplx.Rect": "math/cmplx", - "cmplx.Sin": "math/cmplx", - "cmplx.Sinh": "math/cmplx", - "cmplx.Sqrt": "math/cmplx", - "cmplx.Tan": "math/cmplx", - "cmplx.Tanh": "math/cmplx", - "color.Alpha": "image/color", - "color.Alpha16": "image/color", - "color.Alpha16Model": "image/color", - "color.AlphaModel": "image/color", - "color.Black": "image/color", - "color.CMYK": "image/color", - "color.CMYKModel": "image/color", - "color.CMYKToRGB": "image/color", - "color.Color": "image/color", - "color.Gray": "image/color", - "color.Gray16": "image/color", - "color.Gray16Model": "image/color", - "color.GrayModel": "image/color", - "color.Model": "image/color", - "color.ModelFunc": "image/color", - "color.NRGBA": "image/color", - "color.NRGBA64": "image/color", - "color.NRGBA64Model": "image/color", - "color.NRGBAModel": "image/color", - "color.Opaque": "image/color", - "color.Palette": "image/color", - "color.RGBA": "image/color", - "color.RGBA64": "image/color", - "color.RGBA64Model": "image/color", - "color.RGBAModel": "image/color", - "color.RGBToCMYK": "image/color", - "color.RGBToYCbCr": "image/color", - "color.Transparent": "image/color", - "color.White": "image/color", - "color.YCbCr": "image/color", - "color.YCbCrModel": "image/color", - "color.YCbCrToRGB": "image/color", - "constant.BinaryOp": "go/constant", - "constant.BitLen": "go/constant", - "constant.Bool": "go/constant", - "constant.BoolVal": "go/constant", - "constant.Bytes": "go/constant", - "constant.Compare": "go/constant", - "constant.Complex": "go/constant", - "constant.Denom": "go/constant", - "constant.Float": "go/constant", - "constant.Float32Val": "go/constant", - "constant.Float64Val": "go/constant", - "constant.Imag": "go/constant", - "constant.Int": "go/constant", - "constant.Int64Val": "go/constant", - "constant.Kind": "go/constant", - "constant.MakeBool": "go/constant", - "constant.MakeFloat64": "go/constant", - "constant.MakeFromBytes": "go/constant", - "constant.MakeFromLiteral": "go/constant", - "constant.MakeImag": "go/constant", - "constant.MakeInt64": "go/constant", - "constant.MakeString": "go/constant", - "constant.MakeUint64": "go/constant", - "constant.MakeUnknown": "go/constant", - "constant.Num": "go/constant", - "constant.Real": "go/constant", - "constant.Shift": "go/constant", - "constant.Sign": "go/constant", - "constant.String": "go/constant", - "constant.StringVal": "go/constant", - "constant.Uint64Val": "go/constant", - "constant.UnaryOp": "go/constant", - "constant.Unknown": "go/constant", - "cookiejar.Jar": "net/http/cookiejar", - "cookiejar.New": "net/http/cookiejar", - "cookiejar.Options": "net/http/cookiejar", - "cookiejar.PublicSuffixList": "net/http/cookiejar", - "crc32.Castagnoli": "hash/crc32", - "crc32.Checksum": "hash/crc32", - "crc32.ChecksumIEEE": "hash/crc32", - "crc32.IEEE": "hash/crc32", - "crc32.IEEETable": "hash/crc32", - "crc32.Koopman": "hash/crc32", - "crc32.MakeTable": "hash/crc32", - "crc32.New": "hash/crc32", - "crc32.NewIEEE": "hash/crc32", - "crc32.Size": "hash/crc32", - "crc32.Table": "hash/crc32", - "crc32.Update": "hash/crc32", - "crc64.Checksum": "hash/crc64", - "crc64.ECMA": "hash/crc64", - "crc64.ISO": "hash/crc64", - "crc64.MakeTable": "hash/crc64", - "crc64.New": "hash/crc64", - "crc64.Size": "hash/crc64", - "crc64.Table": "hash/crc64", - "crc64.Update": "hash/crc64", - "crypto.Decrypter": "crypto", - "crypto.DecrypterOpts": "crypto", - "crypto.Hash": "crypto", - "crypto.MD4": "crypto", - "crypto.MD5": "crypto", - "crypto.MD5SHA1": "crypto", - "crypto.PrivateKey": "crypto", - "crypto.PublicKey": "crypto", - "crypto.RIPEMD160": "crypto", - "crypto.RegisterHash": "crypto", - "crypto.SHA1": "crypto", - "crypto.SHA224": "crypto", - "crypto.SHA256": "crypto", - "crypto.SHA384": "crypto", - "crypto.SHA3_224": "crypto", - "crypto.SHA3_256": "crypto", - "crypto.SHA3_384": "crypto", - "crypto.SHA3_512": "crypto", - "crypto.SHA512": "crypto", - "crypto.SHA512_224": "crypto", - "crypto.SHA512_256": "crypto", - "crypto.Signer": "crypto", - "crypto.SignerOpts": "crypto", - "csv.ErrBareQuote": "encoding/csv", - "csv.ErrFieldCount": "encoding/csv", - "csv.ErrQuote": "encoding/csv", - "csv.ErrTrailingComma": "encoding/csv", - "csv.NewReader": "encoding/csv", - "csv.NewWriter": "encoding/csv", - "csv.ParseError": "encoding/csv", - "csv.Reader": "encoding/csv", - "csv.Writer": "encoding/csv", - "debug.FreeOSMemory": "runtime/debug", - "debug.GCStats": "runtime/debug", - "debug.PrintStack": "runtime/debug", - "debug.ReadGCStats": "runtime/debug", - "debug.SetGCPercent": "runtime/debug", - "debug.SetMaxStack": "runtime/debug", - "debug.SetMaxThreads": "runtime/debug", - "debug.SetPanicOnFault": "runtime/debug", - "debug.Stack": "runtime/debug", - "debug.WriteHeapDump": "runtime/debug", - "des.BlockSize": "crypto/des", - "des.KeySizeError": "crypto/des", - "des.NewCipher": "crypto/des", - "des.NewTripleDESCipher": "crypto/des", - "doc.AllDecls": "go/doc", - "doc.AllMethods": "go/doc", - "doc.Example": "go/doc", - "doc.Examples": "go/doc", - "doc.Filter": "go/doc", - "doc.Func": "go/doc", - "doc.IllegalPrefixes": "go/doc", - "doc.Mode": "go/doc", - "doc.New": "go/doc", - "doc.Note": "go/doc", - "doc.Package": "go/doc", - "doc.Synopsis": "go/doc", - "doc.ToHTML": "go/doc", - "doc.ToText": "go/doc", - "doc.Type": "go/doc", - "doc.Value": "go/doc", - "draw.Draw": "image/draw", - "draw.DrawMask": "image/draw", - "draw.Drawer": "image/draw", - "draw.FloydSteinberg": "image/draw", - "draw.Image": "image/draw", - "draw.Op": "image/draw", - "draw.Over": "image/draw", - "draw.Quantizer": "image/draw", - "draw.Src": "image/draw", - "driver.Bool": "database/sql/driver", - "driver.ColumnConverter": "database/sql/driver", - "driver.Conn": "database/sql/driver", - "driver.DefaultParameterConverter": "database/sql/driver", - "driver.Driver": "database/sql/driver", - "driver.ErrBadConn": "database/sql/driver", - "driver.ErrSkip": "database/sql/driver", - "driver.Execer": "database/sql/driver", - "driver.Int32": "database/sql/driver", - "driver.IsScanValue": "database/sql/driver", - "driver.IsValue": "database/sql/driver", - "driver.NotNull": "database/sql/driver", - "driver.Null": "database/sql/driver", - "driver.Queryer": "database/sql/driver", - "driver.Result": "database/sql/driver", - "driver.ResultNoRows": "database/sql/driver", - "driver.Rows": "database/sql/driver", - "driver.RowsAffected": "database/sql/driver", - "driver.Stmt": "database/sql/driver", - "driver.String": "database/sql/driver", - "driver.Tx": "database/sql/driver", - "driver.Value": "database/sql/driver", - "driver.ValueConverter": "database/sql/driver", - "driver.Valuer": "database/sql/driver", - "dsa.ErrInvalidPublicKey": "crypto/dsa", - "dsa.GenerateKey": "crypto/dsa", - "dsa.GenerateParameters": "crypto/dsa", - "dsa.L1024N160": "crypto/dsa", - "dsa.L2048N224": "crypto/dsa", - "dsa.L2048N256": "crypto/dsa", - "dsa.L3072N256": "crypto/dsa", - "dsa.ParameterSizes": "crypto/dsa", - "dsa.Parameters": "crypto/dsa", - "dsa.PrivateKey": "crypto/dsa", - "dsa.PublicKey": "crypto/dsa", - "dsa.Sign": "crypto/dsa", - "dsa.Verify": "crypto/dsa", - "dwarf.AddrType": "debug/dwarf", - "dwarf.ArrayType": "debug/dwarf", - "dwarf.Attr": "debug/dwarf", - "dwarf.AttrAbstractOrigin": "debug/dwarf", - "dwarf.AttrAccessibility": "debug/dwarf", - "dwarf.AttrAddrClass": "debug/dwarf", - "dwarf.AttrAllocated": "debug/dwarf", - "dwarf.AttrArtificial": "debug/dwarf", - "dwarf.AttrAssociated": "debug/dwarf", - "dwarf.AttrBaseTypes": "debug/dwarf", - "dwarf.AttrBitOffset": "debug/dwarf", - "dwarf.AttrBitSize": "debug/dwarf", - "dwarf.AttrByteSize": "debug/dwarf", - "dwarf.AttrCallColumn": "debug/dwarf", - "dwarf.AttrCallFile": "debug/dwarf", - "dwarf.AttrCallLine": "debug/dwarf", - "dwarf.AttrCalling": "debug/dwarf", - "dwarf.AttrCommonRef": "debug/dwarf", - "dwarf.AttrCompDir": "debug/dwarf", - "dwarf.AttrConstValue": "debug/dwarf", - "dwarf.AttrContainingType": "debug/dwarf", - "dwarf.AttrCount": "debug/dwarf", - "dwarf.AttrDataLocation": "debug/dwarf", - "dwarf.AttrDataMemberLoc": "debug/dwarf", - "dwarf.AttrDeclColumn": "debug/dwarf", - "dwarf.AttrDeclFile": "debug/dwarf", - "dwarf.AttrDeclLine": "debug/dwarf", - "dwarf.AttrDeclaration": "debug/dwarf", - "dwarf.AttrDefaultValue": "debug/dwarf", - "dwarf.AttrDescription": "debug/dwarf", - "dwarf.AttrDiscr": "debug/dwarf", - "dwarf.AttrDiscrList": "debug/dwarf", - "dwarf.AttrDiscrValue": "debug/dwarf", - "dwarf.AttrEncoding": "debug/dwarf", - "dwarf.AttrEntrypc": "debug/dwarf", - "dwarf.AttrExtension": "debug/dwarf", - "dwarf.AttrExternal": "debug/dwarf", - "dwarf.AttrFrameBase": "debug/dwarf", - "dwarf.AttrFriend": "debug/dwarf", - "dwarf.AttrHighpc": "debug/dwarf", - "dwarf.AttrIdentifierCase": "debug/dwarf", - "dwarf.AttrImport": "debug/dwarf", - "dwarf.AttrInline": "debug/dwarf", - "dwarf.AttrIsOptional": "debug/dwarf", - "dwarf.AttrLanguage": "debug/dwarf", - "dwarf.AttrLocation": "debug/dwarf", - "dwarf.AttrLowerBound": "debug/dwarf", - "dwarf.AttrLowpc": "debug/dwarf", - "dwarf.AttrMacroInfo": "debug/dwarf", - "dwarf.AttrName": "debug/dwarf", - "dwarf.AttrNamelistItem": "debug/dwarf", - "dwarf.AttrOrdering": "debug/dwarf", - "dwarf.AttrPriority": "debug/dwarf", - "dwarf.AttrProducer": "debug/dwarf", - "dwarf.AttrPrototyped": "debug/dwarf", - "dwarf.AttrRanges": "debug/dwarf", - "dwarf.AttrReturnAddr": "debug/dwarf", - "dwarf.AttrSegment": "debug/dwarf", - "dwarf.AttrSibling": "debug/dwarf", - "dwarf.AttrSpecification": "debug/dwarf", - "dwarf.AttrStartScope": "debug/dwarf", - "dwarf.AttrStaticLink": "debug/dwarf", - "dwarf.AttrStmtList": "debug/dwarf", - "dwarf.AttrStride": "debug/dwarf", - "dwarf.AttrStrideSize": "debug/dwarf", - "dwarf.AttrStringLength": "debug/dwarf", - "dwarf.AttrTrampoline": "debug/dwarf", - "dwarf.AttrType": "debug/dwarf", - "dwarf.AttrUpperBound": "debug/dwarf", - "dwarf.AttrUseLocation": "debug/dwarf", - "dwarf.AttrUseUTF8": "debug/dwarf", - "dwarf.AttrVarParam": "debug/dwarf", - "dwarf.AttrVirtuality": "debug/dwarf", - "dwarf.AttrVisibility": "debug/dwarf", - "dwarf.AttrVtableElemLoc": "debug/dwarf", - "dwarf.BasicType": "debug/dwarf", - "dwarf.BoolType": "debug/dwarf", - "dwarf.CharType": "debug/dwarf", - "dwarf.Class": "debug/dwarf", - "dwarf.ClassAddress": "debug/dwarf", - "dwarf.ClassBlock": "debug/dwarf", - "dwarf.ClassConstant": "debug/dwarf", - "dwarf.ClassExprLoc": "debug/dwarf", - "dwarf.ClassFlag": "debug/dwarf", - "dwarf.ClassLinePtr": "debug/dwarf", - "dwarf.ClassLocListPtr": "debug/dwarf", - "dwarf.ClassMacPtr": "debug/dwarf", - "dwarf.ClassRangeListPtr": "debug/dwarf", - "dwarf.ClassReference": "debug/dwarf", - "dwarf.ClassReferenceAlt": "debug/dwarf", - "dwarf.ClassReferenceSig": "debug/dwarf", - "dwarf.ClassString": "debug/dwarf", - "dwarf.ClassStringAlt": "debug/dwarf", - "dwarf.CommonType": "debug/dwarf", - "dwarf.ComplexType": "debug/dwarf", - "dwarf.Data": "debug/dwarf", - "dwarf.DecodeError": "debug/dwarf", - "dwarf.DotDotDotType": "debug/dwarf", - "dwarf.Entry": "debug/dwarf", - "dwarf.EnumType": "debug/dwarf", - "dwarf.EnumValue": "debug/dwarf", - "dwarf.ErrUnknownPC": "debug/dwarf", - "dwarf.Field": "debug/dwarf", - "dwarf.FloatType": "debug/dwarf", - "dwarf.FuncType": "debug/dwarf", - "dwarf.IntType": "debug/dwarf", - "dwarf.LineEntry": "debug/dwarf", - "dwarf.LineFile": "debug/dwarf", - "dwarf.LineReader": "debug/dwarf", - "dwarf.LineReaderPos": "debug/dwarf", - "dwarf.New": "debug/dwarf", - "dwarf.Offset": "debug/dwarf", - "dwarf.PtrType": "debug/dwarf", - "dwarf.QualType": "debug/dwarf", - "dwarf.Reader": "debug/dwarf", - "dwarf.StructField": "debug/dwarf", - "dwarf.StructType": "debug/dwarf", - "dwarf.Tag": "debug/dwarf", - "dwarf.TagAccessDeclaration": "debug/dwarf", - "dwarf.TagArrayType": "debug/dwarf", - "dwarf.TagBaseType": "debug/dwarf", - "dwarf.TagCatchDwarfBlock": "debug/dwarf", - "dwarf.TagClassType": "debug/dwarf", - "dwarf.TagCommonDwarfBlock": "debug/dwarf", - "dwarf.TagCommonInclusion": "debug/dwarf", - "dwarf.TagCompileUnit": "debug/dwarf", - "dwarf.TagCondition": "debug/dwarf", - "dwarf.TagConstType": "debug/dwarf", - "dwarf.TagConstant": "debug/dwarf", - "dwarf.TagDwarfProcedure": "debug/dwarf", - "dwarf.TagEntryPoint": "debug/dwarf", - "dwarf.TagEnumerationType": "debug/dwarf", - "dwarf.TagEnumerator": "debug/dwarf", - "dwarf.TagFileType": "debug/dwarf", - "dwarf.TagFormalParameter": "debug/dwarf", - "dwarf.TagFriend": "debug/dwarf", - "dwarf.TagImportedDeclaration": "debug/dwarf", - "dwarf.TagImportedModule": "debug/dwarf", - "dwarf.TagImportedUnit": "debug/dwarf", - "dwarf.TagInheritance": "debug/dwarf", - "dwarf.TagInlinedSubroutine": "debug/dwarf", - "dwarf.TagInterfaceType": "debug/dwarf", - "dwarf.TagLabel": "debug/dwarf", - "dwarf.TagLexDwarfBlock": "debug/dwarf", - "dwarf.TagMember": "debug/dwarf", - "dwarf.TagModule": "debug/dwarf", - "dwarf.TagMutableType": "debug/dwarf", - "dwarf.TagNamelist": "debug/dwarf", - "dwarf.TagNamelistItem": "debug/dwarf", - "dwarf.TagNamespace": "debug/dwarf", - "dwarf.TagPackedType": "debug/dwarf", - "dwarf.TagPartialUnit": "debug/dwarf", - "dwarf.TagPointerType": "debug/dwarf", - "dwarf.TagPtrToMemberType": "debug/dwarf", - "dwarf.TagReferenceType": "debug/dwarf", - "dwarf.TagRestrictType": "debug/dwarf", - "dwarf.TagRvalueReferenceType": "debug/dwarf", - "dwarf.TagSetType": "debug/dwarf", - "dwarf.TagSharedType": "debug/dwarf", - "dwarf.TagStringType": "debug/dwarf", - "dwarf.TagStructType": "debug/dwarf", - "dwarf.TagSubprogram": "debug/dwarf", - "dwarf.TagSubrangeType": "debug/dwarf", - "dwarf.TagSubroutineType": "debug/dwarf", - "dwarf.TagTemplateAlias": "debug/dwarf", - "dwarf.TagTemplateTypeParameter": "debug/dwarf", - "dwarf.TagTemplateValueParameter": "debug/dwarf", - "dwarf.TagThrownType": "debug/dwarf", - "dwarf.TagTryDwarfBlock": "debug/dwarf", - "dwarf.TagTypeUnit": "debug/dwarf", - "dwarf.TagTypedef": "debug/dwarf", - "dwarf.TagUnionType": "debug/dwarf", - "dwarf.TagUnspecifiedParameters": "debug/dwarf", - "dwarf.TagUnspecifiedType": "debug/dwarf", - "dwarf.TagVariable": "debug/dwarf", - "dwarf.TagVariant": "debug/dwarf", - "dwarf.TagVariantPart": "debug/dwarf", - "dwarf.TagVolatileType": "debug/dwarf", - "dwarf.TagWithStmt": "debug/dwarf", - "dwarf.Type": "debug/dwarf", - "dwarf.TypedefType": "debug/dwarf", - "dwarf.UcharType": "debug/dwarf", - "dwarf.UintType": "debug/dwarf", - "dwarf.UnspecifiedType": "debug/dwarf", - "dwarf.VoidType": "debug/dwarf", - "ecdsa.GenerateKey": "crypto/ecdsa", - "ecdsa.PrivateKey": "crypto/ecdsa", - "ecdsa.PublicKey": "crypto/ecdsa", - "ecdsa.Sign": "crypto/ecdsa", - "ecdsa.Verify": "crypto/ecdsa", - "elf.ARM_MAGIC_TRAMP_NUMBER": "debug/elf", - "elf.Class": "debug/elf", - "elf.DF_BIND_NOW": "debug/elf", - "elf.DF_ORIGIN": "debug/elf", - "elf.DF_STATIC_TLS": "debug/elf", - "elf.DF_SYMBOLIC": "debug/elf", - "elf.DF_TEXTREL": "debug/elf", - "elf.DT_BIND_NOW": "debug/elf", - "elf.DT_DEBUG": "debug/elf", - "elf.DT_ENCODING": "debug/elf", - "elf.DT_FINI": "debug/elf", - "elf.DT_FINI_ARRAY": "debug/elf", - "elf.DT_FINI_ARRAYSZ": "debug/elf", - "elf.DT_FLAGS": "debug/elf", - "elf.DT_HASH": "debug/elf", - "elf.DT_HIOS": "debug/elf", - "elf.DT_HIPROC": "debug/elf", - "elf.DT_INIT": "debug/elf", - "elf.DT_INIT_ARRAY": "debug/elf", - "elf.DT_INIT_ARRAYSZ": "debug/elf", - "elf.DT_JMPREL": "debug/elf", - "elf.DT_LOOS": "debug/elf", - "elf.DT_LOPROC": "debug/elf", - "elf.DT_NEEDED": "debug/elf", - "elf.DT_NULL": "debug/elf", - "elf.DT_PLTGOT": "debug/elf", - "elf.DT_PLTREL": "debug/elf", - "elf.DT_PLTRELSZ": "debug/elf", - "elf.DT_PREINIT_ARRAY": "debug/elf", - "elf.DT_PREINIT_ARRAYSZ": "debug/elf", - "elf.DT_REL": "debug/elf", - "elf.DT_RELA": "debug/elf", - "elf.DT_RELAENT": "debug/elf", - "elf.DT_RELASZ": "debug/elf", - "elf.DT_RELENT": "debug/elf", - "elf.DT_RELSZ": "debug/elf", - "elf.DT_RPATH": "debug/elf", - "elf.DT_RUNPATH": "debug/elf", - "elf.DT_SONAME": "debug/elf", - "elf.DT_STRSZ": "debug/elf", - "elf.DT_STRTAB": "debug/elf", - "elf.DT_SYMBOLIC": "debug/elf", - "elf.DT_SYMENT": "debug/elf", - "elf.DT_SYMTAB": "debug/elf", - "elf.DT_TEXTREL": "debug/elf", - "elf.DT_VERNEED": "debug/elf", - "elf.DT_VERNEEDNUM": "debug/elf", - "elf.DT_VERSYM": "debug/elf", - "elf.Data": "debug/elf", - "elf.Dyn32": "debug/elf", - "elf.Dyn64": "debug/elf", - "elf.DynFlag": "debug/elf", - "elf.DynTag": "debug/elf", - "elf.EI_ABIVERSION": "debug/elf", - "elf.EI_CLASS": "debug/elf", - "elf.EI_DATA": "debug/elf", - "elf.EI_NIDENT": "debug/elf", - "elf.EI_OSABI": "debug/elf", - "elf.EI_PAD": "debug/elf", - "elf.EI_VERSION": "debug/elf", - "elf.ELFCLASS32": "debug/elf", - "elf.ELFCLASS64": "debug/elf", - "elf.ELFCLASSNONE": "debug/elf", - "elf.ELFDATA2LSB": "debug/elf", - "elf.ELFDATA2MSB": "debug/elf", - "elf.ELFDATANONE": "debug/elf", - "elf.ELFMAG": "debug/elf", - "elf.ELFOSABI_86OPEN": "debug/elf", - "elf.ELFOSABI_AIX": "debug/elf", - "elf.ELFOSABI_ARM": "debug/elf", - "elf.ELFOSABI_FREEBSD": "debug/elf", - "elf.ELFOSABI_HPUX": "debug/elf", - "elf.ELFOSABI_HURD": "debug/elf", - "elf.ELFOSABI_IRIX": "debug/elf", - "elf.ELFOSABI_LINUX": "debug/elf", - "elf.ELFOSABI_MODESTO": "debug/elf", - "elf.ELFOSABI_NETBSD": "debug/elf", - "elf.ELFOSABI_NONE": "debug/elf", - "elf.ELFOSABI_NSK": "debug/elf", - "elf.ELFOSABI_OPENBSD": "debug/elf", - "elf.ELFOSABI_OPENVMS": "debug/elf", - "elf.ELFOSABI_SOLARIS": "debug/elf", - "elf.ELFOSABI_STANDALONE": "debug/elf", - "elf.ELFOSABI_TRU64": "debug/elf", - "elf.EM_386": "debug/elf", - "elf.EM_486": "debug/elf", - "elf.EM_68HC12": "debug/elf", - "elf.EM_68K": "debug/elf", - "elf.EM_860": "debug/elf", - "elf.EM_88K": "debug/elf", - "elf.EM_960": "debug/elf", - "elf.EM_AARCH64": "debug/elf", - "elf.EM_ALPHA": "debug/elf", - "elf.EM_ALPHA_STD": "debug/elf", - "elf.EM_ARC": "debug/elf", - "elf.EM_ARM": "debug/elf", - "elf.EM_COLDFIRE": "debug/elf", - "elf.EM_FR20": "debug/elf", - "elf.EM_H8S": "debug/elf", - "elf.EM_H8_300": "debug/elf", - "elf.EM_H8_300H": "debug/elf", - "elf.EM_H8_500": "debug/elf", - "elf.EM_IA_64": "debug/elf", - "elf.EM_M32": "debug/elf", - "elf.EM_ME16": "debug/elf", - "elf.EM_MIPS": "debug/elf", - "elf.EM_MIPS_RS3_LE": "debug/elf", - "elf.EM_MIPS_RS4_BE": "debug/elf", - "elf.EM_MIPS_X": "debug/elf", - "elf.EM_MMA": "debug/elf", - "elf.EM_NCPU": "debug/elf", - "elf.EM_NDR1": "debug/elf", - "elf.EM_NONE": "debug/elf", - "elf.EM_PARISC": "debug/elf", - "elf.EM_PCP": "debug/elf", - "elf.EM_PPC": "debug/elf", - "elf.EM_PPC64": "debug/elf", - "elf.EM_RCE": "debug/elf", - "elf.EM_RH32": "debug/elf", - "elf.EM_S370": "debug/elf", - "elf.EM_S390": "debug/elf", - "elf.EM_SH": "debug/elf", - "elf.EM_SPARC": "debug/elf", - "elf.EM_SPARC32PLUS": "debug/elf", - "elf.EM_SPARCV9": "debug/elf", - "elf.EM_ST100": "debug/elf", - "elf.EM_STARCORE": "debug/elf", - "elf.EM_TINYJ": "debug/elf", - "elf.EM_TRICORE": "debug/elf", - "elf.EM_V800": "debug/elf", - "elf.EM_VPP500": "debug/elf", - "elf.EM_X86_64": "debug/elf", - "elf.ET_CORE": "debug/elf", - "elf.ET_DYN": "debug/elf", - "elf.ET_EXEC": "debug/elf", - "elf.ET_HIOS": "debug/elf", - "elf.ET_HIPROC": "debug/elf", - "elf.ET_LOOS": "debug/elf", - "elf.ET_LOPROC": "debug/elf", - "elf.ET_NONE": "debug/elf", - "elf.ET_REL": "debug/elf", - "elf.EV_CURRENT": "debug/elf", - "elf.EV_NONE": "debug/elf", - "elf.ErrNoSymbols": "debug/elf", - "elf.File": "debug/elf", - "elf.FileHeader": "debug/elf", - "elf.FormatError": "debug/elf", - "elf.Header32": "debug/elf", - "elf.Header64": "debug/elf", - "elf.ImportedSymbol": "debug/elf", - "elf.Machine": "debug/elf", - "elf.NT_FPREGSET": "debug/elf", - "elf.NT_PRPSINFO": "debug/elf", - "elf.NT_PRSTATUS": "debug/elf", - "elf.NType": "debug/elf", - "elf.NewFile": "debug/elf", - "elf.OSABI": "debug/elf", - "elf.Open": "debug/elf", - "elf.PF_MASKOS": "debug/elf", - "elf.PF_MASKPROC": "debug/elf", - "elf.PF_R": "debug/elf", - "elf.PF_W": "debug/elf", - "elf.PF_X": "debug/elf", - "elf.PT_DYNAMIC": "debug/elf", - "elf.PT_HIOS": "debug/elf", - "elf.PT_HIPROC": "debug/elf", - "elf.PT_INTERP": "debug/elf", - "elf.PT_LOAD": "debug/elf", - "elf.PT_LOOS": "debug/elf", - "elf.PT_LOPROC": "debug/elf", - "elf.PT_NOTE": "debug/elf", - "elf.PT_NULL": "debug/elf", - "elf.PT_PHDR": "debug/elf", - "elf.PT_SHLIB": "debug/elf", - "elf.PT_TLS": "debug/elf", - "elf.Prog": "debug/elf", - "elf.Prog32": "debug/elf", - "elf.Prog64": "debug/elf", - "elf.ProgFlag": "debug/elf", - "elf.ProgHeader": "debug/elf", - "elf.ProgType": "debug/elf", - "elf.R_386": "debug/elf", - "elf.R_386_32": "debug/elf", - "elf.R_386_COPY": "debug/elf", - "elf.R_386_GLOB_DAT": "debug/elf", - "elf.R_386_GOT32": "debug/elf", - "elf.R_386_GOTOFF": "debug/elf", - "elf.R_386_GOTPC": "debug/elf", - "elf.R_386_JMP_SLOT": "debug/elf", - "elf.R_386_NONE": "debug/elf", - "elf.R_386_PC32": "debug/elf", - "elf.R_386_PLT32": "debug/elf", - "elf.R_386_RELATIVE": "debug/elf", - "elf.R_386_TLS_DTPMOD32": "debug/elf", - "elf.R_386_TLS_DTPOFF32": "debug/elf", - "elf.R_386_TLS_GD": "debug/elf", - "elf.R_386_TLS_GD_32": "debug/elf", - "elf.R_386_TLS_GD_CALL": "debug/elf", - "elf.R_386_TLS_GD_POP": "debug/elf", - "elf.R_386_TLS_GD_PUSH": "debug/elf", - "elf.R_386_TLS_GOTIE": "debug/elf", - "elf.R_386_TLS_IE": "debug/elf", - "elf.R_386_TLS_IE_32": "debug/elf", - "elf.R_386_TLS_LDM": "debug/elf", - "elf.R_386_TLS_LDM_32": "debug/elf", - "elf.R_386_TLS_LDM_CALL": "debug/elf", - "elf.R_386_TLS_LDM_POP": "debug/elf", - "elf.R_386_TLS_LDM_PUSH": "debug/elf", - "elf.R_386_TLS_LDO_32": "debug/elf", - "elf.R_386_TLS_LE": "debug/elf", - "elf.R_386_TLS_LE_32": "debug/elf", - "elf.R_386_TLS_TPOFF": "debug/elf", - "elf.R_386_TLS_TPOFF32": "debug/elf", - "elf.R_AARCH64": "debug/elf", - "elf.R_AARCH64_ABS16": "debug/elf", - "elf.R_AARCH64_ABS32": "debug/elf", - "elf.R_AARCH64_ABS64": "debug/elf", - "elf.R_AARCH64_ADD_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_ADR_GOT_PAGE": "debug/elf", - "elf.R_AARCH64_ADR_PREL_LO21": "debug/elf", - "elf.R_AARCH64_ADR_PREL_PG_HI21": "debug/elf", - "elf.R_AARCH64_ADR_PREL_PG_HI21_NC": "debug/elf", - "elf.R_AARCH64_CALL26": "debug/elf", - "elf.R_AARCH64_CONDBR19": "debug/elf", - "elf.R_AARCH64_COPY": "debug/elf", - "elf.R_AARCH64_GLOB_DAT": "debug/elf", - "elf.R_AARCH64_GOT_LD_PREL19": "debug/elf", - "elf.R_AARCH64_IRELATIVE": "debug/elf", - "elf.R_AARCH64_JUMP26": "debug/elf", - "elf.R_AARCH64_JUMP_SLOT": "debug/elf", - "elf.R_AARCH64_LD64_GOT_LO12_NC": "debug/elf", - "elf.R_AARCH64_LDST128_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_LDST16_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_LDST32_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_LDST64_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_LDST8_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_LD_PREL_LO19": "debug/elf", - "elf.R_AARCH64_MOVW_SABS_G0": "debug/elf", - "elf.R_AARCH64_MOVW_SABS_G1": "debug/elf", - "elf.R_AARCH64_MOVW_SABS_G2": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G0": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G0_NC": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G1": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G1_NC": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G2": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G2_NC": "debug/elf", - "elf.R_AARCH64_MOVW_UABS_G3": "debug/elf", - "elf.R_AARCH64_NONE": "debug/elf", - "elf.R_AARCH64_NULL": "debug/elf", - "elf.R_AARCH64_P32_ABS16": "debug/elf", - "elf.R_AARCH64_P32_ABS32": "debug/elf", - "elf.R_AARCH64_P32_ADD_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_ADR_GOT_PAGE": "debug/elf", - "elf.R_AARCH64_P32_ADR_PREL_LO21": "debug/elf", - "elf.R_AARCH64_P32_ADR_PREL_PG_HI21": "debug/elf", - "elf.R_AARCH64_P32_CALL26": "debug/elf", - "elf.R_AARCH64_P32_CONDBR19": "debug/elf", - "elf.R_AARCH64_P32_COPY": "debug/elf", - "elf.R_AARCH64_P32_GLOB_DAT": "debug/elf", - "elf.R_AARCH64_P32_GOT_LD_PREL19": "debug/elf", - "elf.R_AARCH64_P32_IRELATIVE": "debug/elf", - "elf.R_AARCH64_P32_JUMP26": "debug/elf", - "elf.R_AARCH64_P32_JUMP_SLOT": "debug/elf", - "elf.R_AARCH64_P32_LD32_GOT_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_LDST128_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_LDST16_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_LDST32_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_LDST64_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_LDST8_ABS_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_LD_PREL_LO19": "debug/elf", - "elf.R_AARCH64_P32_MOVW_SABS_G0": "debug/elf", - "elf.R_AARCH64_P32_MOVW_UABS_G0": "debug/elf", - "elf.R_AARCH64_P32_MOVW_UABS_G0_NC": "debug/elf", - "elf.R_AARCH64_P32_MOVW_UABS_G1": "debug/elf", - "elf.R_AARCH64_P32_PREL16": "debug/elf", - "elf.R_AARCH64_P32_PREL32": "debug/elf", - "elf.R_AARCH64_P32_RELATIVE": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC_ADD_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC_ADR_PAGE21": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC_ADR_PREL21": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC_CALL": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC_LD32_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_TLSDESC_LD_PREL19": "debug/elf", - "elf.R_AARCH64_P32_TLSGD_ADD_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_TLSGD_ADR_PAGE21": "debug/elf", - "elf.R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21": "debug/elf", - "elf.R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19": "debug/elf", - "elf.R_AARCH64_P32_TLSLE_ADD_TPREL_HI12": "debug/elf", - "elf.R_AARCH64_P32_TLSLE_ADD_TPREL_LO12": "debug/elf", - "elf.R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC": "debug/elf", - "elf.R_AARCH64_P32_TLSLE_MOVW_TPREL_G0": "debug/elf", - "elf.R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC": "debug/elf", - "elf.R_AARCH64_P32_TLSLE_MOVW_TPREL_G1": "debug/elf", - "elf.R_AARCH64_P32_TLS_DTPMOD": "debug/elf", - "elf.R_AARCH64_P32_TLS_DTPREL": "debug/elf", - "elf.R_AARCH64_P32_TLS_TPREL": "debug/elf", - "elf.R_AARCH64_P32_TSTBR14": "debug/elf", - "elf.R_AARCH64_PREL16": "debug/elf", - "elf.R_AARCH64_PREL32": "debug/elf", - "elf.R_AARCH64_PREL64": "debug/elf", - "elf.R_AARCH64_RELATIVE": "debug/elf", - "elf.R_AARCH64_TLSDESC": "debug/elf", - "elf.R_AARCH64_TLSDESC_ADD": "debug/elf", - "elf.R_AARCH64_TLSDESC_ADD_LO12_NC": "debug/elf", - "elf.R_AARCH64_TLSDESC_ADR_PAGE21": "debug/elf", - "elf.R_AARCH64_TLSDESC_ADR_PREL21": "debug/elf", - "elf.R_AARCH64_TLSDESC_CALL": "debug/elf", - "elf.R_AARCH64_TLSDESC_LD64_LO12_NC": "debug/elf", - "elf.R_AARCH64_TLSDESC_LDR": "debug/elf", - "elf.R_AARCH64_TLSDESC_LD_PREL19": "debug/elf", - "elf.R_AARCH64_TLSDESC_OFF_G0_NC": "debug/elf", - "elf.R_AARCH64_TLSDESC_OFF_G1": "debug/elf", - "elf.R_AARCH64_TLSGD_ADD_LO12_NC": "debug/elf", - "elf.R_AARCH64_TLSGD_ADR_PAGE21": "debug/elf", - "elf.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21": "debug/elf", - "elf.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC": "debug/elf", - "elf.R_AARCH64_TLSIE_LD_GOTTPREL_PREL19": "debug/elf", - "elf.R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC": "debug/elf", - "elf.R_AARCH64_TLSIE_MOVW_GOTTPREL_G1": "debug/elf", - "elf.R_AARCH64_TLSLE_ADD_TPREL_HI12": "debug/elf", - "elf.R_AARCH64_TLSLE_ADD_TPREL_LO12": "debug/elf", - "elf.R_AARCH64_TLSLE_ADD_TPREL_LO12_NC": "debug/elf", - "elf.R_AARCH64_TLSLE_MOVW_TPREL_G0": "debug/elf", - "elf.R_AARCH64_TLSLE_MOVW_TPREL_G0_NC": "debug/elf", - "elf.R_AARCH64_TLSLE_MOVW_TPREL_G1": "debug/elf", - "elf.R_AARCH64_TLSLE_MOVW_TPREL_G1_NC": "debug/elf", - "elf.R_AARCH64_TLSLE_MOVW_TPREL_G2": "debug/elf", - "elf.R_AARCH64_TLS_DTPMOD64": "debug/elf", - "elf.R_AARCH64_TLS_DTPREL64": "debug/elf", - "elf.R_AARCH64_TLS_TPREL64": "debug/elf", - "elf.R_AARCH64_TSTBR14": "debug/elf", - "elf.R_ALPHA": "debug/elf", - "elf.R_ALPHA_BRADDR": "debug/elf", - "elf.R_ALPHA_COPY": "debug/elf", - "elf.R_ALPHA_GLOB_DAT": "debug/elf", - "elf.R_ALPHA_GPDISP": "debug/elf", - "elf.R_ALPHA_GPREL32": "debug/elf", - "elf.R_ALPHA_GPRELHIGH": "debug/elf", - "elf.R_ALPHA_GPRELLOW": "debug/elf", - "elf.R_ALPHA_GPVALUE": "debug/elf", - "elf.R_ALPHA_HINT": "debug/elf", - "elf.R_ALPHA_IMMED_BR_HI32": "debug/elf", - "elf.R_ALPHA_IMMED_GP_16": "debug/elf", - "elf.R_ALPHA_IMMED_GP_HI32": "debug/elf", - "elf.R_ALPHA_IMMED_LO32": "debug/elf", - "elf.R_ALPHA_IMMED_SCN_HI32": "debug/elf", - "elf.R_ALPHA_JMP_SLOT": "debug/elf", - "elf.R_ALPHA_LITERAL": "debug/elf", - "elf.R_ALPHA_LITUSE": "debug/elf", - "elf.R_ALPHA_NONE": "debug/elf", - "elf.R_ALPHA_OP_PRSHIFT": "debug/elf", - "elf.R_ALPHA_OP_PSUB": "debug/elf", - "elf.R_ALPHA_OP_PUSH": "debug/elf", - "elf.R_ALPHA_OP_STORE": "debug/elf", - "elf.R_ALPHA_REFLONG": "debug/elf", - "elf.R_ALPHA_REFQUAD": "debug/elf", - "elf.R_ALPHA_RELATIVE": "debug/elf", - "elf.R_ALPHA_SREL16": "debug/elf", - "elf.R_ALPHA_SREL32": "debug/elf", - "elf.R_ALPHA_SREL64": "debug/elf", - "elf.R_ARM": "debug/elf", - "elf.R_ARM_ABS12": "debug/elf", - "elf.R_ARM_ABS16": "debug/elf", - "elf.R_ARM_ABS32": "debug/elf", - "elf.R_ARM_ABS8": "debug/elf", - "elf.R_ARM_AMP_VCALL9": "debug/elf", - "elf.R_ARM_COPY": "debug/elf", - "elf.R_ARM_GLOB_DAT": "debug/elf", - "elf.R_ARM_GNU_VTENTRY": "debug/elf", - "elf.R_ARM_GNU_VTINHERIT": "debug/elf", - "elf.R_ARM_GOT32": "debug/elf", - "elf.R_ARM_GOTOFF": "debug/elf", - "elf.R_ARM_GOTPC": "debug/elf", - "elf.R_ARM_JUMP_SLOT": "debug/elf", - "elf.R_ARM_NONE": "debug/elf", - "elf.R_ARM_PC13": "debug/elf", - "elf.R_ARM_PC24": "debug/elf", - "elf.R_ARM_PLT32": "debug/elf", - "elf.R_ARM_RABS32": "debug/elf", - "elf.R_ARM_RBASE": "debug/elf", - "elf.R_ARM_REL32": "debug/elf", - "elf.R_ARM_RELATIVE": "debug/elf", - "elf.R_ARM_RPC24": "debug/elf", - "elf.R_ARM_RREL32": "debug/elf", - "elf.R_ARM_RSBREL32": "debug/elf", - "elf.R_ARM_SBREL32": "debug/elf", - "elf.R_ARM_SWI24": "debug/elf", - "elf.R_ARM_THM_ABS5": "debug/elf", - "elf.R_ARM_THM_PC22": "debug/elf", - "elf.R_ARM_THM_PC8": "debug/elf", - "elf.R_ARM_THM_RPC22": "debug/elf", - "elf.R_ARM_THM_SWI8": "debug/elf", - "elf.R_ARM_THM_XPC22": "debug/elf", - "elf.R_ARM_XPC25": "debug/elf", - "elf.R_INFO": "debug/elf", - "elf.R_INFO32": "debug/elf", - "elf.R_PPC": "debug/elf", - "elf.R_PPC64": "debug/elf", - "elf.R_PPC64_ADDR14": "debug/elf", - "elf.R_PPC64_ADDR14_BRNTAKEN": "debug/elf", - "elf.R_PPC64_ADDR14_BRTAKEN": "debug/elf", - "elf.R_PPC64_ADDR16": "debug/elf", - "elf.R_PPC64_ADDR16_DS": "debug/elf", - "elf.R_PPC64_ADDR16_HA": "debug/elf", - "elf.R_PPC64_ADDR16_HI": "debug/elf", - "elf.R_PPC64_ADDR16_HIGHER": "debug/elf", - "elf.R_PPC64_ADDR16_HIGHERA": "debug/elf", - "elf.R_PPC64_ADDR16_HIGHEST": "debug/elf", - "elf.R_PPC64_ADDR16_HIGHESTA": "debug/elf", - "elf.R_PPC64_ADDR16_LO": "debug/elf", - "elf.R_PPC64_ADDR16_LO_DS": "debug/elf", - "elf.R_PPC64_ADDR24": "debug/elf", - "elf.R_PPC64_ADDR32": "debug/elf", - "elf.R_PPC64_ADDR64": "debug/elf", - "elf.R_PPC64_DTPMOD64": "debug/elf", - "elf.R_PPC64_DTPREL16": "debug/elf", - "elf.R_PPC64_DTPREL16_DS": "debug/elf", - "elf.R_PPC64_DTPREL16_HA": "debug/elf", - "elf.R_PPC64_DTPREL16_HI": "debug/elf", - "elf.R_PPC64_DTPREL16_HIGHER": "debug/elf", - "elf.R_PPC64_DTPREL16_HIGHERA": "debug/elf", - "elf.R_PPC64_DTPREL16_HIGHEST": "debug/elf", - "elf.R_PPC64_DTPREL16_HIGHESTA": "debug/elf", - "elf.R_PPC64_DTPREL16_LO": "debug/elf", - "elf.R_PPC64_DTPREL16_LO_DS": "debug/elf", - "elf.R_PPC64_DTPREL64": "debug/elf", - "elf.R_PPC64_GOT16": "debug/elf", - "elf.R_PPC64_GOT16_DS": "debug/elf", - "elf.R_PPC64_GOT16_HA": "debug/elf", - "elf.R_PPC64_GOT16_HI": "debug/elf", - "elf.R_PPC64_GOT16_LO": "debug/elf", - "elf.R_PPC64_GOT16_LO_DS": "debug/elf", - "elf.R_PPC64_GOT_DTPREL16_DS": "debug/elf", - "elf.R_PPC64_GOT_DTPREL16_HA": "debug/elf", - "elf.R_PPC64_GOT_DTPREL16_HI": "debug/elf", - "elf.R_PPC64_GOT_DTPREL16_LO_DS": "debug/elf", - "elf.R_PPC64_GOT_TLSGD16": "debug/elf", - "elf.R_PPC64_GOT_TLSGD16_HA": "debug/elf", - "elf.R_PPC64_GOT_TLSGD16_HI": "debug/elf", - "elf.R_PPC64_GOT_TLSGD16_LO": "debug/elf", - "elf.R_PPC64_GOT_TLSLD16": "debug/elf", - "elf.R_PPC64_GOT_TLSLD16_HA": "debug/elf", - "elf.R_PPC64_GOT_TLSLD16_HI": "debug/elf", - "elf.R_PPC64_GOT_TLSLD16_LO": "debug/elf", - "elf.R_PPC64_GOT_TPREL16_DS": "debug/elf", - "elf.R_PPC64_GOT_TPREL16_HA": "debug/elf", - "elf.R_PPC64_GOT_TPREL16_HI": "debug/elf", - "elf.R_PPC64_GOT_TPREL16_LO_DS": "debug/elf", - "elf.R_PPC64_JMP_SLOT": "debug/elf", - "elf.R_PPC64_NONE": "debug/elf", - "elf.R_PPC64_REL14": "debug/elf", - "elf.R_PPC64_REL14_BRNTAKEN": "debug/elf", - "elf.R_PPC64_REL14_BRTAKEN": "debug/elf", - "elf.R_PPC64_REL16": "debug/elf", - "elf.R_PPC64_REL16_HA": "debug/elf", - "elf.R_PPC64_REL16_HI": "debug/elf", - "elf.R_PPC64_REL16_LO": "debug/elf", - "elf.R_PPC64_REL24": "debug/elf", - "elf.R_PPC64_REL32": "debug/elf", - "elf.R_PPC64_REL64": "debug/elf", - "elf.R_PPC64_TLS": "debug/elf", - "elf.R_PPC64_TLSGD": "debug/elf", - "elf.R_PPC64_TLSLD": "debug/elf", - "elf.R_PPC64_TOC": "debug/elf", - "elf.R_PPC64_TOC16": "debug/elf", - "elf.R_PPC64_TOC16_DS": "debug/elf", - "elf.R_PPC64_TOC16_HA": "debug/elf", - "elf.R_PPC64_TOC16_HI": "debug/elf", - "elf.R_PPC64_TOC16_LO": "debug/elf", - "elf.R_PPC64_TOC16_LO_DS": "debug/elf", - "elf.R_PPC64_TPREL16": "debug/elf", - "elf.R_PPC64_TPREL16_DS": "debug/elf", - "elf.R_PPC64_TPREL16_HA": "debug/elf", - "elf.R_PPC64_TPREL16_HI": "debug/elf", - "elf.R_PPC64_TPREL16_HIGHER": "debug/elf", - "elf.R_PPC64_TPREL16_HIGHERA": "debug/elf", - "elf.R_PPC64_TPREL16_HIGHEST": "debug/elf", - "elf.R_PPC64_TPREL16_HIGHESTA": "debug/elf", - "elf.R_PPC64_TPREL16_LO": "debug/elf", - "elf.R_PPC64_TPREL16_LO_DS": "debug/elf", - "elf.R_PPC64_TPREL64": "debug/elf", - "elf.R_PPC_ADDR14": "debug/elf", - "elf.R_PPC_ADDR14_BRNTAKEN": "debug/elf", - "elf.R_PPC_ADDR14_BRTAKEN": "debug/elf", - "elf.R_PPC_ADDR16": "debug/elf", - "elf.R_PPC_ADDR16_HA": "debug/elf", - "elf.R_PPC_ADDR16_HI": "debug/elf", - "elf.R_PPC_ADDR16_LO": "debug/elf", - "elf.R_PPC_ADDR24": "debug/elf", - "elf.R_PPC_ADDR32": "debug/elf", - "elf.R_PPC_COPY": "debug/elf", - "elf.R_PPC_DTPMOD32": "debug/elf", - "elf.R_PPC_DTPREL16": "debug/elf", - "elf.R_PPC_DTPREL16_HA": "debug/elf", - "elf.R_PPC_DTPREL16_HI": "debug/elf", - "elf.R_PPC_DTPREL16_LO": "debug/elf", - "elf.R_PPC_DTPREL32": "debug/elf", - "elf.R_PPC_EMB_BIT_FLD": "debug/elf", - "elf.R_PPC_EMB_MRKREF": "debug/elf", - "elf.R_PPC_EMB_NADDR16": "debug/elf", - "elf.R_PPC_EMB_NADDR16_HA": "debug/elf", - "elf.R_PPC_EMB_NADDR16_HI": "debug/elf", - "elf.R_PPC_EMB_NADDR16_LO": "debug/elf", - "elf.R_PPC_EMB_NADDR32": "debug/elf", - "elf.R_PPC_EMB_RELSDA": "debug/elf", - "elf.R_PPC_EMB_RELSEC16": "debug/elf", - "elf.R_PPC_EMB_RELST_HA": "debug/elf", - "elf.R_PPC_EMB_RELST_HI": "debug/elf", - "elf.R_PPC_EMB_RELST_LO": "debug/elf", - "elf.R_PPC_EMB_SDA21": "debug/elf", - "elf.R_PPC_EMB_SDA2I16": "debug/elf", - "elf.R_PPC_EMB_SDA2REL": "debug/elf", - "elf.R_PPC_EMB_SDAI16": "debug/elf", - "elf.R_PPC_GLOB_DAT": "debug/elf", - "elf.R_PPC_GOT16": "debug/elf", - "elf.R_PPC_GOT16_HA": "debug/elf", - "elf.R_PPC_GOT16_HI": "debug/elf", - "elf.R_PPC_GOT16_LO": "debug/elf", - "elf.R_PPC_GOT_TLSGD16": "debug/elf", - "elf.R_PPC_GOT_TLSGD16_HA": "debug/elf", - "elf.R_PPC_GOT_TLSGD16_HI": "debug/elf", - "elf.R_PPC_GOT_TLSGD16_LO": "debug/elf", - "elf.R_PPC_GOT_TLSLD16": "debug/elf", - "elf.R_PPC_GOT_TLSLD16_HA": "debug/elf", - "elf.R_PPC_GOT_TLSLD16_HI": "debug/elf", - "elf.R_PPC_GOT_TLSLD16_LO": "debug/elf", - "elf.R_PPC_GOT_TPREL16": "debug/elf", - "elf.R_PPC_GOT_TPREL16_HA": "debug/elf", - "elf.R_PPC_GOT_TPREL16_HI": "debug/elf", - "elf.R_PPC_GOT_TPREL16_LO": "debug/elf", - "elf.R_PPC_JMP_SLOT": "debug/elf", - "elf.R_PPC_LOCAL24PC": "debug/elf", - "elf.R_PPC_NONE": "debug/elf", - "elf.R_PPC_PLT16_HA": "debug/elf", - "elf.R_PPC_PLT16_HI": "debug/elf", - "elf.R_PPC_PLT16_LO": "debug/elf", - "elf.R_PPC_PLT32": "debug/elf", - "elf.R_PPC_PLTREL24": "debug/elf", - "elf.R_PPC_PLTREL32": "debug/elf", - "elf.R_PPC_REL14": "debug/elf", - "elf.R_PPC_REL14_BRNTAKEN": "debug/elf", - "elf.R_PPC_REL14_BRTAKEN": "debug/elf", - "elf.R_PPC_REL24": "debug/elf", - "elf.R_PPC_REL32": "debug/elf", - "elf.R_PPC_RELATIVE": "debug/elf", - "elf.R_PPC_SDAREL16": "debug/elf", - "elf.R_PPC_SECTOFF": "debug/elf", - "elf.R_PPC_SECTOFF_HA": "debug/elf", - "elf.R_PPC_SECTOFF_HI": "debug/elf", - "elf.R_PPC_SECTOFF_LO": "debug/elf", - "elf.R_PPC_TLS": "debug/elf", - "elf.R_PPC_TPREL16": "debug/elf", - "elf.R_PPC_TPREL16_HA": "debug/elf", - "elf.R_PPC_TPREL16_HI": "debug/elf", - "elf.R_PPC_TPREL16_LO": "debug/elf", - "elf.R_PPC_TPREL32": "debug/elf", - "elf.R_PPC_UADDR16": "debug/elf", - "elf.R_PPC_UADDR32": "debug/elf", - "elf.R_SPARC": "debug/elf", - "elf.R_SPARC_10": "debug/elf", - "elf.R_SPARC_11": "debug/elf", - "elf.R_SPARC_13": "debug/elf", - "elf.R_SPARC_16": "debug/elf", - "elf.R_SPARC_22": "debug/elf", - "elf.R_SPARC_32": "debug/elf", - "elf.R_SPARC_5": "debug/elf", - "elf.R_SPARC_6": "debug/elf", - "elf.R_SPARC_64": "debug/elf", - "elf.R_SPARC_7": "debug/elf", - "elf.R_SPARC_8": "debug/elf", - "elf.R_SPARC_COPY": "debug/elf", - "elf.R_SPARC_DISP16": "debug/elf", - "elf.R_SPARC_DISP32": "debug/elf", - "elf.R_SPARC_DISP64": "debug/elf", - "elf.R_SPARC_DISP8": "debug/elf", - "elf.R_SPARC_GLOB_DAT": "debug/elf", - "elf.R_SPARC_GLOB_JMP": "debug/elf", - "elf.R_SPARC_GOT10": "debug/elf", - "elf.R_SPARC_GOT13": "debug/elf", - "elf.R_SPARC_GOT22": "debug/elf", - "elf.R_SPARC_H44": "debug/elf", - "elf.R_SPARC_HH22": "debug/elf", - "elf.R_SPARC_HI22": "debug/elf", - "elf.R_SPARC_HIPLT22": "debug/elf", - "elf.R_SPARC_HIX22": "debug/elf", - "elf.R_SPARC_HM10": "debug/elf", - "elf.R_SPARC_JMP_SLOT": "debug/elf", - "elf.R_SPARC_L44": "debug/elf", - "elf.R_SPARC_LM22": "debug/elf", - "elf.R_SPARC_LO10": "debug/elf", - "elf.R_SPARC_LOPLT10": "debug/elf", - "elf.R_SPARC_LOX10": "debug/elf", - "elf.R_SPARC_M44": "debug/elf", - "elf.R_SPARC_NONE": "debug/elf", - "elf.R_SPARC_OLO10": "debug/elf", - "elf.R_SPARC_PC10": "debug/elf", - "elf.R_SPARC_PC22": "debug/elf", - "elf.R_SPARC_PCPLT10": "debug/elf", - "elf.R_SPARC_PCPLT22": "debug/elf", - "elf.R_SPARC_PCPLT32": "debug/elf", - "elf.R_SPARC_PC_HH22": "debug/elf", - "elf.R_SPARC_PC_HM10": "debug/elf", - "elf.R_SPARC_PC_LM22": "debug/elf", - "elf.R_SPARC_PLT32": "debug/elf", - "elf.R_SPARC_PLT64": "debug/elf", - "elf.R_SPARC_REGISTER": "debug/elf", - "elf.R_SPARC_RELATIVE": "debug/elf", - "elf.R_SPARC_UA16": "debug/elf", - "elf.R_SPARC_UA32": "debug/elf", - "elf.R_SPARC_UA64": "debug/elf", - "elf.R_SPARC_WDISP16": "debug/elf", - "elf.R_SPARC_WDISP19": "debug/elf", - "elf.R_SPARC_WDISP22": "debug/elf", - "elf.R_SPARC_WDISP30": "debug/elf", - "elf.R_SPARC_WPLT30": "debug/elf", - "elf.R_SYM32": "debug/elf", - "elf.R_SYM64": "debug/elf", - "elf.R_TYPE32": "debug/elf", - "elf.R_TYPE64": "debug/elf", - "elf.R_X86_64": "debug/elf", - "elf.R_X86_64_16": "debug/elf", - "elf.R_X86_64_32": "debug/elf", - "elf.R_X86_64_32S": "debug/elf", - "elf.R_X86_64_64": "debug/elf", - "elf.R_X86_64_8": "debug/elf", - "elf.R_X86_64_COPY": "debug/elf", - "elf.R_X86_64_DTPMOD64": "debug/elf", - "elf.R_X86_64_DTPOFF32": "debug/elf", - "elf.R_X86_64_DTPOFF64": "debug/elf", - "elf.R_X86_64_GLOB_DAT": "debug/elf", - "elf.R_X86_64_GOT32": "debug/elf", - "elf.R_X86_64_GOTPCREL": "debug/elf", - "elf.R_X86_64_GOTTPOFF": "debug/elf", - "elf.R_X86_64_JMP_SLOT": "debug/elf", - "elf.R_X86_64_NONE": "debug/elf", - "elf.R_X86_64_PC16": "debug/elf", - "elf.R_X86_64_PC32": "debug/elf", - "elf.R_X86_64_PC8": "debug/elf", - "elf.R_X86_64_PLT32": "debug/elf", - "elf.R_X86_64_RELATIVE": "debug/elf", - "elf.R_X86_64_TLSGD": "debug/elf", - "elf.R_X86_64_TLSLD": "debug/elf", - "elf.R_X86_64_TPOFF32": "debug/elf", - "elf.R_X86_64_TPOFF64": "debug/elf", - "elf.Rel32": "debug/elf", - "elf.Rel64": "debug/elf", - "elf.Rela32": "debug/elf", - "elf.Rela64": "debug/elf", - "elf.SHF_ALLOC": "debug/elf", - "elf.SHF_EXECINSTR": "debug/elf", - "elf.SHF_GROUP": "debug/elf", - "elf.SHF_INFO_LINK": "debug/elf", - "elf.SHF_LINK_ORDER": "debug/elf", - "elf.SHF_MASKOS": "debug/elf", - "elf.SHF_MASKPROC": "debug/elf", - "elf.SHF_MERGE": "debug/elf", - "elf.SHF_OS_NONCONFORMING": "debug/elf", - "elf.SHF_STRINGS": "debug/elf", - "elf.SHF_TLS": "debug/elf", - "elf.SHF_WRITE": "debug/elf", - "elf.SHN_ABS": "debug/elf", - "elf.SHN_COMMON": "debug/elf", - "elf.SHN_HIOS": "debug/elf", - "elf.SHN_HIPROC": "debug/elf", - "elf.SHN_HIRESERVE": "debug/elf", - "elf.SHN_LOOS": "debug/elf", - "elf.SHN_LOPROC": "debug/elf", - "elf.SHN_LORESERVE": "debug/elf", - "elf.SHN_UNDEF": "debug/elf", - "elf.SHN_XINDEX": "debug/elf", - "elf.SHT_DYNAMIC": "debug/elf", - "elf.SHT_DYNSYM": "debug/elf", - "elf.SHT_FINI_ARRAY": "debug/elf", - "elf.SHT_GNU_ATTRIBUTES": "debug/elf", - "elf.SHT_GNU_HASH": "debug/elf", - "elf.SHT_GNU_LIBLIST": "debug/elf", - "elf.SHT_GNU_VERDEF": "debug/elf", - "elf.SHT_GNU_VERNEED": "debug/elf", - "elf.SHT_GNU_VERSYM": "debug/elf", - "elf.SHT_GROUP": "debug/elf", - "elf.SHT_HASH": "debug/elf", - "elf.SHT_HIOS": "debug/elf", - "elf.SHT_HIPROC": "debug/elf", - "elf.SHT_HIUSER": "debug/elf", - "elf.SHT_INIT_ARRAY": "debug/elf", - "elf.SHT_LOOS": "debug/elf", - "elf.SHT_LOPROC": "debug/elf", - "elf.SHT_LOUSER": "debug/elf", - "elf.SHT_NOBITS": "debug/elf", - "elf.SHT_NOTE": "debug/elf", - "elf.SHT_NULL": "debug/elf", - "elf.SHT_PREINIT_ARRAY": "debug/elf", - "elf.SHT_PROGBITS": "debug/elf", - "elf.SHT_REL": "debug/elf", - "elf.SHT_RELA": "debug/elf", - "elf.SHT_SHLIB": "debug/elf", - "elf.SHT_STRTAB": "debug/elf", - "elf.SHT_SYMTAB": "debug/elf", - "elf.SHT_SYMTAB_SHNDX": "debug/elf", - "elf.STB_GLOBAL": "debug/elf", - "elf.STB_HIOS": "debug/elf", - "elf.STB_HIPROC": "debug/elf", - "elf.STB_LOCAL": "debug/elf", - "elf.STB_LOOS": "debug/elf", - "elf.STB_LOPROC": "debug/elf", - "elf.STB_WEAK": "debug/elf", - "elf.STT_COMMON": "debug/elf", - "elf.STT_FILE": "debug/elf", - "elf.STT_FUNC": "debug/elf", - "elf.STT_HIOS": "debug/elf", - "elf.STT_HIPROC": "debug/elf", - "elf.STT_LOOS": "debug/elf", - "elf.STT_LOPROC": "debug/elf", - "elf.STT_NOTYPE": "debug/elf", - "elf.STT_OBJECT": "debug/elf", - "elf.STT_SECTION": "debug/elf", - "elf.STT_TLS": "debug/elf", - "elf.STV_DEFAULT": "debug/elf", - "elf.STV_HIDDEN": "debug/elf", - "elf.STV_INTERNAL": "debug/elf", - "elf.STV_PROTECTED": "debug/elf", - "elf.ST_BIND": "debug/elf", - "elf.ST_INFO": "debug/elf", - "elf.ST_TYPE": "debug/elf", - "elf.ST_VISIBILITY": "debug/elf", - "elf.Section": "debug/elf", - "elf.Section32": "debug/elf", - "elf.Section64": "debug/elf", - "elf.SectionFlag": "debug/elf", - "elf.SectionHeader": "debug/elf", - "elf.SectionIndex": "debug/elf", - "elf.SectionType": "debug/elf", - "elf.Sym32": "debug/elf", - "elf.Sym32Size": "debug/elf", - "elf.Sym64": "debug/elf", - "elf.Sym64Size": "debug/elf", - "elf.SymBind": "debug/elf", - "elf.SymType": "debug/elf", - "elf.SymVis": "debug/elf", - "elf.Symbol": "debug/elf", - "elf.Type": "debug/elf", - "elf.Version": "debug/elf", - "elliptic.Curve": "crypto/elliptic", - "elliptic.CurveParams": "crypto/elliptic", - "elliptic.GenerateKey": "crypto/elliptic", - "elliptic.Marshal": "crypto/elliptic", - "elliptic.P224": "crypto/elliptic", - "elliptic.P256": "crypto/elliptic", - "elliptic.P384": "crypto/elliptic", - "elliptic.P521": "crypto/elliptic", - "elliptic.Unmarshal": "crypto/elliptic", - "encoding.BinaryMarshaler": "encoding", - "encoding.BinaryUnmarshaler": "encoding", - "encoding.TextMarshaler": "encoding", - "encoding.TextUnmarshaler": "encoding", - "errors.New": "errors", - "exec.Cmd": "os/exec", - "exec.Command": "os/exec", - "exec.ErrNotFound": "os/exec", - "exec.Error": "os/exec", - "exec.ExitError": "os/exec", - "exec.LookPath": "os/exec", - "expvar.Do": "expvar", - "expvar.Float": "expvar", - "expvar.Func": "expvar", - "expvar.Get": "expvar", - "expvar.Int": "expvar", - "expvar.KeyValue": "expvar", - "expvar.Map": "expvar", - "expvar.NewFloat": "expvar", - "expvar.NewInt": "expvar", - "expvar.NewMap": "expvar", - "expvar.NewString": "expvar", - "expvar.Publish": "expvar", - "expvar.String": "expvar", - "expvar.Var": "expvar", - "fcgi.ErrConnClosed": "net/http/fcgi", - "fcgi.ErrRequestAborted": "net/http/fcgi", - "fcgi.Serve": "net/http/fcgi", - "filepath.Abs": "path/filepath", - "filepath.Base": "path/filepath", - "filepath.Clean": "path/filepath", - "filepath.Dir": "path/filepath", - "filepath.ErrBadPattern": "path/filepath", - "filepath.EvalSymlinks": "path/filepath", - "filepath.Ext": "path/filepath", - "filepath.FromSlash": "path/filepath", - "filepath.Glob": "path/filepath", - "filepath.HasPrefix": "path/filepath", - "filepath.IsAbs": "path/filepath", - "filepath.Join": "path/filepath", - "filepath.ListSeparator": "path/filepath", - "filepath.Match": "path/filepath", - "filepath.Rel": "path/filepath", - "filepath.Separator": "path/filepath", - "filepath.SkipDir": "path/filepath", - "filepath.Split": "path/filepath", - "filepath.SplitList": "path/filepath", - "filepath.ToSlash": "path/filepath", - "filepath.VolumeName": "path/filepath", - "filepath.Walk": "path/filepath", - "filepath.WalkFunc": "path/filepath", - "flag.Arg": "flag", - "flag.Args": "flag", - "flag.Bool": "flag", - "flag.BoolVar": "flag", - "flag.CommandLine": "flag", - "flag.ContinueOnError": "flag", - "flag.Duration": "flag", - "flag.DurationVar": "flag", - "flag.ErrHelp": "flag", - "flag.ErrorHandling": "flag", - "flag.ExitOnError": "flag", - "flag.Flag": "flag", - "flag.FlagSet": "flag", - "flag.Float64": "flag", - "flag.Float64Var": "flag", - "flag.Getter": "flag", - "flag.Int": "flag", - "flag.Int64": "flag", - "flag.Int64Var": "flag", - "flag.IntVar": "flag", - "flag.Lookup": "flag", - "flag.NArg": "flag", - "flag.NFlag": "flag", - "flag.NewFlagSet": "flag", - "flag.PanicOnError": "flag", - "flag.Parse": "flag", - "flag.Parsed": "flag", - "flag.PrintDefaults": "flag", - "flag.Set": "flag", - "flag.String": "flag", - "flag.StringVar": "flag", - "flag.Uint": "flag", - "flag.Uint64": "flag", - "flag.Uint64Var": "flag", - "flag.UintVar": "flag", - "flag.UnquoteUsage": "flag", - "flag.Usage": "flag", - "flag.Value": "flag", - "flag.Var": "flag", - "flag.Visit": "flag", - "flag.VisitAll": "flag", - "flate.BestCompression": "compress/flate", - "flate.BestSpeed": "compress/flate", - "flate.CorruptInputError": "compress/flate", - "flate.DefaultCompression": "compress/flate", - "flate.InternalError": "compress/flate", - "flate.NewReader": "compress/flate", - "flate.NewReaderDict": "compress/flate", - "flate.NewWriter": "compress/flate", - "flate.NewWriterDict": "compress/flate", - "flate.NoCompression": "compress/flate", - "flate.ReadError": "compress/flate", - "flate.Reader": "compress/flate", - "flate.Resetter": "compress/flate", - "flate.WriteError": "compress/flate", - "flate.Writer": "compress/flate", - "fmt.Errorf": "fmt", - "fmt.Formatter": "fmt", - "fmt.Fprint": "fmt", - "fmt.Fprintf": "fmt", - "fmt.Fprintln": "fmt", - "fmt.Fscan": "fmt", - "fmt.Fscanf": "fmt", - "fmt.Fscanln": "fmt", - "fmt.GoStringer": "fmt", - "fmt.Print": "fmt", - "fmt.Printf": "fmt", - "fmt.Println": "fmt", - "fmt.Scan": "fmt", - "fmt.ScanState": "fmt", - "fmt.Scanf": "fmt", - "fmt.Scanln": "fmt", - "fmt.Scanner": "fmt", - "fmt.Sprint": "fmt", - "fmt.Sprintf": "fmt", - "fmt.Sprintln": "fmt", - "fmt.Sscan": "fmt", - "fmt.Sscanf": "fmt", - "fmt.Sscanln": "fmt", - "fmt.State": "fmt", - "fmt.Stringer": "fmt", - "fnv.New32": "hash/fnv", - "fnv.New32a": "hash/fnv", - "fnv.New64": "hash/fnv", - "fnv.New64a": "hash/fnv", - "format.Node": "go/format", - "format.Source": "go/format", - "gif.Decode": "image/gif", - "gif.DecodeAll": "image/gif", - "gif.DecodeConfig": "image/gif", - "gif.DisposalBackground": "image/gif", - "gif.DisposalNone": "image/gif", - "gif.DisposalPrevious": "image/gif", - "gif.Encode": "image/gif", - "gif.EncodeAll": "image/gif", - "gif.GIF": "image/gif", - "gif.Options": "image/gif", - "gob.CommonType": "encoding/gob", - "gob.Decoder": "encoding/gob", - "gob.Encoder": "encoding/gob", - "gob.GobDecoder": "encoding/gob", - "gob.GobEncoder": "encoding/gob", - "gob.NewDecoder": "encoding/gob", - "gob.NewEncoder": "encoding/gob", - "gob.Register": "encoding/gob", - "gob.RegisterName": "encoding/gob", - "gosym.DecodingError": "debug/gosym", - "gosym.Func": "debug/gosym", - "gosym.LineTable": "debug/gosym", - "gosym.NewLineTable": "debug/gosym", - "gosym.NewTable": "debug/gosym", - "gosym.Obj": "debug/gosym", - "gosym.Sym": "debug/gosym", - "gosym.Table": "debug/gosym", - "gosym.UnknownFileError": "debug/gosym", - "gosym.UnknownLineError": "debug/gosym", - "gzip.BestCompression": "compress/gzip", - "gzip.BestSpeed": "compress/gzip", - "gzip.DefaultCompression": "compress/gzip", - "gzip.ErrChecksum": "compress/gzip", - "gzip.ErrHeader": "compress/gzip", - "gzip.Header": "compress/gzip", - "gzip.NewReader": "compress/gzip", - "gzip.NewWriter": "compress/gzip", - "gzip.NewWriterLevel": "compress/gzip", - "gzip.NoCompression": "compress/gzip", - "gzip.Reader": "compress/gzip", - "gzip.Writer": "compress/gzip", - "hash.Hash": "hash", - "hash.Hash32": "hash", - "hash.Hash64": "hash", - "heap.Fix": "container/heap", - "heap.Init": "container/heap", - "heap.Interface": "container/heap", - "heap.Pop": "container/heap", - "heap.Push": "container/heap", - "heap.Remove": "container/heap", - "hex.Decode": "encoding/hex", - "hex.DecodeString": "encoding/hex", - "hex.DecodedLen": "encoding/hex", - "hex.Dump": "encoding/hex", - "hex.Dumper": "encoding/hex", - "hex.Encode": "encoding/hex", - "hex.EncodeToString": "encoding/hex", - "hex.EncodedLen": "encoding/hex", - "hex.ErrLength": "encoding/hex", - "hex.InvalidByteError": "encoding/hex", - "hmac.Equal": "crypto/hmac", - "hmac.New": "crypto/hmac", - "html.EscapeString": "html", - "html.UnescapeString": "html", - "http.CanonicalHeaderKey": "net/http", - "http.Client": "net/http", - "http.CloseNotifier": "net/http", - "http.ConnState": "net/http", - "http.Cookie": "net/http", - "http.CookieJar": "net/http", - "http.DefaultClient": "net/http", - "http.DefaultMaxHeaderBytes": "net/http", - "http.DefaultMaxIdleConnsPerHost": "net/http", - "http.DefaultServeMux": "net/http", - "http.DefaultTransport": "net/http", - "http.DetectContentType": "net/http", - "http.Dir": "net/http", - "http.ErrBodyNotAllowed": "net/http", - "http.ErrBodyReadAfterClose": "net/http", - "http.ErrContentLength": "net/http", - "http.ErrHandlerTimeout": "net/http", - "http.ErrHeaderTooLong": "net/http", - "http.ErrHijacked": "net/http", - "http.ErrLineTooLong": "net/http", - "http.ErrMissingBoundary": "net/http", - "http.ErrMissingContentLength": "net/http", - "http.ErrMissingFile": "net/http", - "http.ErrNoCookie": "net/http", - "http.ErrNoLocation": "net/http", - "http.ErrNotMultipart": "net/http", - "http.ErrNotSupported": "net/http", - "http.ErrShortBody": "net/http", - "http.ErrUnexpectedTrailer": "net/http", - "http.ErrWriteAfterFlush": "net/http", - "http.Error": "net/http", - "http.File": "net/http", - "http.FileServer": "net/http", - "http.FileSystem": "net/http", - "http.Flusher": "net/http", - "http.Get": "net/http", - "http.Handle": "net/http", - "http.HandleFunc": "net/http", - "http.Handler": "net/http", - "http.HandlerFunc": "net/http", - "http.Head": "net/http", - "http.Header": "net/http", - "http.Hijacker": "net/http", - "http.ListenAndServe": "net/http", - "http.ListenAndServeTLS": "net/http", - "http.MaxBytesReader": "net/http", - "http.NewFileTransport": "net/http", - "http.NewRequest": "net/http", - "http.NewServeMux": "net/http", - "http.NotFound": "net/http", - "http.NotFoundHandler": "net/http", - "http.ParseHTTPVersion": "net/http", - "http.ParseTime": "net/http", - "http.Post": "net/http", - "http.PostForm": "net/http", - "http.ProtocolError": "net/http", - "http.ProxyFromEnvironment": "net/http", - "http.ProxyURL": "net/http", - "http.ReadRequest": "net/http", - "http.ReadResponse": "net/http", - "http.Redirect": "net/http", - "http.RedirectHandler": "net/http", - "http.Request": "net/http", - "http.Response": "net/http", - "http.ResponseWriter": "net/http", - "http.RoundTripper": "net/http", - "http.Serve": "net/http", - "http.ServeContent": "net/http", - "http.ServeFile": "net/http", - "http.ServeMux": "net/http", - "http.Server": "net/http", - "http.SetCookie": "net/http", - "http.StateActive": "net/http", - "http.StateClosed": "net/http", - "http.StateHijacked": "net/http", - "http.StateIdle": "net/http", - "http.StateNew": "net/http", - "http.StatusAccepted": "net/http", - "http.StatusBadGateway": "net/http", - "http.StatusBadRequest": "net/http", - "http.StatusConflict": "net/http", - "http.StatusContinue": "net/http", - "http.StatusCreated": "net/http", - "http.StatusExpectationFailed": "net/http", - "http.StatusForbidden": "net/http", - "http.StatusFound": "net/http", - "http.StatusGatewayTimeout": "net/http", - "http.StatusGone": "net/http", - "http.StatusHTTPVersionNotSupported": "net/http", - "http.StatusInternalServerError": "net/http", - "http.StatusLengthRequired": "net/http", - "http.StatusMethodNotAllowed": "net/http", - "http.StatusMovedPermanently": "net/http", - "http.StatusMultipleChoices": "net/http", - "http.StatusNoContent": "net/http", - "http.StatusNonAuthoritativeInfo": "net/http", - "http.StatusNotAcceptable": "net/http", - "http.StatusNotFound": "net/http", - "http.StatusNotImplemented": "net/http", - "http.StatusNotModified": "net/http", - "http.StatusOK": "net/http", - "http.StatusPartialContent": "net/http", - "http.StatusPaymentRequired": "net/http", - "http.StatusPreconditionFailed": "net/http", - "http.StatusProxyAuthRequired": "net/http", - "http.StatusRequestEntityTooLarge": "net/http", - "http.StatusRequestTimeout": "net/http", - "http.StatusRequestURITooLong": "net/http", - "http.StatusRequestedRangeNotSatisfiable": "net/http", - "http.StatusResetContent": "net/http", - "http.StatusSeeOther": "net/http", - "http.StatusServiceUnavailable": "net/http", - "http.StatusSwitchingProtocols": "net/http", - "http.StatusTeapot": "net/http", - "http.StatusTemporaryRedirect": "net/http", - "http.StatusText": "net/http", - "http.StatusUnauthorized": "net/http", - "http.StatusUnsupportedMediaType": "net/http", - "http.StatusUseProxy": "net/http", - "http.StripPrefix": "net/http", - "http.TimeFormat": "net/http", - "http.TimeoutHandler": "net/http", - "http.Transport": "net/http", - "httptest.DefaultRemoteAddr": "net/http/httptest", - "httptest.NewRecorder": "net/http/httptest", - "httptest.NewServer": "net/http/httptest", - "httptest.NewTLSServer": "net/http/httptest", - "httptest.NewUnstartedServer": "net/http/httptest", - "httptest.ResponseRecorder": "net/http/httptest", - "httptest.Server": "net/http/httptest", - "httputil.ClientConn": "net/http/httputil", - "httputil.DumpRequest": "net/http/httputil", - "httputil.DumpRequestOut": "net/http/httputil", - "httputil.DumpResponse": "net/http/httputil", - "httputil.ErrClosed": "net/http/httputil", - "httputil.ErrLineTooLong": "net/http/httputil", - "httputil.ErrPersistEOF": "net/http/httputil", - "httputil.ErrPipeline": "net/http/httputil", - "httputil.NewChunkedReader": "net/http/httputil", - "httputil.NewChunkedWriter": "net/http/httputil", - "httputil.NewClientConn": "net/http/httputil", - "httputil.NewProxyClientConn": "net/http/httputil", - "httputil.NewServerConn": "net/http/httputil", - "httputil.NewSingleHostReverseProxy": "net/http/httputil", - "httputil.ReverseProxy": "net/http/httputil", - "httputil.ServerConn": "net/http/httputil", - "image.Alpha": "image", - "image.Alpha16": "image", - "image.Black": "image", - "image.CMYK": "image", - "image.Config": "image", - "image.Decode": "image", - "image.DecodeConfig": "image", - "image.ErrFormat": "image", - "image.Gray": "image", - "image.Gray16": "image", - "image.Image": "image", - "image.NRGBA": "image", - "image.NRGBA64": "image", - "image.NewAlpha": "image", - "image.NewAlpha16": "image", - "image.NewCMYK": "image", - "image.NewGray": "image", - "image.NewGray16": "image", - "image.NewNRGBA": "image", - "image.NewNRGBA64": "image", - "image.NewPaletted": "image", - "image.NewRGBA": "image", - "image.NewRGBA64": "image", - "image.NewUniform": "image", - "image.NewYCbCr": "image", - "image.Opaque": "image", - "image.Paletted": "image", - "image.PalettedImage": "image", - "image.Point": "image", - "image.Pt": "image", - "image.RGBA": "image", - "image.RGBA64": "image", - "image.Rect": "image", - "image.Rectangle": "image", - "image.RegisterFormat": "image", - "image.Transparent": "image", - "image.Uniform": "image", - "image.White": "image", - "image.YCbCr": "image", - "image.YCbCrSubsampleRatio": "image", - "image.YCbCrSubsampleRatio410": "image", - "image.YCbCrSubsampleRatio411": "image", - "image.YCbCrSubsampleRatio420": "image", - "image.YCbCrSubsampleRatio422": "image", - "image.YCbCrSubsampleRatio440": "image", - "image.YCbCrSubsampleRatio444": "image", - "image.ZP": "image", - "image.ZR": "image", - "importer.Default": "go/importer", - "importer.For": "go/importer", - "importer.Lookup": "go/importer", - "io.ByteReader": "io", - "io.ByteScanner": "io", - "io.ByteWriter": "io", - "io.Closer": "io", - "io.Copy": "io", - "io.CopyBuffer": "io", - "io.CopyN": "io", - "io.EOF": "io", - "io.ErrClosedPipe": "io", - "io.ErrNoProgress": "io", - "io.ErrShortBuffer": "io", - "io.ErrShortWrite": "io", - "io.ErrUnexpectedEOF": "io", - "io.LimitReader": "io", - "io.LimitedReader": "io", - "io.MultiReader": "io", - "io.MultiWriter": "io", - "io.NewSectionReader": "io", - "io.Pipe": "io", - "io.PipeReader": "io", - "io.PipeWriter": "io", - "io.ReadAtLeast": "io", - "io.ReadCloser": "io", - "io.ReadFull": "io", - "io.ReadSeeker": "io", - "io.ReadWriteCloser": "io", - "io.ReadWriteSeeker": "io", - "io.ReadWriter": "io", - "io.Reader": "io", - "io.ReaderAt": "io", - "io.ReaderFrom": "io", - "io.RuneReader": "io", - "io.RuneScanner": "io", - "io.SectionReader": "io", - "io.Seeker": "io", - "io.TeeReader": "io", - "io.WriteCloser": "io", - "io.WriteSeeker": "io", - "io.WriteString": "io", - "io.Writer": "io", - "io.WriterAt": "io", - "io.WriterTo": "io", - "iotest.DataErrReader": "testing/iotest", - "iotest.ErrTimeout": "testing/iotest", - "iotest.HalfReader": "testing/iotest", - "iotest.NewReadLogger": "testing/iotest", - "iotest.NewWriteLogger": "testing/iotest", - "iotest.OneByteReader": "testing/iotest", - "iotest.TimeoutReader": "testing/iotest", - "iotest.TruncateWriter": "testing/iotest", - "ioutil.Discard": "io/ioutil", - "ioutil.NopCloser": "io/ioutil", - "ioutil.ReadAll": "io/ioutil", - "ioutil.ReadDir": "io/ioutil", - "ioutil.ReadFile": "io/ioutil", - "ioutil.TempDir": "io/ioutil", - "ioutil.TempFile": "io/ioutil", - "ioutil.WriteFile": "io/ioutil", - "jpeg.Decode": "image/jpeg", - "jpeg.DecodeConfig": "image/jpeg", - "jpeg.DefaultQuality": "image/jpeg", - "jpeg.Encode": "image/jpeg", - "jpeg.FormatError": "image/jpeg", - "jpeg.Options": "image/jpeg", - "jpeg.Reader": "image/jpeg", - "jpeg.UnsupportedError": "image/jpeg", - "json.Compact": "encoding/json", - "json.Decoder": "encoding/json", - "json.Delim": "encoding/json", - "json.Encoder": "encoding/json", - "json.HTMLEscape": "encoding/json", - "json.Indent": "encoding/json", - "json.InvalidUTF8Error": "encoding/json", - "json.InvalidUnmarshalError": "encoding/json", - "json.Marshal": "encoding/json", - "json.MarshalIndent": "encoding/json", - "json.Marshaler": "encoding/json", - "json.MarshalerError": "encoding/json", - "json.NewDecoder": "encoding/json", - "json.NewEncoder": "encoding/json", - "json.Number": "encoding/json", - "json.RawMessage": "encoding/json", - "json.SyntaxError": "encoding/json", - "json.Token": "encoding/json", - "json.Unmarshal": "encoding/json", - "json.UnmarshalFieldError": "encoding/json", - "json.UnmarshalTypeError": "encoding/json", - "json.Unmarshaler": "encoding/json", - "json.UnsupportedTypeError": "encoding/json", - "json.UnsupportedValueError": "encoding/json", - "jsonrpc.Dial": "net/rpc/jsonrpc", - "jsonrpc.NewClient": "net/rpc/jsonrpc", - "jsonrpc.NewClientCodec": "net/rpc/jsonrpc", - "jsonrpc.NewServerCodec": "net/rpc/jsonrpc", - "jsonrpc.ServeConn": "net/rpc/jsonrpc", - "list.Element": "container/list", - "list.List": "container/list", - "list.New": "container/list", - "log.Fatal": "log", - "log.Fatalf": "log", - "log.Fatalln": "log", - "log.Flags": "log", - "log.LUTC": "log", - "log.Ldate": "log", - "log.Llongfile": "log", - "log.Lmicroseconds": "log", - "log.Logger": "log", - "log.Lshortfile": "log", - "log.LstdFlags": "log", - "log.Ltime": "log", - "log.New": "log", - "log.Output": "log", - "log.Panic": "log", - "log.Panicf": "log", - "log.Panicln": "log", - "log.Prefix": "log", - "log.Print": "log", - "log.Printf": "log", - "log.Println": "log", - "log.SetFlags": "log", - "log.SetOutput": "log", - "log.SetPrefix": "log", - "lzw.LSB": "compress/lzw", - "lzw.MSB": "compress/lzw", - "lzw.NewReader": "compress/lzw", - "lzw.NewWriter": "compress/lzw", - "lzw.Order": "compress/lzw", - "macho.Cpu": "debug/macho", - "macho.Cpu386": "debug/macho", - "macho.CpuAmd64": "debug/macho", - "macho.CpuArm": "debug/macho", - "macho.CpuPpc": "debug/macho", - "macho.CpuPpc64": "debug/macho", - "macho.Dylib": "debug/macho", - "macho.DylibCmd": "debug/macho", - "macho.Dysymtab": "debug/macho", - "macho.DysymtabCmd": "debug/macho", - "macho.ErrNotFat": "debug/macho", - "macho.FatArch": "debug/macho", - "macho.FatArchHeader": "debug/macho", - "macho.FatFile": "debug/macho", - "macho.File": "debug/macho", - "macho.FileHeader": "debug/macho", - "macho.FormatError": "debug/macho", - "macho.Load": "debug/macho", - "macho.LoadBytes": "debug/macho", - "macho.LoadCmd": "debug/macho", - "macho.LoadCmdDylib": "debug/macho", - "macho.LoadCmdDylinker": "debug/macho", - "macho.LoadCmdDysymtab": "debug/macho", - "macho.LoadCmdSegment": "debug/macho", - "macho.LoadCmdSegment64": "debug/macho", - "macho.LoadCmdSymtab": "debug/macho", - "macho.LoadCmdThread": "debug/macho", - "macho.LoadCmdUnixThread": "debug/macho", - "macho.Magic32": "debug/macho", - "macho.Magic64": "debug/macho", - "macho.MagicFat": "debug/macho", - "macho.NewFatFile": "debug/macho", - "macho.NewFile": "debug/macho", - "macho.Nlist32": "debug/macho", - "macho.Nlist64": "debug/macho", - "macho.Open": "debug/macho", - "macho.OpenFat": "debug/macho", - "macho.Regs386": "debug/macho", - "macho.RegsAMD64": "debug/macho", - "macho.Section": "debug/macho", - "macho.Section32": "debug/macho", - "macho.Section64": "debug/macho", - "macho.SectionHeader": "debug/macho", - "macho.Segment": "debug/macho", - "macho.Segment32": "debug/macho", - "macho.Segment64": "debug/macho", - "macho.SegmentHeader": "debug/macho", - "macho.Symbol": "debug/macho", - "macho.Symtab": "debug/macho", - "macho.SymtabCmd": "debug/macho", - "macho.Thread": "debug/macho", - "macho.Type": "debug/macho", - "macho.TypeBundle": "debug/macho", - "macho.TypeDylib": "debug/macho", - "macho.TypeExec": "debug/macho", - "macho.TypeObj": "debug/macho", - "mail.Address": "net/mail", - "mail.AddressParser": "net/mail", - "mail.ErrHeaderNotPresent": "net/mail", - "mail.Header": "net/mail", - "mail.Message": "net/mail", - "mail.ParseAddress": "net/mail", - "mail.ParseAddressList": "net/mail", - "mail.ReadMessage": "net/mail", - "math.Abs": "math", - "math.Acos": "math", - "math.Acosh": "math", - "math.Asin": "math", - "math.Asinh": "math", - "math.Atan": "math", - "math.Atan2": "math", - "math.Atanh": "math", - "math.Cbrt": "math", - "math.Ceil": "math", - "math.Copysign": "math", - "math.Cos": "math", - "math.Cosh": "math", - "math.Dim": "math", - "math.E": "math", - "math.Erf": "math", - "math.Erfc": "math", - "math.Exp": "math", - "math.Exp2": "math", - "math.Expm1": "math", - "math.Float32bits": "math", - "math.Float32frombits": "math", - "math.Float64bits": "math", - "math.Float64frombits": "math", - "math.Floor": "math", - "math.Frexp": "math", - "math.Gamma": "math", - "math.Hypot": "math", - "math.Ilogb": "math", - "math.Inf": "math", - "math.IsInf": "math", - "math.IsNaN": "math", - "math.J0": "math", - "math.J1": "math", - "math.Jn": "math", - "math.Ldexp": "math", - "math.Lgamma": "math", - "math.Ln10": "math", - "math.Ln2": "math", - "math.Log": "math", - "math.Log10": "math", - "math.Log10E": "math", - "math.Log1p": "math", - "math.Log2": "math", - "math.Log2E": "math", - "math.Logb": "math", - "math.Max": "math", - "math.MaxFloat32": "math", - "math.MaxFloat64": "math", - "math.MaxInt16": "math", - "math.MaxInt32": "math", - "math.MaxInt64": "math", - "math.MaxInt8": "math", - "math.MaxUint16": "math", - "math.MaxUint32": "math", - "math.MaxUint64": "math", - "math.MaxUint8": "math", - "math.Min": "math", - "math.MinInt16": "math", - "math.MinInt32": "math", - "math.MinInt64": "math", - "math.MinInt8": "math", - "math.Mod": "math", - "math.Modf": "math", - "math.NaN": "math", - "math.Nextafter": "math", - "math.Nextafter32": "math", - "math.Phi": "math", - "math.Pi": "math", - "math.Pow": "math", - "math.Pow10": "math", - "math.Remainder": "math", - "math.Signbit": "math", - "math.Sin": "math", - "math.Sincos": "math", - "math.Sinh": "math", - "math.SmallestNonzeroFloat32": "math", - "math.SmallestNonzeroFloat64": "math", - "math.Sqrt": "math", - "math.Sqrt2": "math", - "math.SqrtE": "math", - "math.SqrtPhi": "math", - "math.SqrtPi": "math", - "math.Tan": "math", - "math.Tanh": "math", - "math.Trunc": "math", - "math.Y0": "math", - "math.Y1": "math", - "math.Yn": "math", - "md5.BlockSize": "crypto/md5", - "md5.New": "crypto/md5", - "md5.Size": "crypto/md5", - "md5.Sum": "crypto/md5", - "mime.AddExtensionType": "mime", - "mime.BEncoding": "mime", - "mime.ExtensionsByType": "mime", - "mime.FormatMediaType": "mime", - "mime.ParseMediaType": "mime", - "mime.QEncoding": "mime", - "mime.TypeByExtension": "mime", - "mime.WordDecoder": "mime", - "mime.WordEncoder": "mime", - "multipart.File": "mime/multipart", - "multipart.FileHeader": "mime/multipart", - "multipart.Form": "mime/multipart", - "multipart.NewReader": "mime/multipart", - "multipart.NewWriter": "mime/multipart", - "multipart.Part": "mime/multipart", - "multipart.Reader": "mime/multipart", - "multipart.Writer": "mime/multipart", - "net.Addr": "net", - "net.AddrError": "net", - "net.CIDRMask": "net", - "net.Conn": "net", - "net.DNSConfigError": "net", - "net.DNSError": "net", - "net.Dial": "net", - "net.DialIP": "net", - "net.DialTCP": "net", - "net.DialTimeout": "net", - "net.DialUDP": "net", - "net.DialUnix": "net", - "net.Dialer": "net", - "net.ErrWriteToConnected": "net", - "net.Error": "net", - "net.FileConn": "net", - "net.FileListener": "net", - "net.FilePacketConn": "net", - "net.FlagBroadcast": "net", - "net.FlagLoopback": "net", - "net.FlagMulticast": "net", - "net.FlagPointToPoint": "net", - "net.FlagUp": "net", - "net.Flags": "net", - "net.HardwareAddr": "net", - "net.IP": "net", - "net.IPAddr": "net", - "net.IPConn": "net", - "net.IPMask": "net", - "net.IPNet": "net", - "net.IPv4": "net", - "net.IPv4Mask": "net", - "net.IPv4allrouter": "net", - "net.IPv4allsys": "net", - "net.IPv4bcast": "net", - "net.IPv4len": "net", - "net.IPv4zero": "net", - "net.IPv6interfacelocalallnodes": "net", - "net.IPv6len": "net", - "net.IPv6linklocalallnodes": "net", - "net.IPv6linklocalallrouters": "net", - "net.IPv6loopback": "net", - "net.IPv6unspecified": "net", - "net.IPv6zero": "net", - "net.Interface": "net", - "net.InterfaceAddrs": "net", - "net.InterfaceByIndex": "net", - "net.InterfaceByName": "net", - "net.Interfaces": "net", - "net.InvalidAddrError": "net", - "net.JoinHostPort": "net", - "net.Listen": "net", - "net.ListenIP": "net", - "net.ListenMulticastUDP": "net", - "net.ListenPacket": "net", - "net.ListenTCP": "net", - "net.ListenUDP": "net", - "net.ListenUnix": "net", - "net.ListenUnixgram": "net", - "net.Listener": "net", - "net.LookupAddr": "net", - "net.LookupCNAME": "net", - "net.LookupHost": "net", - "net.LookupIP": "net", - "net.LookupMX": "net", - "net.LookupNS": "net", - "net.LookupPort": "net", - "net.LookupSRV": "net", - "net.LookupTXT": "net", - "net.MX": "net", - "net.NS": "net", - "net.OpError": "net", - "net.PacketConn": "net", - "net.ParseCIDR": "net", - "net.ParseError": "net", - "net.ParseIP": "net", - "net.ParseMAC": "net", - "net.Pipe": "net", - "net.ResolveIPAddr": "net", - "net.ResolveTCPAddr": "net", - "net.ResolveUDPAddr": "net", - "net.ResolveUnixAddr": "net", - "net.SRV": "net", - "net.SplitHostPort": "net", - "net.TCPAddr": "net", - "net.TCPConn": "net", - "net.TCPListener": "net", - "net.UDPAddr": "net", - "net.UDPConn": "net", - "net.UnixAddr": "net", - "net.UnixConn": "net", - "net.UnixListener": "net", - "net.UnknownNetworkError": "net", - "os.Args": "os", - "os.Chdir": "os", - "os.Chmod": "os", - "os.Chown": "os", - "os.Chtimes": "os", - "os.Clearenv": "os", - "os.Create": "os", - "os.DevNull": "os", - "os.Environ": "os", - "os.ErrExist": "os", - "os.ErrInvalid": "os", - "os.ErrNotExist": "os", - "os.ErrPermission": "os", - "os.Exit": "os", - "os.Expand": "os", - "os.ExpandEnv": "os", - "os.File": "os", - "os.FileInfo": "os", - "os.FileMode": "os", - "os.FindProcess": "os", - "os.Getegid": "os", - "os.Getenv": "os", - "os.Geteuid": "os", - "os.Getgid": "os", - "os.Getgroups": "os", - "os.Getpagesize": "os", - "os.Getpid": "os", - "os.Getppid": "os", - "os.Getuid": "os", - "os.Getwd": "os", - "os.Hostname": "os", - "os.Interrupt": "os", - "os.IsExist": "os", - "os.IsNotExist": "os", - "os.IsPathSeparator": "os", - "os.IsPermission": "os", - "os.Kill": "os", - "os.Lchown": "os", - "os.Link": "os", - "os.LinkError": "os", - "os.LookupEnv": "os", - "os.Lstat": "os", - "os.Mkdir": "os", - "os.MkdirAll": "os", - "os.ModeAppend": "os", - "os.ModeCharDevice": "os", - "os.ModeDevice": "os", - "os.ModeDir": "os", - "os.ModeExclusive": "os", - "os.ModeNamedPipe": "os", - "os.ModePerm": "os", - "os.ModeSetgid": "os", - "os.ModeSetuid": "os", - "os.ModeSocket": "os", - "os.ModeSticky": "os", - "os.ModeSymlink": "os", - "os.ModeTemporary": "os", - "os.ModeType": "os", - "os.NewFile": "os", - "os.NewSyscallError": "os", - "os.O_APPEND": "os", - "os.O_CREATE": "os", - "os.O_EXCL": "os", - "os.O_RDONLY": "os", - "os.O_RDWR": "os", - "os.O_SYNC": "os", - "os.O_TRUNC": "os", - "os.O_WRONLY": "os", - "os.Open": "os", - "os.OpenFile": "os", - "os.PathError": "os", - "os.PathListSeparator": "os", - "os.PathSeparator": "os", - "os.Pipe": "os", - "os.ProcAttr": "os", - "os.Process": "os", - "os.ProcessState": "os", - "os.Readlink": "os", - "os.Remove": "os", - "os.RemoveAll": "os", - "os.Rename": "os", - "os.SEEK_CUR": "os", - "os.SEEK_END": "os", - "os.SEEK_SET": "os", - "os.SameFile": "os", - "os.Setenv": "os", - "os.Signal": "os", - "os.StartProcess": "os", - "os.Stat": "os", - "os.Stderr": "os", - "os.Stdin": "os", - "os.Stdout": "os", - "os.Symlink": "os", - "os.SyscallError": "os", - "os.TempDir": "os", - "os.Truncate": "os", - "os.Unsetenv": "os", - "palette.Plan9": "image/color/palette", - "palette.WebSafe": "image/color/palette", - "parse.ActionNode": "text/template/parse", - "parse.BoolNode": "text/template/parse", - "parse.BranchNode": "text/template/parse", - "parse.ChainNode": "text/template/parse", - "parse.CommandNode": "text/template/parse", - "parse.DotNode": "text/template/parse", - "parse.FieldNode": "text/template/parse", - "parse.IdentifierNode": "text/template/parse", - "parse.IfNode": "text/template/parse", - "parse.IsEmptyTree": "text/template/parse", - "parse.ListNode": "text/template/parse", - "parse.New": "text/template/parse", - "parse.NewIdentifier": "text/template/parse", - "parse.NilNode": "text/template/parse", - "parse.Node": "text/template/parse", - "parse.NodeAction": "text/template/parse", - "parse.NodeBool": "text/template/parse", - "parse.NodeChain": "text/template/parse", - "parse.NodeCommand": "text/template/parse", - "parse.NodeDot": "text/template/parse", - "parse.NodeField": "text/template/parse", - "parse.NodeIdentifier": "text/template/parse", - "parse.NodeIf": "text/template/parse", - "parse.NodeList": "text/template/parse", - "parse.NodeNil": "text/template/parse", - "parse.NodeNumber": "text/template/parse", - "parse.NodePipe": "text/template/parse", - "parse.NodeRange": "text/template/parse", - "parse.NodeString": "text/template/parse", - "parse.NodeTemplate": "text/template/parse", - "parse.NodeText": "text/template/parse", - "parse.NodeType": "text/template/parse", - "parse.NodeVariable": "text/template/parse", - "parse.NodeWith": "text/template/parse", - "parse.NumberNode": "text/template/parse", - "parse.Parse": "text/template/parse", - "parse.PipeNode": "text/template/parse", - "parse.Pos": "text/template/parse", - "parse.RangeNode": "text/template/parse", - "parse.StringNode": "text/template/parse", - "parse.TemplateNode": "text/template/parse", - "parse.TextNode": "text/template/parse", - "parse.Tree": "text/template/parse", - "parse.VariableNode": "text/template/parse", - "parse.WithNode": "text/template/parse", - "parser.AllErrors": "go/parser", - "parser.DeclarationErrors": "go/parser", - "parser.ImportsOnly": "go/parser", - "parser.Mode": "go/parser", - "parser.PackageClauseOnly": "go/parser", - "parser.ParseComments": "go/parser", - "parser.ParseDir": "go/parser", - "parser.ParseExpr": "go/parser", - "parser.ParseExprFrom": "go/parser", - "parser.ParseFile": "go/parser", - "parser.SpuriousErrors": "go/parser", - "parser.Trace": "go/parser", - "path.Base": "path", - "path.Clean": "path", - "path.Dir": "path", - "path.ErrBadPattern": "path", - "path.Ext": "path", - "path.IsAbs": "path", - "path.Join": "path", - "path.Match": "path", - "path.Split": "path", - "pe.COFFSymbol": "debug/pe", - "pe.COFFSymbolSize": "debug/pe", - "pe.DataDirectory": "debug/pe", - "pe.File": "debug/pe", - "pe.FileHeader": "debug/pe", - "pe.FormatError": "debug/pe", - "pe.IMAGE_FILE_MACHINE_AM33": "debug/pe", - "pe.IMAGE_FILE_MACHINE_AMD64": "debug/pe", - "pe.IMAGE_FILE_MACHINE_ARM": "debug/pe", - "pe.IMAGE_FILE_MACHINE_EBC": "debug/pe", - "pe.IMAGE_FILE_MACHINE_I386": "debug/pe", - "pe.IMAGE_FILE_MACHINE_IA64": "debug/pe", - "pe.IMAGE_FILE_MACHINE_M32R": "debug/pe", - "pe.IMAGE_FILE_MACHINE_MIPS16": "debug/pe", - "pe.IMAGE_FILE_MACHINE_MIPSFPU": "debug/pe", - "pe.IMAGE_FILE_MACHINE_MIPSFPU16": "debug/pe", - "pe.IMAGE_FILE_MACHINE_POWERPC": "debug/pe", - "pe.IMAGE_FILE_MACHINE_POWERPCFP": "debug/pe", - "pe.IMAGE_FILE_MACHINE_R4000": "debug/pe", - "pe.IMAGE_FILE_MACHINE_SH3": "debug/pe", - "pe.IMAGE_FILE_MACHINE_SH3DSP": "debug/pe", - "pe.IMAGE_FILE_MACHINE_SH4": "debug/pe", - "pe.IMAGE_FILE_MACHINE_SH5": "debug/pe", - "pe.IMAGE_FILE_MACHINE_THUMB": "debug/pe", - "pe.IMAGE_FILE_MACHINE_UNKNOWN": "debug/pe", - "pe.IMAGE_FILE_MACHINE_WCEMIPSV2": "debug/pe", - "pe.ImportDirectory": "debug/pe", - "pe.NewFile": "debug/pe", - "pe.Open": "debug/pe", - "pe.OptionalHeader32": "debug/pe", - "pe.OptionalHeader64": "debug/pe", - "pe.Section": "debug/pe", - "pe.SectionHeader": "debug/pe", - "pe.SectionHeader32": "debug/pe", - "pe.Symbol": "debug/pe", - "pem.Block": "encoding/pem", - "pem.Decode": "encoding/pem", - "pem.Encode": "encoding/pem", - "pem.EncodeToMemory": "encoding/pem", - "pkix.AlgorithmIdentifier": "crypto/x509/pkix", - "pkix.AttributeTypeAndValue": "crypto/x509/pkix", - "pkix.AttributeTypeAndValueSET": "crypto/x509/pkix", - "pkix.CertificateList": "crypto/x509/pkix", - "pkix.Extension": "crypto/x509/pkix", - "pkix.Name": "crypto/x509/pkix", - "pkix.RDNSequence": "crypto/x509/pkix", - "pkix.RelativeDistinguishedNameSET": "crypto/x509/pkix", - "pkix.RevokedCertificate": "crypto/x509/pkix", - "pkix.TBSCertificateList": "crypto/x509/pkix", - "plan9obj.File": "debug/plan9obj", - "plan9obj.FileHeader": "debug/plan9obj", - "plan9obj.Magic386": "debug/plan9obj", - "plan9obj.Magic64": "debug/plan9obj", - "plan9obj.MagicAMD64": "debug/plan9obj", - "plan9obj.MagicARM": "debug/plan9obj", - "plan9obj.NewFile": "debug/plan9obj", - "plan9obj.Open": "debug/plan9obj", - "plan9obj.Section": "debug/plan9obj", - "plan9obj.SectionHeader": "debug/plan9obj", - "plan9obj.Sym": "debug/plan9obj", - "png.BestCompression": "image/png", - "png.BestSpeed": "image/png", - "png.CompressionLevel": "image/png", - "png.Decode": "image/png", - "png.DecodeConfig": "image/png", - "png.DefaultCompression": "image/png", - "png.Encode": "image/png", - "png.Encoder": "image/png", - "png.FormatError": "image/png", - "png.NoCompression": "image/png", - "png.UnsupportedError": "image/png", - "pprof.Cmdline": "net/http/pprof", - "pprof.Handler": "net/http/pprof", - "pprof.Index": "net/http/pprof", - "pprof.Lookup": "runtime/pprof", - "pprof.NewProfile": "runtime/pprof", - // "pprof.Profile" is ambiguous - "pprof.Profiles": "runtime/pprof", - "pprof.StartCPUProfile": "runtime/pprof", - "pprof.StopCPUProfile": "runtime/pprof", - "pprof.Symbol": "net/http/pprof", - "pprof.Trace": "net/http/pprof", - "pprof.WriteHeapProfile": "runtime/pprof", - "printer.CommentedNode": "go/printer", - "printer.Config": "go/printer", - "printer.Fprint": "go/printer", - "printer.Mode": "go/printer", - "printer.RawFormat": "go/printer", - "printer.SourcePos": "go/printer", - "printer.TabIndent": "go/printer", - "printer.UseSpaces": "go/printer", - "quick.Check": "testing/quick", - "quick.CheckEqual": "testing/quick", - "quick.CheckEqualError": "testing/quick", - "quick.CheckError": "testing/quick", - "quick.Config": "testing/quick", - "quick.Generator": "testing/quick", - "quick.SetupError": "testing/quick", - "quick.Value": "testing/quick", - "quotedprintable.NewReader": "mime/quotedprintable", - "quotedprintable.NewWriter": "mime/quotedprintable", - "quotedprintable.Reader": "mime/quotedprintable", - "quotedprintable.Writer": "mime/quotedprintable", - "rand.ExpFloat64": "math/rand", - "rand.Float32": "math/rand", - "rand.Float64": "math/rand", - // "rand.Int" is ambiguous - "rand.Int31": "math/rand", - "rand.Int31n": "math/rand", - "rand.Int63": "math/rand", - "rand.Int63n": "math/rand", - "rand.Intn": "math/rand", - "rand.New": "math/rand", - "rand.NewSource": "math/rand", - "rand.NewZipf": "math/rand", - "rand.NormFloat64": "math/rand", - "rand.Perm": "math/rand", - "rand.Prime": "crypto/rand", - "rand.Rand": "math/rand", - "rand.Read": "crypto/rand", - "rand.Reader": "crypto/rand", - "rand.Seed": "math/rand", - "rand.Source": "math/rand", - "rand.Uint32": "math/rand", - "rand.Zipf": "math/rand", - "rc4.Cipher": "crypto/rc4", - "rc4.KeySizeError": "crypto/rc4", - "rc4.NewCipher": "crypto/rc4", - "reflect.Append": "reflect", - "reflect.AppendSlice": "reflect", - "reflect.Array": "reflect", - "reflect.ArrayOf": "reflect", - "reflect.Bool": "reflect", - "reflect.BothDir": "reflect", - "reflect.Chan": "reflect", - "reflect.ChanDir": "reflect", - "reflect.ChanOf": "reflect", - "reflect.Complex128": "reflect", - "reflect.Complex64": "reflect", - "reflect.Copy": "reflect", - "reflect.DeepEqual": "reflect", - "reflect.Float32": "reflect", - "reflect.Float64": "reflect", - "reflect.Func": "reflect", - "reflect.FuncOf": "reflect", - "reflect.Indirect": "reflect", - "reflect.Int": "reflect", - "reflect.Int16": "reflect", - "reflect.Int32": "reflect", - "reflect.Int64": "reflect", - "reflect.Int8": "reflect", - "reflect.Interface": "reflect", - "reflect.Invalid": "reflect", - "reflect.Kind": "reflect", - "reflect.MakeChan": "reflect", - "reflect.MakeFunc": "reflect", - "reflect.MakeMap": "reflect", - "reflect.MakeSlice": "reflect", - "reflect.Map": "reflect", - "reflect.MapOf": "reflect", - "reflect.Method": "reflect", - "reflect.New": "reflect", - "reflect.NewAt": "reflect", - "reflect.Ptr": "reflect", - "reflect.PtrTo": "reflect", - "reflect.RecvDir": "reflect", - "reflect.Select": "reflect", - "reflect.SelectCase": "reflect", - "reflect.SelectDefault": "reflect", - "reflect.SelectDir": "reflect", - "reflect.SelectRecv": "reflect", - "reflect.SelectSend": "reflect", - "reflect.SendDir": "reflect", - "reflect.Slice": "reflect", - "reflect.SliceHeader": "reflect", - "reflect.SliceOf": "reflect", - "reflect.String": "reflect", - "reflect.StringHeader": "reflect", - "reflect.Struct": "reflect", - "reflect.StructField": "reflect", - "reflect.StructTag": "reflect", - "reflect.TypeOf": "reflect", - "reflect.Uint": "reflect", - "reflect.Uint16": "reflect", - "reflect.Uint32": "reflect", - "reflect.Uint64": "reflect", - "reflect.Uint8": "reflect", - "reflect.Uintptr": "reflect", - "reflect.UnsafePointer": "reflect", - "reflect.Value": "reflect", - "reflect.ValueError": "reflect", - "reflect.ValueOf": "reflect", - "reflect.Zero": "reflect", - "regexp.Compile": "regexp", - "regexp.CompilePOSIX": "regexp", - "regexp.Match": "regexp", - "regexp.MatchReader": "regexp", - "regexp.MatchString": "regexp", - "regexp.MustCompile": "regexp", - "regexp.MustCompilePOSIX": "regexp", - "regexp.QuoteMeta": "regexp", - "regexp.Regexp": "regexp", - "ring.New": "container/ring", - "ring.Ring": "container/ring", - "rpc.Accept": "net/rpc", - "rpc.Call": "net/rpc", - "rpc.Client": "net/rpc", - "rpc.ClientCodec": "net/rpc", - "rpc.DefaultDebugPath": "net/rpc", - "rpc.DefaultRPCPath": "net/rpc", - "rpc.DefaultServer": "net/rpc", - "rpc.Dial": "net/rpc", - "rpc.DialHTTP": "net/rpc", - "rpc.DialHTTPPath": "net/rpc", - "rpc.ErrShutdown": "net/rpc", - "rpc.HandleHTTP": "net/rpc", - "rpc.NewClient": "net/rpc", - "rpc.NewClientWithCodec": "net/rpc", - "rpc.NewServer": "net/rpc", - "rpc.Register": "net/rpc", - "rpc.RegisterName": "net/rpc", - "rpc.Request": "net/rpc", - "rpc.Response": "net/rpc", - "rpc.ServeCodec": "net/rpc", - "rpc.ServeConn": "net/rpc", - "rpc.ServeRequest": "net/rpc", - "rpc.Server": "net/rpc", - "rpc.ServerCodec": "net/rpc", - "rpc.ServerError": "net/rpc", - "rsa.CRTValue": "crypto/rsa", - "rsa.DecryptOAEP": "crypto/rsa", - "rsa.DecryptPKCS1v15": "crypto/rsa", - "rsa.DecryptPKCS1v15SessionKey": "crypto/rsa", - "rsa.EncryptOAEP": "crypto/rsa", - "rsa.EncryptPKCS1v15": "crypto/rsa", - "rsa.ErrDecryption": "crypto/rsa", - "rsa.ErrMessageTooLong": "crypto/rsa", - "rsa.ErrVerification": "crypto/rsa", - "rsa.GenerateKey": "crypto/rsa", - "rsa.GenerateMultiPrimeKey": "crypto/rsa", - "rsa.OAEPOptions": "crypto/rsa", - "rsa.PKCS1v15DecryptOptions": "crypto/rsa", - "rsa.PSSOptions": "crypto/rsa", - "rsa.PSSSaltLengthAuto": "crypto/rsa", - "rsa.PSSSaltLengthEqualsHash": "crypto/rsa", - "rsa.PrecomputedValues": "crypto/rsa", - "rsa.PrivateKey": "crypto/rsa", - "rsa.PublicKey": "crypto/rsa", - "rsa.SignPKCS1v15": "crypto/rsa", - "rsa.SignPSS": "crypto/rsa", - "rsa.VerifyPKCS1v15": "crypto/rsa", - "rsa.VerifyPSS": "crypto/rsa", - "runtime.BlockProfile": "runtime", - "runtime.BlockProfileRecord": "runtime", - "runtime.Breakpoint": "runtime", - "runtime.CPUProfile": "runtime", - "runtime.Caller": "runtime", - "runtime.Callers": "runtime", - "runtime.Compiler": "runtime", - "runtime.Error": "runtime", - "runtime.Func": "runtime", - "runtime.FuncForPC": "runtime", - "runtime.GC": "runtime", - "runtime.GOARCH": "runtime", - "runtime.GOMAXPROCS": "runtime", - "runtime.GOOS": "runtime", - "runtime.GOROOT": "runtime", - "runtime.Goexit": "runtime", - "runtime.GoroutineProfile": "runtime", - "runtime.Gosched": "runtime", - "runtime.LockOSThread": "runtime", - "runtime.MemProfile": "runtime", - "runtime.MemProfileRate": "runtime", - "runtime.MemProfileRecord": "runtime", - "runtime.MemStats": "runtime", - "runtime.NumCPU": "runtime", - "runtime.NumCgoCall": "runtime", - "runtime.NumGoroutine": "runtime", - "runtime.ReadMemStats": "runtime", - "runtime.ReadTrace": "runtime", - "runtime.SetBlockProfileRate": "runtime", - "runtime.SetCPUProfileRate": "runtime", - "runtime.SetFinalizer": "runtime", - "runtime.Stack": "runtime", - "runtime.StackRecord": "runtime", - "runtime.StartTrace": "runtime", - "runtime.StopTrace": "runtime", - "runtime.ThreadCreateProfile": "runtime", - "runtime.TypeAssertionError": "runtime", - "runtime.UnlockOSThread": "runtime", - "runtime.Version": "runtime", - "scanner.Char": "text/scanner", - "scanner.Comment": "text/scanner", - "scanner.EOF": "text/scanner", - "scanner.Error": "go/scanner", - "scanner.ErrorHandler": "go/scanner", - "scanner.ErrorList": "go/scanner", - "scanner.Float": "text/scanner", - "scanner.GoTokens": "text/scanner", - "scanner.GoWhitespace": "text/scanner", - "scanner.Ident": "text/scanner", - "scanner.Int": "text/scanner", - "scanner.Mode": "go/scanner", - "scanner.Position": "text/scanner", - "scanner.PrintError": "go/scanner", - "scanner.RawString": "text/scanner", - "scanner.ScanChars": "text/scanner", - // "scanner.ScanComments" is ambiguous - "scanner.ScanFloats": "text/scanner", - "scanner.ScanIdents": "text/scanner", - "scanner.ScanInts": "text/scanner", - "scanner.ScanRawStrings": "text/scanner", - "scanner.ScanStrings": "text/scanner", - // "scanner.Scanner" is ambiguous - "scanner.SkipComments": "text/scanner", - "scanner.String": "text/scanner", - "scanner.TokenString": "text/scanner", - "sha1.BlockSize": "crypto/sha1", - "sha1.New": "crypto/sha1", - "sha1.Size": "crypto/sha1", - "sha1.Sum": "crypto/sha1", - "sha256.BlockSize": "crypto/sha256", - "sha256.New": "crypto/sha256", - "sha256.New224": "crypto/sha256", - "sha256.Size": "crypto/sha256", - "sha256.Size224": "crypto/sha256", - "sha256.Sum224": "crypto/sha256", - "sha256.Sum256": "crypto/sha256", - "sha512.BlockSize": "crypto/sha512", - "sha512.New": "crypto/sha512", - "sha512.New384": "crypto/sha512", - "sha512.New512_224": "crypto/sha512", - "sha512.New512_256": "crypto/sha512", - "sha512.Size": "crypto/sha512", - "sha512.Size224": "crypto/sha512", - "sha512.Size256": "crypto/sha512", - "sha512.Size384": "crypto/sha512", - "sha512.Sum384": "crypto/sha512", - "sha512.Sum512": "crypto/sha512", - "sha512.Sum512_224": "crypto/sha512", - "sha512.Sum512_256": "crypto/sha512", - "signal.Ignore": "os/signal", - "signal.Notify": "os/signal", - "signal.Reset": "os/signal", - "signal.Stop": "os/signal", - "smtp.Auth": "net/smtp", - "smtp.CRAMMD5Auth": "net/smtp", - "smtp.Client": "net/smtp", - "smtp.Dial": "net/smtp", - "smtp.NewClient": "net/smtp", - "smtp.PlainAuth": "net/smtp", - "smtp.SendMail": "net/smtp", - "smtp.ServerInfo": "net/smtp", - "sort.Float64Slice": "sort", - "sort.Float64s": "sort", - "sort.Float64sAreSorted": "sort", - "sort.IntSlice": "sort", - "sort.Interface": "sort", - "sort.Ints": "sort", - "sort.IntsAreSorted": "sort", - "sort.IsSorted": "sort", - "sort.Reverse": "sort", - "sort.Search": "sort", - "sort.SearchFloat64s": "sort", - "sort.SearchInts": "sort", - "sort.SearchStrings": "sort", - "sort.Sort": "sort", - "sort.Stable": "sort", - "sort.StringSlice": "sort", - "sort.Strings": "sort", - "sort.StringsAreSorted": "sort", - "sql.DB": "database/sql", - "sql.DBStats": "database/sql", - "sql.Drivers": "database/sql", - "sql.ErrNoRows": "database/sql", - "sql.ErrTxDone": "database/sql", - "sql.NullBool": "database/sql", - "sql.NullFloat64": "database/sql", - "sql.NullInt64": "database/sql", - "sql.NullString": "database/sql", - "sql.Open": "database/sql", - "sql.RawBytes": "database/sql", - "sql.Register": "database/sql", - "sql.Result": "database/sql", - "sql.Row": "database/sql", - "sql.Rows": "database/sql", - "sql.Scanner": "database/sql", - "sql.Stmt": "database/sql", - "sql.Tx": "database/sql", - "strconv.AppendBool": "strconv", - "strconv.AppendFloat": "strconv", - "strconv.AppendInt": "strconv", - "strconv.AppendQuote": "strconv", - "strconv.AppendQuoteRune": "strconv", - "strconv.AppendQuoteRuneToASCII": "strconv", - "strconv.AppendQuoteToASCII": "strconv", - "strconv.AppendUint": "strconv", - "strconv.Atoi": "strconv", - "strconv.CanBackquote": "strconv", - "strconv.ErrRange": "strconv", - "strconv.ErrSyntax": "strconv", - "strconv.FormatBool": "strconv", - "strconv.FormatFloat": "strconv", - "strconv.FormatInt": "strconv", - "strconv.FormatUint": "strconv", - "strconv.IntSize": "strconv", - "strconv.IsPrint": "strconv", - "strconv.Itoa": "strconv", - "strconv.NumError": "strconv", - "strconv.ParseBool": "strconv", - "strconv.ParseFloat": "strconv", - "strconv.ParseInt": "strconv", - "strconv.ParseUint": "strconv", - "strconv.Quote": "strconv", - "strconv.QuoteRune": "strconv", - "strconv.QuoteRuneToASCII": "strconv", - "strconv.QuoteToASCII": "strconv", - "strconv.Unquote": "strconv", - "strconv.UnquoteChar": "strconv", - "strings.Compare": "strings", - "strings.Contains": "strings", - "strings.ContainsAny": "strings", - "strings.ContainsRune": "strings", - "strings.Count": "strings", - "strings.EqualFold": "strings", - "strings.Fields": "strings", - "strings.FieldsFunc": "strings", - "strings.HasPrefix": "strings", - "strings.HasSuffix": "strings", - "strings.Index": "strings", - "strings.IndexAny": "strings", - "strings.IndexByte": "strings", - "strings.IndexFunc": "strings", - "strings.IndexRune": "strings", - "strings.Join": "strings", - "strings.LastIndex": "strings", - "strings.LastIndexAny": "strings", - "strings.LastIndexByte": "strings", - "strings.LastIndexFunc": "strings", - "strings.Map": "strings", - "strings.NewReader": "strings", - "strings.NewReplacer": "strings", - "strings.Reader": "strings", - "strings.Repeat": "strings", - "strings.Replace": "strings", - "strings.Replacer": "strings", - "strings.Split": "strings", - "strings.SplitAfter": "strings", - "strings.SplitAfterN": "strings", - "strings.SplitN": "strings", - "strings.Title": "strings", - "strings.ToLower": "strings", - "strings.ToLowerSpecial": "strings", - "strings.ToTitle": "strings", - "strings.ToTitleSpecial": "strings", - "strings.ToUpper": "strings", - "strings.ToUpperSpecial": "strings", - "strings.Trim": "strings", - "strings.TrimFunc": "strings", - "strings.TrimLeft": "strings", - "strings.TrimLeftFunc": "strings", - "strings.TrimPrefix": "strings", - "strings.TrimRight": "strings", - "strings.TrimRightFunc": "strings", - "strings.TrimSpace": "strings", - "strings.TrimSuffix": "strings", - "subtle.ConstantTimeByteEq": "crypto/subtle", - "subtle.ConstantTimeCompare": "crypto/subtle", - "subtle.ConstantTimeCopy": "crypto/subtle", - "subtle.ConstantTimeEq": "crypto/subtle", - "subtle.ConstantTimeLessOrEq": "crypto/subtle", - "subtle.ConstantTimeSelect": "crypto/subtle", - "suffixarray.Index": "index/suffixarray", - "suffixarray.New": "index/suffixarray", - "sync.Cond": "sync", - "sync.Locker": "sync", - "sync.Mutex": "sync", - "sync.NewCond": "sync", - "sync.Once": "sync", - "sync.Pool": "sync", - "sync.RWMutex": "sync", - "sync.WaitGroup": "sync", - "syntax.ClassNL": "regexp/syntax", - "syntax.Compile": "regexp/syntax", - "syntax.DotNL": "regexp/syntax", - "syntax.EmptyBeginLine": "regexp/syntax", - "syntax.EmptyBeginText": "regexp/syntax", - "syntax.EmptyEndLine": "regexp/syntax", - "syntax.EmptyEndText": "regexp/syntax", - "syntax.EmptyNoWordBoundary": "regexp/syntax", - "syntax.EmptyOp": "regexp/syntax", - "syntax.EmptyOpContext": "regexp/syntax", - "syntax.EmptyWordBoundary": "regexp/syntax", - "syntax.ErrInternalError": "regexp/syntax", - "syntax.ErrInvalidCharClass": "regexp/syntax", - "syntax.ErrInvalidCharRange": "regexp/syntax", - "syntax.ErrInvalidEscape": "regexp/syntax", - "syntax.ErrInvalidNamedCapture": "regexp/syntax", - "syntax.ErrInvalidPerlOp": "regexp/syntax", - "syntax.ErrInvalidRepeatOp": "regexp/syntax", - "syntax.ErrInvalidRepeatSize": "regexp/syntax", - "syntax.ErrInvalidUTF8": "regexp/syntax", - "syntax.ErrMissingBracket": "regexp/syntax", - "syntax.ErrMissingParen": "regexp/syntax", - "syntax.ErrMissingRepeatArgument": "regexp/syntax", - "syntax.ErrTrailingBackslash": "regexp/syntax", - "syntax.ErrUnexpectedParen": "regexp/syntax", - "syntax.Error": "regexp/syntax", - "syntax.ErrorCode": "regexp/syntax", - "syntax.Flags": "regexp/syntax", - "syntax.FoldCase": "regexp/syntax", - "syntax.Inst": "regexp/syntax", - "syntax.InstAlt": "regexp/syntax", - "syntax.InstAltMatch": "regexp/syntax", - "syntax.InstCapture": "regexp/syntax", - "syntax.InstEmptyWidth": "regexp/syntax", - "syntax.InstFail": "regexp/syntax", - "syntax.InstMatch": "regexp/syntax", - "syntax.InstNop": "regexp/syntax", - "syntax.InstOp": "regexp/syntax", - "syntax.InstRune": "regexp/syntax", - "syntax.InstRune1": "regexp/syntax", - "syntax.InstRuneAny": "regexp/syntax", - "syntax.InstRuneAnyNotNL": "regexp/syntax", - "syntax.IsWordChar": "regexp/syntax", - "syntax.Literal": "regexp/syntax", - "syntax.MatchNL": "regexp/syntax", - "syntax.NonGreedy": "regexp/syntax", - "syntax.OneLine": "regexp/syntax", - "syntax.Op": "regexp/syntax", - "syntax.OpAlternate": "regexp/syntax", - "syntax.OpAnyChar": "regexp/syntax", - "syntax.OpAnyCharNotNL": "regexp/syntax", - "syntax.OpBeginLine": "regexp/syntax", - "syntax.OpBeginText": "regexp/syntax", - "syntax.OpCapture": "regexp/syntax", - "syntax.OpCharClass": "regexp/syntax", - "syntax.OpConcat": "regexp/syntax", - "syntax.OpEmptyMatch": "regexp/syntax", - "syntax.OpEndLine": "regexp/syntax", - "syntax.OpEndText": "regexp/syntax", - "syntax.OpLiteral": "regexp/syntax", - "syntax.OpNoMatch": "regexp/syntax", - "syntax.OpNoWordBoundary": "regexp/syntax", - "syntax.OpPlus": "regexp/syntax", - "syntax.OpQuest": "regexp/syntax", - "syntax.OpRepeat": "regexp/syntax", - "syntax.OpStar": "regexp/syntax", - "syntax.OpWordBoundary": "regexp/syntax", - "syntax.POSIX": "regexp/syntax", - "syntax.Parse": "regexp/syntax", - "syntax.Perl": "regexp/syntax", - "syntax.PerlX": "regexp/syntax", - "syntax.Prog": "regexp/syntax", - "syntax.Regexp": "regexp/syntax", - "syntax.Simple": "regexp/syntax", - "syntax.UnicodeGroups": "regexp/syntax", - "syntax.WasDollar": "regexp/syntax", - "syscall.AF_ALG": "syscall", - "syscall.AF_APPLETALK": "syscall", - "syscall.AF_ARP": "syscall", - "syscall.AF_ASH": "syscall", - "syscall.AF_ATM": "syscall", - "syscall.AF_ATMPVC": "syscall", - "syscall.AF_ATMSVC": "syscall", - "syscall.AF_AX25": "syscall", - "syscall.AF_BLUETOOTH": "syscall", - "syscall.AF_BRIDGE": "syscall", - "syscall.AF_CAIF": "syscall", - "syscall.AF_CAN": "syscall", - "syscall.AF_CCITT": "syscall", - "syscall.AF_CHAOS": "syscall", - "syscall.AF_CNT": "syscall", - "syscall.AF_COIP": "syscall", - "syscall.AF_DATAKIT": "syscall", - "syscall.AF_DECnet": "syscall", - "syscall.AF_DLI": "syscall", - "syscall.AF_E164": "syscall", - "syscall.AF_ECMA": "syscall", - "syscall.AF_ECONET": "syscall", - "syscall.AF_ENCAP": "syscall", - "syscall.AF_FILE": "syscall", - "syscall.AF_HYLINK": "syscall", - "syscall.AF_IEEE80211": "syscall", - "syscall.AF_IEEE802154": "syscall", - "syscall.AF_IMPLINK": "syscall", - "syscall.AF_INET": "syscall", - "syscall.AF_INET6": "syscall", - "syscall.AF_INET6_SDP": "syscall", - "syscall.AF_INET_SDP": "syscall", - "syscall.AF_IPX": "syscall", - "syscall.AF_IRDA": "syscall", - "syscall.AF_ISDN": "syscall", - "syscall.AF_ISO": "syscall", - "syscall.AF_IUCV": "syscall", - "syscall.AF_KEY": "syscall", - "syscall.AF_LAT": "syscall", - "syscall.AF_LINK": "syscall", - "syscall.AF_LLC": "syscall", - "syscall.AF_LOCAL": "syscall", - "syscall.AF_MAX": "syscall", - "syscall.AF_MPLS": "syscall", - "syscall.AF_NATM": "syscall", - "syscall.AF_NDRV": "syscall", - "syscall.AF_NETBEUI": "syscall", - "syscall.AF_NETBIOS": "syscall", - "syscall.AF_NETGRAPH": "syscall", - "syscall.AF_NETLINK": "syscall", - "syscall.AF_NETROM": "syscall", - "syscall.AF_NS": "syscall", - "syscall.AF_OROUTE": "syscall", - "syscall.AF_OSI": "syscall", - "syscall.AF_PACKET": "syscall", - "syscall.AF_PHONET": "syscall", - "syscall.AF_PPP": "syscall", - "syscall.AF_PPPOX": "syscall", - "syscall.AF_PUP": "syscall", - "syscall.AF_RDS": "syscall", - "syscall.AF_RESERVED_36": "syscall", - "syscall.AF_ROSE": "syscall", - "syscall.AF_ROUTE": "syscall", - "syscall.AF_RXRPC": "syscall", - "syscall.AF_SCLUSTER": "syscall", - "syscall.AF_SECURITY": "syscall", - "syscall.AF_SIP": "syscall", - "syscall.AF_SLOW": "syscall", - "syscall.AF_SNA": "syscall", - "syscall.AF_SYSTEM": "syscall", - "syscall.AF_TIPC": "syscall", - "syscall.AF_UNIX": "syscall", - "syscall.AF_UNSPEC": "syscall", - "syscall.AF_VENDOR00": "syscall", - "syscall.AF_VENDOR01": "syscall", - "syscall.AF_VENDOR02": "syscall", - "syscall.AF_VENDOR03": "syscall", - "syscall.AF_VENDOR04": "syscall", - "syscall.AF_VENDOR05": "syscall", - "syscall.AF_VENDOR06": "syscall", - "syscall.AF_VENDOR07": "syscall", - "syscall.AF_VENDOR08": "syscall", - "syscall.AF_VENDOR09": "syscall", - "syscall.AF_VENDOR10": "syscall", - "syscall.AF_VENDOR11": "syscall", - "syscall.AF_VENDOR12": "syscall", - "syscall.AF_VENDOR13": "syscall", - "syscall.AF_VENDOR14": "syscall", - "syscall.AF_VENDOR15": "syscall", - "syscall.AF_VENDOR16": "syscall", - "syscall.AF_VENDOR17": "syscall", - "syscall.AF_VENDOR18": "syscall", - "syscall.AF_VENDOR19": "syscall", - "syscall.AF_VENDOR20": "syscall", - "syscall.AF_VENDOR21": "syscall", - "syscall.AF_VENDOR22": "syscall", - "syscall.AF_VENDOR23": "syscall", - "syscall.AF_VENDOR24": "syscall", - "syscall.AF_VENDOR25": "syscall", - "syscall.AF_VENDOR26": "syscall", - "syscall.AF_VENDOR27": "syscall", - "syscall.AF_VENDOR28": "syscall", - "syscall.AF_VENDOR29": "syscall", - "syscall.AF_VENDOR30": "syscall", - "syscall.AF_VENDOR31": "syscall", - "syscall.AF_VENDOR32": "syscall", - "syscall.AF_VENDOR33": "syscall", - "syscall.AF_VENDOR34": "syscall", - "syscall.AF_VENDOR35": "syscall", - "syscall.AF_VENDOR36": "syscall", - "syscall.AF_VENDOR37": "syscall", - "syscall.AF_VENDOR38": "syscall", - "syscall.AF_VENDOR39": "syscall", - "syscall.AF_VENDOR40": "syscall", - "syscall.AF_VENDOR41": "syscall", - "syscall.AF_VENDOR42": "syscall", - "syscall.AF_VENDOR43": "syscall", - "syscall.AF_VENDOR44": "syscall", - "syscall.AF_VENDOR45": "syscall", - "syscall.AF_VENDOR46": "syscall", - "syscall.AF_VENDOR47": "syscall", - "syscall.AF_WANPIPE": "syscall", - "syscall.AF_X25": "syscall", - "syscall.AI_CANONNAME": "syscall", - "syscall.AI_NUMERICHOST": "syscall", - "syscall.AI_PASSIVE": "syscall", - "syscall.APPLICATION_ERROR": "syscall", - "syscall.ARPHRD_ADAPT": "syscall", - "syscall.ARPHRD_APPLETLK": "syscall", - "syscall.ARPHRD_ARCNET": "syscall", - "syscall.ARPHRD_ASH": "syscall", - "syscall.ARPHRD_ATM": "syscall", - "syscall.ARPHRD_AX25": "syscall", - "syscall.ARPHRD_BIF": "syscall", - "syscall.ARPHRD_CHAOS": "syscall", - "syscall.ARPHRD_CISCO": "syscall", - "syscall.ARPHRD_CSLIP": "syscall", - "syscall.ARPHRD_CSLIP6": "syscall", - "syscall.ARPHRD_DDCMP": "syscall", - "syscall.ARPHRD_DLCI": "syscall", - "syscall.ARPHRD_ECONET": "syscall", - "syscall.ARPHRD_EETHER": "syscall", - "syscall.ARPHRD_ETHER": "syscall", - "syscall.ARPHRD_EUI64": "syscall", - "syscall.ARPHRD_FCAL": "syscall", - "syscall.ARPHRD_FCFABRIC": "syscall", - "syscall.ARPHRD_FCPL": "syscall", - "syscall.ARPHRD_FCPP": "syscall", - "syscall.ARPHRD_FDDI": "syscall", - "syscall.ARPHRD_FRAD": "syscall", - "syscall.ARPHRD_FRELAY": "syscall", - "syscall.ARPHRD_HDLC": "syscall", - "syscall.ARPHRD_HIPPI": "syscall", - "syscall.ARPHRD_HWX25": "syscall", - "syscall.ARPHRD_IEEE1394": "syscall", - "syscall.ARPHRD_IEEE802": "syscall", - "syscall.ARPHRD_IEEE80211": "syscall", - "syscall.ARPHRD_IEEE80211_PRISM": "syscall", - "syscall.ARPHRD_IEEE80211_RADIOTAP": "syscall", - "syscall.ARPHRD_IEEE802154": "syscall", - "syscall.ARPHRD_IEEE802154_PHY": "syscall", - "syscall.ARPHRD_IEEE802_TR": "syscall", - "syscall.ARPHRD_INFINIBAND": "syscall", - "syscall.ARPHRD_IPDDP": "syscall", - "syscall.ARPHRD_IPGRE": "syscall", - "syscall.ARPHRD_IRDA": "syscall", - "syscall.ARPHRD_LAPB": "syscall", - "syscall.ARPHRD_LOCALTLK": "syscall", - "syscall.ARPHRD_LOOPBACK": "syscall", - "syscall.ARPHRD_METRICOM": "syscall", - "syscall.ARPHRD_NETROM": "syscall", - "syscall.ARPHRD_NONE": "syscall", - "syscall.ARPHRD_PIMREG": "syscall", - "syscall.ARPHRD_PPP": "syscall", - "syscall.ARPHRD_PRONET": "syscall", - "syscall.ARPHRD_RAWHDLC": "syscall", - "syscall.ARPHRD_ROSE": "syscall", - "syscall.ARPHRD_RSRVD": "syscall", - "syscall.ARPHRD_SIT": "syscall", - "syscall.ARPHRD_SKIP": "syscall", - "syscall.ARPHRD_SLIP": "syscall", - "syscall.ARPHRD_SLIP6": "syscall", - "syscall.ARPHRD_STRIP": "syscall", - "syscall.ARPHRD_TUNNEL": "syscall", - "syscall.ARPHRD_TUNNEL6": "syscall", - "syscall.ARPHRD_VOID": "syscall", - "syscall.ARPHRD_X25": "syscall", - "syscall.AUTHTYPE_CLIENT": "syscall", - "syscall.AUTHTYPE_SERVER": "syscall", - "syscall.Accept": "syscall", - "syscall.Accept4": "syscall", - "syscall.AcceptEx": "syscall", - "syscall.Access": "syscall", - "syscall.Acct": "syscall", - "syscall.AddrinfoW": "syscall", - "syscall.Adjtime": "syscall", - "syscall.Adjtimex": "syscall", - "syscall.AttachLsf": "syscall", - "syscall.B0": "syscall", - "syscall.B1000000": "syscall", - "syscall.B110": "syscall", - "syscall.B115200": "syscall", - "syscall.B1152000": "syscall", - "syscall.B1200": "syscall", - "syscall.B134": "syscall", - "syscall.B14400": "syscall", - "syscall.B150": "syscall", - "syscall.B1500000": "syscall", - "syscall.B1800": "syscall", - "syscall.B19200": "syscall", - "syscall.B200": "syscall", - "syscall.B2000000": "syscall", - "syscall.B230400": "syscall", - "syscall.B2400": "syscall", - "syscall.B2500000": "syscall", - "syscall.B28800": "syscall", - "syscall.B300": "syscall", - "syscall.B3000000": "syscall", - "syscall.B3500000": "syscall", - "syscall.B38400": "syscall", - "syscall.B4000000": "syscall", - "syscall.B460800": "syscall", - "syscall.B4800": "syscall", - "syscall.B50": "syscall", - "syscall.B500000": "syscall", - "syscall.B57600": "syscall", - "syscall.B576000": "syscall", - "syscall.B600": "syscall", - "syscall.B7200": "syscall", - "syscall.B75": "syscall", - "syscall.B76800": "syscall", - "syscall.B921600": "syscall", - "syscall.B9600": "syscall", - "syscall.BASE_PROTOCOL": "syscall", - "syscall.BIOCFEEDBACK": "syscall", - "syscall.BIOCFLUSH": "syscall", - "syscall.BIOCGBLEN": "syscall", - "syscall.BIOCGDIRECTION": "syscall", - "syscall.BIOCGDIRFILT": "syscall", - "syscall.BIOCGDLT": "syscall", - "syscall.BIOCGDLTLIST": "syscall", - "syscall.BIOCGETBUFMODE": "syscall", - "syscall.BIOCGETIF": "syscall", - "syscall.BIOCGETZMAX": "syscall", - "syscall.BIOCGFEEDBACK": "syscall", - "syscall.BIOCGFILDROP": "syscall", - "syscall.BIOCGHDRCMPLT": "syscall", - "syscall.BIOCGRSIG": "syscall", - "syscall.BIOCGRTIMEOUT": "syscall", - "syscall.BIOCGSEESENT": "syscall", - "syscall.BIOCGSTATS": "syscall", - "syscall.BIOCGSTATSOLD": "syscall", - "syscall.BIOCGTSTAMP": "syscall", - "syscall.BIOCIMMEDIATE": "syscall", - "syscall.BIOCLOCK": "syscall", - "syscall.BIOCPROMISC": "syscall", - "syscall.BIOCROTZBUF": "syscall", - "syscall.BIOCSBLEN": "syscall", - "syscall.BIOCSDIRECTION": "syscall", - "syscall.BIOCSDIRFILT": "syscall", - "syscall.BIOCSDLT": "syscall", - "syscall.BIOCSETBUFMODE": "syscall", - "syscall.BIOCSETF": "syscall", - "syscall.BIOCSETFNR": "syscall", - "syscall.BIOCSETIF": "syscall", - "syscall.BIOCSETWF": "syscall", - "syscall.BIOCSETZBUF": "syscall", - "syscall.BIOCSFEEDBACK": "syscall", - "syscall.BIOCSFILDROP": "syscall", - "syscall.BIOCSHDRCMPLT": "syscall", - "syscall.BIOCSRSIG": "syscall", - "syscall.BIOCSRTIMEOUT": "syscall", - "syscall.BIOCSSEESENT": "syscall", - "syscall.BIOCSTCPF": "syscall", - "syscall.BIOCSTSTAMP": "syscall", - "syscall.BIOCSUDPF": "syscall", - "syscall.BIOCVERSION": "syscall", - "syscall.BPF_A": "syscall", - "syscall.BPF_ABS": "syscall", - "syscall.BPF_ADD": "syscall", - "syscall.BPF_ALIGNMENT": "syscall", - "syscall.BPF_ALIGNMENT32": "syscall", - "syscall.BPF_ALU": "syscall", - "syscall.BPF_AND": "syscall", - "syscall.BPF_B": "syscall", - "syscall.BPF_BUFMODE_BUFFER": "syscall", - "syscall.BPF_BUFMODE_ZBUF": "syscall", - "syscall.BPF_DFLTBUFSIZE": "syscall", - "syscall.BPF_DIRECTION_IN": "syscall", - "syscall.BPF_DIRECTION_OUT": "syscall", - "syscall.BPF_DIV": "syscall", - "syscall.BPF_H": "syscall", - "syscall.BPF_IMM": "syscall", - "syscall.BPF_IND": "syscall", - "syscall.BPF_JA": "syscall", - "syscall.BPF_JEQ": "syscall", - "syscall.BPF_JGE": "syscall", - "syscall.BPF_JGT": "syscall", - "syscall.BPF_JMP": "syscall", - "syscall.BPF_JSET": "syscall", - "syscall.BPF_K": "syscall", - "syscall.BPF_LD": "syscall", - "syscall.BPF_LDX": "syscall", - "syscall.BPF_LEN": "syscall", - "syscall.BPF_LSH": "syscall", - "syscall.BPF_MAJOR_VERSION": "syscall", - "syscall.BPF_MAXBUFSIZE": "syscall", - "syscall.BPF_MAXINSNS": "syscall", - "syscall.BPF_MEM": "syscall", - "syscall.BPF_MEMWORDS": "syscall", - "syscall.BPF_MINBUFSIZE": "syscall", - "syscall.BPF_MINOR_VERSION": "syscall", - "syscall.BPF_MISC": "syscall", - "syscall.BPF_MSH": "syscall", - "syscall.BPF_MUL": "syscall", - "syscall.BPF_NEG": "syscall", - "syscall.BPF_OR": "syscall", - "syscall.BPF_RELEASE": "syscall", - "syscall.BPF_RET": "syscall", - "syscall.BPF_RSH": "syscall", - "syscall.BPF_ST": "syscall", - "syscall.BPF_STX": "syscall", - "syscall.BPF_SUB": "syscall", - "syscall.BPF_TAX": "syscall", - "syscall.BPF_TXA": "syscall", - "syscall.BPF_T_BINTIME": "syscall", - "syscall.BPF_T_BINTIME_FAST": "syscall", - "syscall.BPF_T_BINTIME_MONOTONIC": "syscall", - "syscall.BPF_T_BINTIME_MONOTONIC_FAST": "syscall", - "syscall.BPF_T_FAST": "syscall", - "syscall.BPF_T_FLAG_MASK": "syscall", - "syscall.BPF_T_FORMAT_MASK": "syscall", - "syscall.BPF_T_MICROTIME": "syscall", - "syscall.BPF_T_MICROTIME_FAST": "syscall", - "syscall.BPF_T_MICROTIME_MONOTONIC": "syscall", - "syscall.BPF_T_MICROTIME_MONOTONIC_FAST": "syscall", - "syscall.BPF_T_MONOTONIC": "syscall", - "syscall.BPF_T_MONOTONIC_FAST": "syscall", - "syscall.BPF_T_NANOTIME": "syscall", - "syscall.BPF_T_NANOTIME_FAST": "syscall", - "syscall.BPF_T_NANOTIME_MONOTONIC": "syscall", - "syscall.BPF_T_NANOTIME_MONOTONIC_FAST": "syscall", - "syscall.BPF_T_NONE": "syscall", - "syscall.BPF_T_NORMAL": "syscall", - "syscall.BPF_W": "syscall", - "syscall.BPF_X": "syscall", - "syscall.BRKINT": "syscall", - "syscall.Bind": "syscall", - "syscall.BindToDevice": "syscall", - "syscall.BpfBuflen": "syscall", - "syscall.BpfDatalink": "syscall", - "syscall.BpfHdr": "syscall", - "syscall.BpfHeadercmpl": "syscall", - "syscall.BpfInsn": "syscall", - "syscall.BpfInterface": "syscall", - "syscall.BpfJump": "syscall", - "syscall.BpfProgram": "syscall", - "syscall.BpfStat": "syscall", - "syscall.BpfStats": "syscall", - "syscall.BpfStmt": "syscall", - "syscall.BpfTimeout": "syscall", - "syscall.BpfTimeval": "syscall", - "syscall.BpfVersion": "syscall", - "syscall.BpfZbuf": "syscall", - "syscall.BpfZbufHeader": "syscall", - "syscall.ByHandleFileInformation": "syscall", - "syscall.BytePtrFromString": "syscall", - "syscall.ByteSliceFromString": "syscall", - "syscall.CCR0_FLUSH": "syscall", - "syscall.CERT_CHAIN_POLICY_AUTHENTICODE": "syscall", - "syscall.CERT_CHAIN_POLICY_AUTHENTICODE_TS": "syscall", - "syscall.CERT_CHAIN_POLICY_BASE": "syscall", - "syscall.CERT_CHAIN_POLICY_BASIC_CONSTRAINTS": "syscall", - "syscall.CERT_CHAIN_POLICY_EV": "syscall", - "syscall.CERT_CHAIN_POLICY_MICROSOFT_ROOT": "syscall", - "syscall.CERT_CHAIN_POLICY_NT_AUTH": "syscall", - "syscall.CERT_CHAIN_POLICY_SSL": "syscall", - "syscall.CERT_E_CN_NO_MATCH": "syscall", - "syscall.CERT_E_EXPIRED": "syscall", - "syscall.CERT_E_PURPOSE": "syscall", - "syscall.CERT_E_ROLE": "syscall", - "syscall.CERT_E_UNTRUSTEDROOT": "syscall", - "syscall.CERT_STORE_ADD_ALWAYS": "syscall", - "syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG": "syscall", - "syscall.CERT_STORE_PROV_MEMORY": "syscall", - "syscall.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT": "syscall", - "syscall.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT": "syscall", - "syscall.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT": "syscall", - "syscall.CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT": "syscall", - "syscall.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT": "syscall", - "syscall.CERT_TRUST_INVALID_BASIC_CONSTRAINTS": "syscall", - "syscall.CERT_TRUST_INVALID_EXTENSION": "syscall", - "syscall.CERT_TRUST_INVALID_NAME_CONSTRAINTS": "syscall", - "syscall.CERT_TRUST_INVALID_POLICY_CONSTRAINTS": "syscall", - "syscall.CERT_TRUST_IS_CYCLIC": "syscall", - "syscall.CERT_TRUST_IS_EXPLICIT_DISTRUST": "syscall", - "syscall.CERT_TRUST_IS_NOT_SIGNATURE_VALID": "syscall", - "syscall.CERT_TRUST_IS_NOT_TIME_VALID": "syscall", - "syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE": "syscall", - "syscall.CERT_TRUST_IS_OFFLINE_REVOCATION": "syscall", - "syscall.CERT_TRUST_IS_REVOKED": "syscall", - "syscall.CERT_TRUST_IS_UNTRUSTED_ROOT": "syscall", - "syscall.CERT_TRUST_NO_ERROR": "syscall", - "syscall.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY": "syscall", - "syscall.CERT_TRUST_REVOCATION_STATUS_UNKNOWN": "syscall", - "syscall.CFLUSH": "syscall", - "syscall.CLOCAL": "syscall", - "syscall.CLONE_CHILD_CLEARTID": "syscall", - "syscall.CLONE_CHILD_SETTID": "syscall", - "syscall.CLONE_CSIGNAL": "syscall", - "syscall.CLONE_DETACHED": "syscall", - "syscall.CLONE_FILES": "syscall", - "syscall.CLONE_FS": "syscall", - "syscall.CLONE_IO": "syscall", - "syscall.CLONE_NEWIPC": "syscall", - "syscall.CLONE_NEWNET": "syscall", - "syscall.CLONE_NEWNS": "syscall", - "syscall.CLONE_NEWPID": "syscall", - "syscall.CLONE_NEWUSER": "syscall", - "syscall.CLONE_NEWUTS": "syscall", - "syscall.CLONE_PARENT": "syscall", - "syscall.CLONE_PARENT_SETTID": "syscall", - "syscall.CLONE_PID": "syscall", - "syscall.CLONE_PTRACE": "syscall", - "syscall.CLONE_SETTLS": "syscall", - "syscall.CLONE_SIGHAND": "syscall", - "syscall.CLONE_SYSVSEM": "syscall", - "syscall.CLONE_THREAD": "syscall", - "syscall.CLONE_UNTRACED": "syscall", - "syscall.CLONE_VFORK": "syscall", - "syscall.CLONE_VM": "syscall", - "syscall.CPUID_CFLUSH": "syscall", - "syscall.CREAD": "syscall", - "syscall.CREATE_ALWAYS": "syscall", - "syscall.CREATE_NEW": "syscall", - "syscall.CREATE_NEW_PROCESS_GROUP": "syscall", - "syscall.CREATE_UNICODE_ENVIRONMENT": "syscall", - "syscall.CRYPT_DEFAULT_CONTAINER_OPTIONAL": "syscall", - "syscall.CRYPT_DELETEKEYSET": "syscall", - "syscall.CRYPT_MACHINE_KEYSET": "syscall", - "syscall.CRYPT_NEWKEYSET": "syscall", - "syscall.CRYPT_SILENT": "syscall", - "syscall.CRYPT_VERIFYCONTEXT": "syscall", - "syscall.CS5": "syscall", - "syscall.CS6": "syscall", - "syscall.CS7": "syscall", - "syscall.CS8": "syscall", - "syscall.CSIZE": "syscall", - "syscall.CSTART": "syscall", - "syscall.CSTATUS": "syscall", - "syscall.CSTOP": "syscall", - "syscall.CSTOPB": "syscall", - "syscall.CSUSP": "syscall", - "syscall.CTL_MAXNAME": "syscall", - "syscall.CTL_NET": "syscall", - "syscall.CTL_QUERY": "syscall", - "syscall.CTRL_BREAK_EVENT": "syscall", - "syscall.CTRL_C_EVENT": "syscall", - "syscall.CancelIo": "syscall", - "syscall.CancelIoEx": "syscall", - "syscall.CertAddCertificateContextToStore": "syscall", - "syscall.CertChainContext": "syscall", - "syscall.CertChainElement": "syscall", - "syscall.CertChainPara": "syscall", - "syscall.CertChainPolicyPara": "syscall", - "syscall.CertChainPolicyStatus": "syscall", - "syscall.CertCloseStore": "syscall", - "syscall.CertContext": "syscall", - "syscall.CertCreateCertificateContext": "syscall", - "syscall.CertEnhKeyUsage": "syscall", - "syscall.CertEnumCertificatesInStore": "syscall", - "syscall.CertFreeCertificateChain": "syscall", - "syscall.CertFreeCertificateContext": "syscall", - "syscall.CertGetCertificateChain": "syscall", - "syscall.CertOpenStore": "syscall", - "syscall.CertOpenSystemStore": "syscall", - "syscall.CertRevocationInfo": "syscall", - "syscall.CertSimpleChain": "syscall", - "syscall.CertTrustStatus": "syscall", - "syscall.CertUsageMatch": "syscall", - "syscall.CertVerifyCertificateChainPolicy": "syscall", - "syscall.Chdir": "syscall", - "syscall.CheckBpfVersion": "syscall", - "syscall.Chflags": "syscall", - "syscall.Chmod": "syscall", - "syscall.Chown": "syscall", - "syscall.Chroot": "syscall", - "syscall.Clearenv": "syscall", - "syscall.Close": "syscall", - "syscall.CloseHandle": "syscall", - "syscall.CloseOnExec": "syscall", - "syscall.Closesocket": "syscall", - "syscall.CmsgLen": "syscall", - "syscall.CmsgSpace": "syscall", - "syscall.Cmsghdr": "syscall", - "syscall.CommandLineToArgv": "syscall", - "syscall.ComputerName": "syscall", - "syscall.Connect": "syscall", - "syscall.ConnectEx": "syscall", - "syscall.ConvertSidToStringSid": "syscall", - "syscall.ConvertStringSidToSid": "syscall", - "syscall.CopySid": "syscall", - "syscall.Creat": "syscall", - "syscall.CreateDirectory": "syscall", - "syscall.CreateFile": "syscall", - "syscall.CreateFileMapping": "syscall", - "syscall.CreateHardLink": "syscall", - "syscall.CreateIoCompletionPort": "syscall", - "syscall.CreatePipe": "syscall", - "syscall.CreateProcess": "syscall", - "syscall.CreateSymbolicLink": "syscall", - "syscall.CreateToolhelp32Snapshot": "syscall", - "syscall.Credential": "syscall", - "syscall.CryptAcquireContext": "syscall", - "syscall.CryptGenRandom": "syscall", - "syscall.CryptReleaseContext": "syscall", - "syscall.DIOCBSFLUSH": "syscall", - "syscall.DIOCOSFPFLUSH": "syscall", - "syscall.DLL": "syscall", - "syscall.DLLError": "syscall", - "syscall.DLT_A429": "syscall", - "syscall.DLT_A653_ICM": "syscall", - "syscall.DLT_AIRONET_HEADER": "syscall", - "syscall.DLT_AOS": "syscall", - "syscall.DLT_APPLE_IP_OVER_IEEE1394": "syscall", - "syscall.DLT_ARCNET": "syscall", - "syscall.DLT_ARCNET_LINUX": "syscall", - "syscall.DLT_ATM_CLIP": "syscall", - "syscall.DLT_ATM_RFC1483": "syscall", - "syscall.DLT_AURORA": "syscall", - "syscall.DLT_AX25": "syscall", - "syscall.DLT_AX25_KISS": "syscall", - "syscall.DLT_BACNET_MS_TP": "syscall", - "syscall.DLT_BLUETOOTH_HCI_H4": "syscall", - "syscall.DLT_BLUETOOTH_HCI_H4_WITH_PHDR": "syscall", - "syscall.DLT_CAN20B": "syscall", - "syscall.DLT_CAN_SOCKETCAN": "syscall", - "syscall.DLT_CHAOS": "syscall", - "syscall.DLT_CHDLC": "syscall", - "syscall.DLT_CISCO_IOS": "syscall", - "syscall.DLT_C_HDLC": "syscall", - "syscall.DLT_C_HDLC_WITH_DIR": "syscall", - "syscall.DLT_DBUS": "syscall", - "syscall.DLT_DECT": "syscall", - "syscall.DLT_DOCSIS": "syscall", - "syscall.DLT_DVB_CI": "syscall", - "syscall.DLT_ECONET": "syscall", - "syscall.DLT_EN10MB": "syscall", - "syscall.DLT_EN3MB": "syscall", - "syscall.DLT_ENC": "syscall", - "syscall.DLT_ERF": "syscall", - "syscall.DLT_ERF_ETH": "syscall", - "syscall.DLT_ERF_POS": "syscall", - "syscall.DLT_FC_2": "syscall", - "syscall.DLT_FC_2_WITH_FRAME_DELIMS": "syscall", - "syscall.DLT_FDDI": "syscall", - "syscall.DLT_FLEXRAY": "syscall", - "syscall.DLT_FRELAY": "syscall", - "syscall.DLT_FRELAY_WITH_DIR": "syscall", - "syscall.DLT_GCOM_SERIAL": "syscall", - "syscall.DLT_GCOM_T1E1": "syscall", - "syscall.DLT_GPF_F": "syscall", - "syscall.DLT_GPF_T": "syscall", - "syscall.DLT_GPRS_LLC": "syscall", - "syscall.DLT_GSMTAP_ABIS": "syscall", - "syscall.DLT_GSMTAP_UM": "syscall", - "syscall.DLT_HDLC": "syscall", - "syscall.DLT_HHDLC": "syscall", - "syscall.DLT_HIPPI": "syscall", - "syscall.DLT_IBM_SN": "syscall", - "syscall.DLT_IBM_SP": "syscall", - "syscall.DLT_IEEE802": "syscall", - "syscall.DLT_IEEE802_11": "syscall", - "syscall.DLT_IEEE802_11_RADIO": "syscall", - "syscall.DLT_IEEE802_11_RADIO_AVS": "syscall", - "syscall.DLT_IEEE802_15_4": "syscall", - "syscall.DLT_IEEE802_15_4_LINUX": "syscall", - "syscall.DLT_IEEE802_15_4_NOFCS": "syscall", - "syscall.DLT_IEEE802_15_4_NONASK_PHY": "syscall", - "syscall.DLT_IEEE802_16_MAC_CPS": "syscall", - "syscall.DLT_IEEE802_16_MAC_CPS_RADIO": "syscall", - "syscall.DLT_IPFILTER": "syscall", - "syscall.DLT_IPMB": "syscall", - "syscall.DLT_IPMB_LINUX": "syscall", - "syscall.DLT_IPNET": "syscall", - "syscall.DLT_IPOIB": "syscall", - "syscall.DLT_IPV4": "syscall", - "syscall.DLT_IPV6": "syscall", - "syscall.DLT_IP_OVER_FC": "syscall", - "syscall.DLT_JUNIPER_ATM1": "syscall", - "syscall.DLT_JUNIPER_ATM2": "syscall", - "syscall.DLT_JUNIPER_ATM_CEMIC": "syscall", - "syscall.DLT_JUNIPER_CHDLC": "syscall", - "syscall.DLT_JUNIPER_ES": "syscall", - "syscall.DLT_JUNIPER_ETHER": "syscall", - "syscall.DLT_JUNIPER_FIBRECHANNEL": "syscall", - "syscall.DLT_JUNIPER_FRELAY": "syscall", - "syscall.DLT_JUNIPER_GGSN": "syscall", - "syscall.DLT_JUNIPER_ISM": "syscall", - "syscall.DLT_JUNIPER_MFR": "syscall", - "syscall.DLT_JUNIPER_MLFR": "syscall", - "syscall.DLT_JUNIPER_MLPPP": "syscall", - "syscall.DLT_JUNIPER_MONITOR": "syscall", - "syscall.DLT_JUNIPER_PIC_PEER": "syscall", - "syscall.DLT_JUNIPER_PPP": "syscall", - "syscall.DLT_JUNIPER_PPPOE": "syscall", - "syscall.DLT_JUNIPER_PPPOE_ATM": "syscall", - "syscall.DLT_JUNIPER_SERVICES": "syscall", - "syscall.DLT_JUNIPER_SRX_E2E": "syscall", - "syscall.DLT_JUNIPER_ST": "syscall", - "syscall.DLT_JUNIPER_VP": "syscall", - "syscall.DLT_JUNIPER_VS": "syscall", - "syscall.DLT_LAPB_WITH_DIR": "syscall", - "syscall.DLT_LAPD": "syscall", - "syscall.DLT_LIN": "syscall", - "syscall.DLT_LINUX_EVDEV": "syscall", - "syscall.DLT_LINUX_IRDA": "syscall", - "syscall.DLT_LINUX_LAPD": "syscall", - "syscall.DLT_LINUX_PPP_WITHDIRECTION": "syscall", - "syscall.DLT_LINUX_SLL": "syscall", - "syscall.DLT_LOOP": "syscall", - "syscall.DLT_LTALK": "syscall", - "syscall.DLT_MATCHING_MAX": "syscall", - "syscall.DLT_MATCHING_MIN": "syscall", - "syscall.DLT_MFR": "syscall", - "syscall.DLT_MOST": "syscall", - "syscall.DLT_MPEG_2_TS": "syscall", - "syscall.DLT_MPLS": "syscall", - "syscall.DLT_MTP2": "syscall", - "syscall.DLT_MTP2_WITH_PHDR": "syscall", - "syscall.DLT_MTP3": "syscall", - "syscall.DLT_MUX27010": "syscall", - "syscall.DLT_NETANALYZER": "syscall", - "syscall.DLT_NETANALYZER_TRANSPARENT": "syscall", - "syscall.DLT_NFC_LLCP": "syscall", - "syscall.DLT_NFLOG": "syscall", - "syscall.DLT_NG40": "syscall", - "syscall.DLT_NULL": "syscall", - "syscall.DLT_PCI_EXP": "syscall", - "syscall.DLT_PFLOG": "syscall", - "syscall.DLT_PFSYNC": "syscall", - "syscall.DLT_PPI": "syscall", - "syscall.DLT_PPP": "syscall", - "syscall.DLT_PPP_BSDOS": "syscall", - "syscall.DLT_PPP_ETHER": "syscall", - "syscall.DLT_PPP_PPPD": "syscall", - "syscall.DLT_PPP_SERIAL": "syscall", - "syscall.DLT_PPP_WITH_DIR": "syscall", - "syscall.DLT_PPP_WITH_DIRECTION": "syscall", - "syscall.DLT_PRISM_HEADER": "syscall", - "syscall.DLT_PRONET": "syscall", - "syscall.DLT_RAIF1": "syscall", - "syscall.DLT_RAW": "syscall", - "syscall.DLT_RAWAF_MASK": "syscall", - "syscall.DLT_RIO": "syscall", - "syscall.DLT_SCCP": "syscall", - "syscall.DLT_SITA": "syscall", - "syscall.DLT_SLIP": "syscall", - "syscall.DLT_SLIP_BSDOS": "syscall", - "syscall.DLT_STANAG_5066_D_PDU": "syscall", - "syscall.DLT_SUNATM": "syscall", - "syscall.DLT_SYMANTEC_FIREWALL": "syscall", - "syscall.DLT_TZSP": "syscall", - "syscall.DLT_USB": "syscall", - "syscall.DLT_USB_LINUX": "syscall", - "syscall.DLT_USB_LINUX_MMAPPED": "syscall", - "syscall.DLT_USER0": "syscall", - "syscall.DLT_USER1": "syscall", - "syscall.DLT_USER10": "syscall", - "syscall.DLT_USER11": "syscall", - "syscall.DLT_USER12": "syscall", - "syscall.DLT_USER13": "syscall", - "syscall.DLT_USER14": "syscall", - "syscall.DLT_USER15": "syscall", - "syscall.DLT_USER2": "syscall", - "syscall.DLT_USER3": "syscall", - "syscall.DLT_USER4": "syscall", - "syscall.DLT_USER5": "syscall", - "syscall.DLT_USER6": "syscall", - "syscall.DLT_USER7": "syscall", - "syscall.DLT_USER8": "syscall", - "syscall.DLT_USER9": "syscall", - "syscall.DLT_WIHART": "syscall", - "syscall.DLT_X2E_SERIAL": "syscall", - "syscall.DLT_X2E_XORAYA": "syscall", - "syscall.DNSMXData": "syscall", - "syscall.DNSPTRData": "syscall", - "syscall.DNSRecord": "syscall", - "syscall.DNSSRVData": "syscall", - "syscall.DNSTXTData": "syscall", - "syscall.DNS_INFO_NO_RECORDS": "syscall", - "syscall.DNS_TYPE_A": "syscall", - "syscall.DNS_TYPE_A6": "syscall", - "syscall.DNS_TYPE_AAAA": "syscall", - "syscall.DNS_TYPE_ADDRS": "syscall", - "syscall.DNS_TYPE_AFSDB": "syscall", - "syscall.DNS_TYPE_ALL": "syscall", - "syscall.DNS_TYPE_ANY": "syscall", - "syscall.DNS_TYPE_ATMA": "syscall", - "syscall.DNS_TYPE_AXFR": "syscall", - "syscall.DNS_TYPE_CERT": "syscall", - "syscall.DNS_TYPE_CNAME": "syscall", - "syscall.DNS_TYPE_DHCID": "syscall", - "syscall.DNS_TYPE_DNAME": "syscall", - "syscall.DNS_TYPE_DNSKEY": "syscall", - "syscall.DNS_TYPE_DS": "syscall", - "syscall.DNS_TYPE_EID": "syscall", - "syscall.DNS_TYPE_GID": "syscall", - "syscall.DNS_TYPE_GPOS": "syscall", - "syscall.DNS_TYPE_HINFO": "syscall", - "syscall.DNS_TYPE_ISDN": "syscall", - "syscall.DNS_TYPE_IXFR": "syscall", - "syscall.DNS_TYPE_KEY": "syscall", - "syscall.DNS_TYPE_KX": "syscall", - "syscall.DNS_TYPE_LOC": "syscall", - "syscall.DNS_TYPE_MAILA": "syscall", - "syscall.DNS_TYPE_MAILB": "syscall", - "syscall.DNS_TYPE_MB": "syscall", - "syscall.DNS_TYPE_MD": "syscall", - "syscall.DNS_TYPE_MF": "syscall", - "syscall.DNS_TYPE_MG": "syscall", - "syscall.DNS_TYPE_MINFO": "syscall", - "syscall.DNS_TYPE_MR": "syscall", - "syscall.DNS_TYPE_MX": "syscall", - "syscall.DNS_TYPE_NAPTR": "syscall", - "syscall.DNS_TYPE_NBSTAT": "syscall", - "syscall.DNS_TYPE_NIMLOC": "syscall", - "syscall.DNS_TYPE_NS": "syscall", - "syscall.DNS_TYPE_NSAP": "syscall", - "syscall.DNS_TYPE_NSAPPTR": "syscall", - "syscall.DNS_TYPE_NSEC": "syscall", - "syscall.DNS_TYPE_NULL": "syscall", - "syscall.DNS_TYPE_NXT": "syscall", - "syscall.DNS_TYPE_OPT": "syscall", - "syscall.DNS_TYPE_PTR": "syscall", - "syscall.DNS_TYPE_PX": "syscall", - "syscall.DNS_TYPE_RP": "syscall", - "syscall.DNS_TYPE_RRSIG": "syscall", - "syscall.DNS_TYPE_RT": "syscall", - "syscall.DNS_TYPE_SIG": "syscall", - "syscall.DNS_TYPE_SINK": "syscall", - "syscall.DNS_TYPE_SOA": "syscall", - "syscall.DNS_TYPE_SRV": "syscall", - "syscall.DNS_TYPE_TEXT": "syscall", - "syscall.DNS_TYPE_TKEY": "syscall", - "syscall.DNS_TYPE_TSIG": "syscall", - "syscall.DNS_TYPE_UID": "syscall", - "syscall.DNS_TYPE_UINFO": "syscall", - "syscall.DNS_TYPE_UNSPEC": "syscall", - "syscall.DNS_TYPE_WINS": "syscall", - "syscall.DNS_TYPE_WINSR": "syscall", - "syscall.DNS_TYPE_WKS": "syscall", - "syscall.DNS_TYPE_X25": "syscall", - "syscall.DT_BLK": "syscall", - "syscall.DT_CHR": "syscall", - "syscall.DT_DIR": "syscall", - "syscall.DT_FIFO": "syscall", - "syscall.DT_LNK": "syscall", - "syscall.DT_REG": "syscall", - "syscall.DT_SOCK": "syscall", - "syscall.DT_UNKNOWN": "syscall", - "syscall.DT_WHT": "syscall", - "syscall.DUPLICATE_CLOSE_SOURCE": "syscall", - "syscall.DUPLICATE_SAME_ACCESS": "syscall", - "syscall.DeleteFile": "syscall", - "syscall.DetachLsf": "syscall", - "syscall.DeviceIoControl": "syscall", - "syscall.Dirent": "syscall", - "syscall.DnsNameCompare": "syscall", - "syscall.DnsQuery": "syscall", - "syscall.DnsRecordListFree": "syscall", - "syscall.DnsSectionAdditional": "syscall", - "syscall.DnsSectionAnswer": "syscall", - "syscall.DnsSectionAuthority": "syscall", - "syscall.DnsSectionQuestion": "syscall", - "syscall.Dup": "syscall", - "syscall.Dup2": "syscall", - "syscall.Dup3": "syscall", - "syscall.DuplicateHandle": "syscall", - "syscall.E2BIG": "syscall", - "syscall.EACCES": "syscall", - "syscall.EADDRINUSE": "syscall", - "syscall.EADDRNOTAVAIL": "syscall", - "syscall.EADV": "syscall", - "syscall.EAFNOSUPPORT": "syscall", - "syscall.EAGAIN": "syscall", - "syscall.EALREADY": "syscall", - "syscall.EAUTH": "syscall", - "syscall.EBADARCH": "syscall", - "syscall.EBADE": "syscall", - "syscall.EBADEXEC": "syscall", - "syscall.EBADF": "syscall", - "syscall.EBADFD": "syscall", - "syscall.EBADMACHO": "syscall", - "syscall.EBADMSG": "syscall", - "syscall.EBADR": "syscall", - "syscall.EBADRPC": "syscall", - "syscall.EBADRQC": "syscall", - "syscall.EBADSLT": "syscall", - "syscall.EBFONT": "syscall", - "syscall.EBUSY": "syscall", - "syscall.ECANCELED": "syscall", - "syscall.ECAPMODE": "syscall", - "syscall.ECHILD": "syscall", - "syscall.ECHO": "syscall", - "syscall.ECHOCTL": "syscall", - "syscall.ECHOE": "syscall", - "syscall.ECHOK": "syscall", - "syscall.ECHOKE": "syscall", - "syscall.ECHONL": "syscall", - "syscall.ECHOPRT": "syscall", - "syscall.ECHRNG": "syscall", - "syscall.ECOMM": "syscall", - "syscall.ECONNABORTED": "syscall", - "syscall.ECONNREFUSED": "syscall", - "syscall.ECONNRESET": "syscall", - "syscall.EDEADLK": "syscall", - "syscall.EDEADLOCK": "syscall", - "syscall.EDESTADDRREQ": "syscall", - "syscall.EDEVERR": "syscall", - "syscall.EDOM": "syscall", - "syscall.EDOOFUS": "syscall", - "syscall.EDOTDOT": "syscall", - "syscall.EDQUOT": "syscall", - "syscall.EEXIST": "syscall", - "syscall.EFAULT": "syscall", - "syscall.EFBIG": "syscall", - "syscall.EFER_LMA": "syscall", - "syscall.EFER_LME": "syscall", - "syscall.EFER_NXE": "syscall", - "syscall.EFER_SCE": "syscall", - "syscall.EFTYPE": "syscall", - "syscall.EHOSTDOWN": "syscall", - "syscall.EHOSTUNREACH": "syscall", - "syscall.EHWPOISON": "syscall", - "syscall.EIDRM": "syscall", - "syscall.EILSEQ": "syscall", - "syscall.EINPROGRESS": "syscall", - "syscall.EINTR": "syscall", - "syscall.EINVAL": "syscall", - "syscall.EIO": "syscall", - "syscall.EIPSEC": "syscall", - "syscall.EISCONN": "syscall", - "syscall.EISDIR": "syscall", - "syscall.EISNAM": "syscall", - "syscall.EKEYEXPIRED": "syscall", - "syscall.EKEYREJECTED": "syscall", - "syscall.EKEYREVOKED": "syscall", - "syscall.EL2HLT": "syscall", - "syscall.EL2NSYNC": "syscall", - "syscall.EL3HLT": "syscall", - "syscall.EL3RST": "syscall", - "syscall.ELAST": "syscall", - "syscall.ELF_NGREG": "syscall", - "syscall.ELF_PRARGSZ": "syscall", - "syscall.ELIBACC": "syscall", - "syscall.ELIBBAD": "syscall", - "syscall.ELIBEXEC": "syscall", - "syscall.ELIBMAX": "syscall", - "syscall.ELIBSCN": "syscall", - "syscall.ELNRNG": "syscall", - "syscall.ELOOP": "syscall", - "syscall.EMEDIUMTYPE": "syscall", - "syscall.EMFILE": "syscall", - "syscall.EMLINK": "syscall", - "syscall.EMSGSIZE": "syscall", - "syscall.EMT_TAGOVF": "syscall", - "syscall.EMULTIHOP": "syscall", - "syscall.EMUL_ENABLED": "syscall", - "syscall.EMUL_LINUX": "syscall", - "syscall.EMUL_LINUX32": "syscall", - "syscall.EMUL_MAXID": "syscall", - "syscall.EMUL_NATIVE": "syscall", - "syscall.ENAMETOOLONG": "syscall", - "syscall.ENAVAIL": "syscall", - "syscall.ENDRUNDISC": "syscall", - "syscall.ENEEDAUTH": "syscall", - "syscall.ENETDOWN": "syscall", - "syscall.ENETRESET": "syscall", - "syscall.ENETUNREACH": "syscall", - "syscall.ENFILE": "syscall", - "syscall.ENOANO": "syscall", - "syscall.ENOATTR": "syscall", - "syscall.ENOBUFS": "syscall", - "syscall.ENOCSI": "syscall", - "syscall.ENODATA": "syscall", - "syscall.ENODEV": "syscall", - "syscall.ENOENT": "syscall", - "syscall.ENOEXEC": "syscall", - "syscall.ENOKEY": "syscall", - "syscall.ENOLCK": "syscall", - "syscall.ENOLINK": "syscall", - "syscall.ENOMEDIUM": "syscall", - "syscall.ENOMEM": "syscall", - "syscall.ENOMSG": "syscall", - "syscall.ENONET": "syscall", - "syscall.ENOPKG": "syscall", - "syscall.ENOPOLICY": "syscall", - "syscall.ENOPROTOOPT": "syscall", - "syscall.ENOSPC": "syscall", - "syscall.ENOSR": "syscall", - "syscall.ENOSTR": "syscall", - "syscall.ENOSYS": "syscall", - "syscall.ENOTBLK": "syscall", - "syscall.ENOTCAPABLE": "syscall", - "syscall.ENOTCONN": "syscall", - "syscall.ENOTDIR": "syscall", - "syscall.ENOTEMPTY": "syscall", - "syscall.ENOTNAM": "syscall", - "syscall.ENOTRECOVERABLE": "syscall", - "syscall.ENOTSOCK": "syscall", - "syscall.ENOTSUP": "syscall", - "syscall.ENOTTY": "syscall", - "syscall.ENOTUNIQ": "syscall", - "syscall.ENXIO": "syscall", - "syscall.EN_SW_CTL_INF": "syscall", - "syscall.EN_SW_CTL_PREC": "syscall", - "syscall.EN_SW_CTL_ROUND": "syscall", - "syscall.EN_SW_DATACHAIN": "syscall", - "syscall.EN_SW_DENORM": "syscall", - "syscall.EN_SW_INVOP": "syscall", - "syscall.EN_SW_OVERFLOW": "syscall", - "syscall.EN_SW_PRECLOSS": "syscall", - "syscall.EN_SW_UNDERFLOW": "syscall", - "syscall.EN_SW_ZERODIV": "syscall", - "syscall.EOPNOTSUPP": "syscall", - "syscall.EOVERFLOW": "syscall", - "syscall.EOWNERDEAD": "syscall", - "syscall.EPERM": "syscall", - "syscall.EPFNOSUPPORT": "syscall", - "syscall.EPIPE": "syscall", - "syscall.EPOLLERR": "syscall", - "syscall.EPOLLET": "syscall", - "syscall.EPOLLHUP": "syscall", - "syscall.EPOLLIN": "syscall", - "syscall.EPOLLMSG": "syscall", - "syscall.EPOLLONESHOT": "syscall", - "syscall.EPOLLOUT": "syscall", - "syscall.EPOLLPRI": "syscall", - "syscall.EPOLLRDBAND": "syscall", - "syscall.EPOLLRDHUP": "syscall", - "syscall.EPOLLRDNORM": "syscall", - "syscall.EPOLLWRBAND": "syscall", - "syscall.EPOLLWRNORM": "syscall", - "syscall.EPOLL_CLOEXEC": "syscall", - "syscall.EPOLL_CTL_ADD": "syscall", - "syscall.EPOLL_CTL_DEL": "syscall", - "syscall.EPOLL_CTL_MOD": "syscall", - "syscall.EPOLL_NONBLOCK": "syscall", - "syscall.EPROCLIM": "syscall", - "syscall.EPROCUNAVAIL": "syscall", - "syscall.EPROGMISMATCH": "syscall", - "syscall.EPROGUNAVAIL": "syscall", - "syscall.EPROTO": "syscall", - "syscall.EPROTONOSUPPORT": "syscall", - "syscall.EPROTOTYPE": "syscall", - "syscall.EPWROFF": "syscall", - "syscall.ERANGE": "syscall", - "syscall.EREMCHG": "syscall", - "syscall.EREMOTE": "syscall", - "syscall.EREMOTEIO": "syscall", - "syscall.ERESTART": "syscall", - "syscall.ERFKILL": "syscall", - "syscall.EROFS": "syscall", - "syscall.ERPCMISMATCH": "syscall", - "syscall.ERROR_ACCESS_DENIED": "syscall", - "syscall.ERROR_ALREADY_EXISTS": "syscall", - "syscall.ERROR_BROKEN_PIPE": "syscall", - "syscall.ERROR_BUFFER_OVERFLOW": "syscall", - "syscall.ERROR_ENVVAR_NOT_FOUND": "syscall", - "syscall.ERROR_FILE_EXISTS": "syscall", - "syscall.ERROR_FILE_NOT_FOUND": "syscall", - "syscall.ERROR_HANDLE_EOF": "syscall", - "syscall.ERROR_INSUFFICIENT_BUFFER": "syscall", - "syscall.ERROR_IO_PENDING": "syscall", - "syscall.ERROR_MOD_NOT_FOUND": "syscall", - "syscall.ERROR_MORE_DATA": "syscall", - "syscall.ERROR_NETNAME_DELETED": "syscall", - "syscall.ERROR_NOT_FOUND": "syscall", - "syscall.ERROR_NO_MORE_FILES": "syscall", - "syscall.ERROR_OPERATION_ABORTED": "syscall", - "syscall.ERROR_PATH_NOT_FOUND": "syscall", - "syscall.ERROR_PRIVILEGE_NOT_HELD": "syscall", - "syscall.ERROR_PROC_NOT_FOUND": "syscall", - "syscall.ESHLIBVERS": "syscall", - "syscall.ESHUTDOWN": "syscall", - "syscall.ESOCKTNOSUPPORT": "syscall", - "syscall.ESPIPE": "syscall", - "syscall.ESRCH": "syscall", - "syscall.ESRMNT": "syscall", - "syscall.ESTALE": "syscall", - "syscall.ESTRPIPE": "syscall", - "syscall.ETHERCAP_JUMBO_MTU": "syscall", - "syscall.ETHERCAP_VLAN_HWTAGGING": "syscall", - "syscall.ETHERCAP_VLAN_MTU": "syscall", - "syscall.ETHERMIN": "syscall", - "syscall.ETHERMTU": "syscall", - "syscall.ETHERMTU_JUMBO": "syscall", - "syscall.ETHERTYPE_8023": "syscall", - "syscall.ETHERTYPE_AARP": "syscall", - "syscall.ETHERTYPE_ACCTON": "syscall", - "syscall.ETHERTYPE_AEONIC": "syscall", - "syscall.ETHERTYPE_ALPHA": "syscall", - "syscall.ETHERTYPE_AMBER": "syscall", - "syscall.ETHERTYPE_AMOEBA": "syscall", - "syscall.ETHERTYPE_AOE": "syscall", - "syscall.ETHERTYPE_APOLLO": "syscall", - "syscall.ETHERTYPE_APOLLODOMAIN": "syscall", - "syscall.ETHERTYPE_APPLETALK": "syscall", - "syscall.ETHERTYPE_APPLITEK": "syscall", - "syscall.ETHERTYPE_ARGONAUT": "syscall", - "syscall.ETHERTYPE_ARP": "syscall", - "syscall.ETHERTYPE_AT": "syscall", - "syscall.ETHERTYPE_ATALK": "syscall", - "syscall.ETHERTYPE_ATOMIC": "syscall", - "syscall.ETHERTYPE_ATT": "syscall", - "syscall.ETHERTYPE_ATTSTANFORD": "syscall", - "syscall.ETHERTYPE_AUTOPHON": "syscall", - "syscall.ETHERTYPE_AXIS": "syscall", - "syscall.ETHERTYPE_BCLOOP": "syscall", - "syscall.ETHERTYPE_BOFL": "syscall", - "syscall.ETHERTYPE_CABLETRON": "syscall", - "syscall.ETHERTYPE_CHAOS": "syscall", - "syscall.ETHERTYPE_COMDESIGN": "syscall", - "syscall.ETHERTYPE_COMPUGRAPHIC": "syscall", - "syscall.ETHERTYPE_COUNTERPOINT": "syscall", - "syscall.ETHERTYPE_CRONUS": "syscall", - "syscall.ETHERTYPE_CRONUSVLN": "syscall", - "syscall.ETHERTYPE_DCA": "syscall", - "syscall.ETHERTYPE_DDE": "syscall", - "syscall.ETHERTYPE_DEBNI": "syscall", - "syscall.ETHERTYPE_DECAM": "syscall", - "syscall.ETHERTYPE_DECCUST": "syscall", - "syscall.ETHERTYPE_DECDIAG": "syscall", - "syscall.ETHERTYPE_DECDNS": "syscall", - "syscall.ETHERTYPE_DECDTS": "syscall", - "syscall.ETHERTYPE_DECEXPER": "syscall", - "syscall.ETHERTYPE_DECLAST": "syscall", - "syscall.ETHERTYPE_DECLTM": "syscall", - "syscall.ETHERTYPE_DECMUMPS": "syscall", - "syscall.ETHERTYPE_DECNETBIOS": "syscall", - "syscall.ETHERTYPE_DELTACON": "syscall", - "syscall.ETHERTYPE_DIDDLE": "syscall", - "syscall.ETHERTYPE_DLOG1": "syscall", - "syscall.ETHERTYPE_DLOG2": "syscall", - "syscall.ETHERTYPE_DN": "syscall", - "syscall.ETHERTYPE_DOGFIGHT": "syscall", - "syscall.ETHERTYPE_DSMD": "syscall", - "syscall.ETHERTYPE_ECMA": "syscall", - "syscall.ETHERTYPE_ENCRYPT": "syscall", - "syscall.ETHERTYPE_ES": "syscall", - "syscall.ETHERTYPE_EXCELAN": "syscall", - "syscall.ETHERTYPE_EXPERDATA": "syscall", - "syscall.ETHERTYPE_FLIP": "syscall", - "syscall.ETHERTYPE_FLOWCONTROL": "syscall", - "syscall.ETHERTYPE_FRARP": "syscall", - "syscall.ETHERTYPE_GENDYN": "syscall", - "syscall.ETHERTYPE_HAYES": "syscall", - "syscall.ETHERTYPE_HIPPI_FP": "syscall", - "syscall.ETHERTYPE_HITACHI": "syscall", - "syscall.ETHERTYPE_HP": "syscall", - "syscall.ETHERTYPE_IEEEPUP": "syscall", - "syscall.ETHERTYPE_IEEEPUPAT": "syscall", - "syscall.ETHERTYPE_IMLBL": "syscall", - "syscall.ETHERTYPE_IMLBLDIAG": "syscall", - "syscall.ETHERTYPE_IP": "syscall", - "syscall.ETHERTYPE_IPAS": "syscall", - "syscall.ETHERTYPE_IPV6": "syscall", - "syscall.ETHERTYPE_IPX": "syscall", - "syscall.ETHERTYPE_IPXNEW": "syscall", - "syscall.ETHERTYPE_KALPANA": "syscall", - "syscall.ETHERTYPE_LANBRIDGE": "syscall", - "syscall.ETHERTYPE_LANPROBE": "syscall", - "syscall.ETHERTYPE_LAT": "syscall", - "syscall.ETHERTYPE_LBACK": "syscall", - "syscall.ETHERTYPE_LITTLE": "syscall", - "syscall.ETHERTYPE_LLDP": "syscall", - "syscall.ETHERTYPE_LOGICRAFT": "syscall", - "syscall.ETHERTYPE_LOOPBACK": "syscall", - "syscall.ETHERTYPE_MATRA": "syscall", - "syscall.ETHERTYPE_MAX": "syscall", - "syscall.ETHERTYPE_MERIT": "syscall", - "syscall.ETHERTYPE_MICP": "syscall", - "syscall.ETHERTYPE_MOPDL": "syscall", - "syscall.ETHERTYPE_MOPRC": "syscall", - "syscall.ETHERTYPE_MOTOROLA": "syscall", - "syscall.ETHERTYPE_MPLS": "syscall", - "syscall.ETHERTYPE_MPLS_MCAST": "syscall", - "syscall.ETHERTYPE_MUMPS": "syscall", - "syscall.ETHERTYPE_NBPCC": "syscall", - "syscall.ETHERTYPE_NBPCLAIM": "syscall", - "syscall.ETHERTYPE_NBPCLREQ": "syscall", - "syscall.ETHERTYPE_NBPCLRSP": "syscall", - "syscall.ETHERTYPE_NBPCREQ": "syscall", - "syscall.ETHERTYPE_NBPCRSP": "syscall", - "syscall.ETHERTYPE_NBPDG": "syscall", - "syscall.ETHERTYPE_NBPDGB": "syscall", - "syscall.ETHERTYPE_NBPDLTE": "syscall", - "syscall.ETHERTYPE_NBPRAR": "syscall", - "syscall.ETHERTYPE_NBPRAS": "syscall", - "syscall.ETHERTYPE_NBPRST": "syscall", - "syscall.ETHERTYPE_NBPSCD": "syscall", - "syscall.ETHERTYPE_NBPVCD": "syscall", - "syscall.ETHERTYPE_NBS": "syscall", - "syscall.ETHERTYPE_NCD": "syscall", - "syscall.ETHERTYPE_NESTAR": "syscall", - "syscall.ETHERTYPE_NETBEUI": "syscall", - "syscall.ETHERTYPE_NOVELL": "syscall", - "syscall.ETHERTYPE_NS": "syscall", - "syscall.ETHERTYPE_NSAT": "syscall", - "syscall.ETHERTYPE_NSCOMPAT": "syscall", - "syscall.ETHERTYPE_NTRAILER": "syscall", - "syscall.ETHERTYPE_OS9": "syscall", - "syscall.ETHERTYPE_OS9NET": "syscall", - "syscall.ETHERTYPE_PACER": "syscall", - "syscall.ETHERTYPE_PAE": "syscall", - "syscall.ETHERTYPE_PCS": "syscall", - "syscall.ETHERTYPE_PLANNING": "syscall", - "syscall.ETHERTYPE_PPP": "syscall", - "syscall.ETHERTYPE_PPPOE": "syscall", - "syscall.ETHERTYPE_PPPOEDISC": "syscall", - "syscall.ETHERTYPE_PRIMENTS": "syscall", - "syscall.ETHERTYPE_PUP": "syscall", - "syscall.ETHERTYPE_PUPAT": "syscall", - "syscall.ETHERTYPE_QINQ": "syscall", - "syscall.ETHERTYPE_RACAL": "syscall", - "syscall.ETHERTYPE_RATIONAL": "syscall", - "syscall.ETHERTYPE_RAWFR": "syscall", - "syscall.ETHERTYPE_RCL": "syscall", - "syscall.ETHERTYPE_RDP": "syscall", - "syscall.ETHERTYPE_RETIX": "syscall", - "syscall.ETHERTYPE_REVARP": "syscall", - "syscall.ETHERTYPE_SCA": "syscall", - "syscall.ETHERTYPE_SECTRA": "syscall", - "syscall.ETHERTYPE_SECUREDATA": "syscall", - "syscall.ETHERTYPE_SGITW": "syscall", - "syscall.ETHERTYPE_SG_BOUNCE": "syscall", - "syscall.ETHERTYPE_SG_DIAG": "syscall", - "syscall.ETHERTYPE_SG_NETGAMES": "syscall", - "syscall.ETHERTYPE_SG_RESV": "syscall", - "syscall.ETHERTYPE_SIMNET": "syscall", - "syscall.ETHERTYPE_SLOW": "syscall", - "syscall.ETHERTYPE_SLOWPROTOCOLS": "syscall", - "syscall.ETHERTYPE_SNA": "syscall", - "syscall.ETHERTYPE_SNMP": "syscall", - "syscall.ETHERTYPE_SONIX": "syscall", - "syscall.ETHERTYPE_SPIDER": "syscall", - "syscall.ETHERTYPE_SPRITE": "syscall", - "syscall.ETHERTYPE_STP": "syscall", - "syscall.ETHERTYPE_TALARIS": "syscall", - "syscall.ETHERTYPE_TALARISMC": "syscall", - "syscall.ETHERTYPE_TCPCOMP": "syscall", - "syscall.ETHERTYPE_TCPSM": "syscall", - "syscall.ETHERTYPE_TEC": "syscall", - "syscall.ETHERTYPE_TIGAN": "syscall", - "syscall.ETHERTYPE_TRAIL": "syscall", - "syscall.ETHERTYPE_TRANSETHER": "syscall", - "syscall.ETHERTYPE_TYMSHARE": "syscall", - "syscall.ETHERTYPE_UBBST": "syscall", - "syscall.ETHERTYPE_UBDEBUG": "syscall", - "syscall.ETHERTYPE_UBDIAGLOOP": "syscall", - "syscall.ETHERTYPE_UBDL": "syscall", - "syscall.ETHERTYPE_UBNIU": "syscall", - "syscall.ETHERTYPE_UBNMC": "syscall", - "syscall.ETHERTYPE_VALID": "syscall", - "syscall.ETHERTYPE_VARIAN": "syscall", - "syscall.ETHERTYPE_VAXELN": "syscall", - "syscall.ETHERTYPE_VEECO": "syscall", - "syscall.ETHERTYPE_VEXP": "syscall", - "syscall.ETHERTYPE_VGLAB": "syscall", - "syscall.ETHERTYPE_VINES": "syscall", - "syscall.ETHERTYPE_VINESECHO": "syscall", - "syscall.ETHERTYPE_VINESLOOP": "syscall", - "syscall.ETHERTYPE_VITAL": "syscall", - "syscall.ETHERTYPE_VLAN": "syscall", - "syscall.ETHERTYPE_VLTLMAN": "syscall", - "syscall.ETHERTYPE_VPROD": "syscall", - "syscall.ETHERTYPE_VURESERVED": "syscall", - "syscall.ETHERTYPE_WATERLOO": "syscall", - "syscall.ETHERTYPE_WELLFLEET": "syscall", - "syscall.ETHERTYPE_X25": "syscall", - "syscall.ETHERTYPE_X75": "syscall", - "syscall.ETHERTYPE_XNSSM": "syscall", - "syscall.ETHERTYPE_XTP": "syscall", - "syscall.ETHER_ADDR_LEN": "syscall", - "syscall.ETHER_ALIGN": "syscall", - "syscall.ETHER_CRC_LEN": "syscall", - "syscall.ETHER_CRC_POLY_BE": "syscall", - "syscall.ETHER_CRC_POLY_LE": "syscall", - "syscall.ETHER_HDR_LEN": "syscall", - "syscall.ETHER_MAX_DIX_LEN": "syscall", - "syscall.ETHER_MAX_LEN": "syscall", - "syscall.ETHER_MAX_LEN_JUMBO": "syscall", - "syscall.ETHER_MIN_LEN": "syscall", - "syscall.ETHER_PPPOE_ENCAP_LEN": "syscall", - "syscall.ETHER_TYPE_LEN": "syscall", - "syscall.ETHER_VLAN_ENCAP_LEN": "syscall", - "syscall.ETH_P_1588": "syscall", - "syscall.ETH_P_8021Q": "syscall", - "syscall.ETH_P_802_2": "syscall", - "syscall.ETH_P_802_3": "syscall", - "syscall.ETH_P_AARP": "syscall", - "syscall.ETH_P_ALL": "syscall", - "syscall.ETH_P_AOE": "syscall", - "syscall.ETH_P_ARCNET": "syscall", - "syscall.ETH_P_ARP": "syscall", - "syscall.ETH_P_ATALK": "syscall", - "syscall.ETH_P_ATMFATE": "syscall", - "syscall.ETH_P_ATMMPOA": "syscall", - "syscall.ETH_P_AX25": "syscall", - "syscall.ETH_P_BPQ": "syscall", - "syscall.ETH_P_CAIF": "syscall", - "syscall.ETH_P_CAN": "syscall", - "syscall.ETH_P_CONTROL": "syscall", - "syscall.ETH_P_CUST": "syscall", - "syscall.ETH_P_DDCMP": "syscall", - "syscall.ETH_P_DEC": "syscall", - "syscall.ETH_P_DIAG": "syscall", - "syscall.ETH_P_DNA_DL": "syscall", - "syscall.ETH_P_DNA_RC": "syscall", - "syscall.ETH_P_DNA_RT": "syscall", - "syscall.ETH_P_DSA": "syscall", - "syscall.ETH_P_ECONET": "syscall", - "syscall.ETH_P_EDSA": "syscall", - "syscall.ETH_P_FCOE": "syscall", - "syscall.ETH_P_FIP": "syscall", - "syscall.ETH_P_HDLC": "syscall", - "syscall.ETH_P_IEEE802154": "syscall", - "syscall.ETH_P_IEEEPUP": "syscall", - "syscall.ETH_P_IEEEPUPAT": "syscall", - "syscall.ETH_P_IP": "syscall", - "syscall.ETH_P_IPV6": "syscall", - "syscall.ETH_P_IPX": "syscall", - "syscall.ETH_P_IRDA": "syscall", - "syscall.ETH_P_LAT": "syscall", - "syscall.ETH_P_LINK_CTL": "syscall", - "syscall.ETH_P_LOCALTALK": "syscall", - "syscall.ETH_P_LOOP": "syscall", - "syscall.ETH_P_MOBITEX": "syscall", - "syscall.ETH_P_MPLS_MC": "syscall", - "syscall.ETH_P_MPLS_UC": "syscall", - "syscall.ETH_P_PAE": "syscall", - "syscall.ETH_P_PAUSE": "syscall", - "syscall.ETH_P_PHONET": "syscall", - "syscall.ETH_P_PPPTALK": "syscall", - "syscall.ETH_P_PPP_DISC": "syscall", - "syscall.ETH_P_PPP_MP": "syscall", - "syscall.ETH_P_PPP_SES": "syscall", - "syscall.ETH_P_PUP": "syscall", - "syscall.ETH_P_PUPAT": "syscall", - "syscall.ETH_P_RARP": "syscall", - "syscall.ETH_P_SCA": "syscall", - "syscall.ETH_P_SLOW": "syscall", - "syscall.ETH_P_SNAP": "syscall", - "syscall.ETH_P_TEB": "syscall", - "syscall.ETH_P_TIPC": "syscall", - "syscall.ETH_P_TRAILER": "syscall", - "syscall.ETH_P_TR_802_2": "syscall", - "syscall.ETH_P_WAN_PPP": "syscall", - "syscall.ETH_P_WCCP": "syscall", - "syscall.ETH_P_X25": "syscall", - "syscall.ETIME": "syscall", - "syscall.ETIMEDOUT": "syscall", - "syscall.ETOOMANYREFS": "syscall", - "syscall.ETXTBSY": "syscall", - "syscall.EUCLEAN": "syscall", - "syscall.EUNATCH": "syscall", - "syscall.EUSERS": "syscall", - "syscall.EVFILT_AIO": "syscall", - "syscall.EVFILT_FS": "syscall", - "syscall.EVFILT_LIO": "syscall", - "syscall.EVFILT_MACHPORT": "syscall", - "syscall.EVFILT_PROC": "syscall", - "syscall.EVFILT_READ": "syscall", - "syscall.EVFILT_SIGNAL": "syscall", - "syscall.EVFILT_SYSCOUNT": "syscall", - "syscall.EVFILT_THREADMARKER": "syscall", - "syscall.EVFILT_TIMER": "syscall", - "syscall.EVFILT_USER": "syscall", - "syscall.EVFILT_VM": "syscall", - "syscall.EVFILT_VNODE": "syscall", - "syscall.EVFILT_WRITE": "syscall", - "syscall.EV_ADD": "syscall", - "syscall.EV_CLEAR": "syscall", - "syscall.EV_DELETE": "syscall", - "syscall.EV_DISABLE": "syscall", - "syscall.EV_DISPATCH": "syscall", - "syscall.EV_DROP": "syscall", - "syscall.EV_ENABLE": "syscall", - "syscall.EV_EOF": "syscall", - "syscall.EV_ERROR": "syscall", - "syscall.EV_FLAG0": "syscall", - "syscall.EV_FLAG1": "syscall", - "syscall.EV_ONESHOT": "syscall", - "syscall.EV_OOBAND": "syscall", - "syscall.EV_POLL": "syscall", - "syscall.EV_RECEIPT": "syscall", - "syscall.EV_SYSFLAGS": "syscall", - "syscall.EWINDOWS": "syscall", - "syscall.EWOULDBLOCK": "syscall", - "syscall.EXDEV": "syscall", - "syscall.EXFULL": "syscall", - "syscall.EXTA": "syscall", - "syscall.EXTB": "syscall", - "syscall.EXTPROC": "syscall", - "syscall.Environ": "syscall", - "syscall.EpollCreate": "syscall", - "syscall.EpollCreate1": "syscall", - "syscall.EpollCtl": "syscall", - "syscall.EpollEvent": "syscall", - "syscall.EpollWait": "syscall", - "syscall.Errno": "syscall", - "syscall.EscapeArg": "syscall", - "syscall.Exchangedata": "syscall", - "syscall.Exec": "syscall", - "syscall.Exit": "syscall", - "syscall.ExitProcess": "syscall", - "syscall.FD_CLOEXEC": "syscall", - "syscall.FD_SETSIZE": "syscall", - "syscall.FILE_ACTION_ADDED": "syscall", - "syscall.FILE_ACTION_MODIFIED": "syscall", - "syscall.FILE_ACTION_REMOVED": "syscall", - "syscall.FILE_ACTION_RENAMED_NEW_NAME": "syscall", - "syscall.FILE_ACTION_RENAMED_OLD_NAME": "syscall", - "syscall.FILE_APPEND_DATA": "syscall", - "syscall.FILE_ATTRIBUTE_ARCHIVE": "syscall", - "syscall.FILE_ATTRIBUTE_DIRECTORY": "syscall", - "syscall.FILE_ATTRIBUTE_HIDDEN": "syscall", - "syscall.FILE_ATTRIBUTE_NORMAL": "syscall", - "syscall.FILE_ATTRIBUTE_READONLY": "syscall", - "syscall.FILE_ATTRIBUTE_REPARSE_POINT": "syscall", - "syscall.FILE_ATTRIBUTE_SYSTEM": "syscall", - "syscall.FILE_BEGIN": "syscall", - "syscall.FILE_CURRENT": "syscall", - "syscall.FILE_END": "syscall", - "syscall.FILE_FLAG_BACKUP_SEMANTICS": "syscall", - "syscall.FILE_FLAG_OPEN_REPARSE_POINT": "syscall", - "syscall.FILE_FLAG_OVERLAPPED": "syscall", - "syscall.FILE_LIST_DIRECTORY": "syscall", - "syscall.FILE_MAP_COPY": "syscall", - "syscall.FILE_MAP_EXECUTE": "syscall", - "syscall.FILE_MAP_READ": "syscall", - "syscall.FILE_MAP_WRITE": "syscall", - "syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES": "syscall", - "syscall.FILE_NOTIFY_CHANGE_CREATION": "syscall", - "syscall.FILE_NOTIFY_CHANGE_DIR_NAME": "syscall", - "syscall.FILE_NOTIFY_CHANGE_FILE_NAME": "syscall", - "syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS": "syscall", - "syscall.FILE_NOTIFY_CHANGE_LAST_WRITE": "syscall", - "syscall.FILE_NOTIFY_CHANGE_SIZE": "syscall", - "syscall.FILE_SHARE_DELETE": "syscall", - "syscall.FILE_SHARE_READ": "syscall", - "syscall.FILE_SHARE_WRITE": "syscall", - "syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS": "syscall", - "syscall.FILE_SKIP_SET_EVENT_ON_HANDLE": "syscall", - "syscall.FILE_TYPE_CHAR": "syscall", - "syscall.FILE_TYPE_DISK": "syscall", - "syscall.FILE_TYPE_PIPE": "syscall", - "syscall.FILE_TYPE_REMOTE": "syscall", - "syscall.FILE_TYPE_UNKNOWN": "syscall", - "syscall.FILE_WRITE_ATTRIBUTES": "syscall", - "syscall.FLUSHO": "syscall", - "syscall.FORMAT_MESSAGE_ALLOCATE_BUFFER": "syscall", - "syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY": "syscall", - "syscall.FORMAT_MESSAGE_FROM_HMODULE": "syscall", - "syscall.FORMAT_MESSAGE_FROM_STRING": "syscall", - "syscall.FORMAT_MESSAGE_FROM_SYSTEM": "syscall", - "syscall.FORMAT_MESSAGE_IGNORE_INSERTS": "syscall", - "syscall.FORMAT_MESSAGE_MAX_WIDTH_MASK": "syscall", - "syscall.FSCTL_GET_REPARSE_POINT": "syscall", - "syscall.F_ADDFILESIGS": "syscall", - "syscall.F_ADDSIGS": "syscall", - "syscall.F_ALLOCATEALL": "syscall", - "syscall.F_ALLOCATECONTIG": "syscall", - "syscall.F_CANCEL": "syscall", - "syscall.F_CHKCLEAN": "syscall", - "syscall.F_CLOSEM": "syscall", - "syscall.F_DUP2FD": "syscall", - "syscall.F_DUP2FD_CLOEXEC": "syscall", - "syscall.F_DUPFD": "syscall", - "syscall.F_DUPFD_CLOEXEC": "syscall", - "syscall.F_EXLCK": "syscall", - "syscall.F_FLUSH_DATA": "syscall", - "syscall.F_FREEZE_FS": "syscall", - "syscall.F_FSCTL": "syscall", - "syscall.F_FSDIRMASK": "syscall", - "syscall.F_FSIN": "syscall", - "syscall.F_FSINOUT": "syscall", - "syscall.F_FSOUT": "syscall", - "syscall.F_FSPRIV": "syscall", - "syscall.F_FSVOID": "syscall", - "syscall.F_FULLFSYNC": "syscall", - "syscall.F_GETFD": "syscall", - "syscall.F_GETFL": "syscall", - "syscall.F_GETLEASE": "syscall", - "syscall.F_GETLK": "syscall", - "syscall.F_GETLK64": "syscall", - "syscall.F_GETLKPID": "syscall", - "syscall.F_GETNOSIGPIPE": "syscall", - "syscall.F_GETOWN": "syscall", - "syscall.F_GETOWN_EX": "syscall", - "syscall.F_GETPATH": "syscall", - "syscall.F_GETPATH_MTMINFO": "syscall", - "syscall.F_GETPIPE_SZ": "syscall", - "syscall.F_GETPROTECTIONCLASS": "syscall", - "syscall.F_GETSIG": "syscall", - "syscall.F_GLOBAL_NOCACHE": "syscall", - "syscall.F_LOCK": "syscall", - "syscall.F_LOG2PHYS": "syscall", - "syscall.F_LOG2PHYS_EXT": "syscall", - "syscall.F_MARKDEPENDENCY": "syscall", - "syscall.F_MAXFD": "syscall", - "syscall.F_NOCACHE": "syscall", - "syscall.F_NODIRECT": "syscall", - "syscall.F_NOTIFY": "syscall", - "syscall.F_OGETLK": "syscall", - "syscall.F_OK": "syscall", - "syscall.F_OSETLK": "syscall", - "syscall.F_OSETLKW": "syscall", - "syscall.F_PARAM_MASK": "syscall", - "syscall.F_PARAM_MAX": "syscall", - "syscall.F_PATHPKG_CHECK": "syscall", - "syscall.F_PEOFPOSMODE": "syscall", - "syscall.F_PREALLOCATE": "syscall", - "syscall.F_RDADVISE": "syscall", - "syscall.F_RDAHEAD": "syscall", - "syscall.F_RDLCK": "syscall", - "syscall.F_READAHEAD": "syscall", - "syscall.F_READBOOTSTRAP": "syscall", - "syscall.F_SETBACKINGSTORE": "syscall", - "syscall.F_SETFD": "syscall", - "syscall.F_SETFL": "syscall", - "syscall.F_SETLEASE": "syscall", - "syscall.F_SETLK": "syscall", - "syscall.F_SETLK64": "syscall", - "syscall.F_SETLKW": "syscall", - "syscall.F_SETLKW64": "syscall", - "syscall.F_SETLK_REMOTE": "syscall", - "syscall.F_SETNOSIGPIPE": "syscall", - "syscall.F_SETOWN": "syscall", - "syscall.F_SETOWN_EX": "syscall", - "syscall.F_SETPIPE_SZ": "syscall", - "syscall.F_SETPROTECTIONCLASS": "syscall", - "syscall.F_SETSIG": "syscall", - "syscall.F_SETSIZE": "syscall", - "syscall.F_SHLCK": "syscall", - "syscall.F_TEST": "syscall", - "syscall.F_THAW_FS": "syscall", - "syscall.F_TLOCK": "syscall", - "syscall.F_ULOCK": "syscall", - "syscall.F_UNLCK": "syscall", - "syscall.F_UNLCKSYS": "syscall", - "syscall.F_VOLPOSMODE": "syscall", - "syscall.F_WRITEBOOTSTRAP": "syscall", - "syscall.F_WRLCK": "syscall", - "syscall.Faccessat": "syscall", - "syscall.Fallocate": "syscall", - "syscall.Fbootstraptransfer_t": "syscall", - "syscall.Fchdir": "syscall", - "syscall.Fchflags": "syscall", - "syscall.Fchmod": "syscall", - "syscall.Fchmodat": "syscall", - "syscall.Fchown": "syscall", - "syscall.Fchownat": "syscall", - "syscall.FcntlFlock": "syscall", - "syscall.FdSet": "syscall", - "syscall.Fdatasync": "syscall", - "syscall.FileNotifyInformation": "syscall", - "syscall.Filetime": "syscall", - "syscall.FindClose": "syscall", - "syscall.FindFirstFile": "syscall", - "syscall.FindNextFile": "syscall", - "syscall.Flock": "syscall", - "syscall.Flock_t": "syscall", - "syscall.FlushBpf": "syscall", - "syscall.FlushFileBuffers": "syscall", - "syscall.FlushViewOfFile": "syscall", - "syscall.ForkExec": "syscall", - "syscall.ForkLock": "syscall", - "syscall.FormatMessage": "syscall", - "syscall.Fpathconf": "syscall", - "syscall.FreeAddrInfoW": "syscall", - "syscall.FreeEnvironmentStrings": "syscall", - "syscall.FreeLibrary": "syscall", - "syscall.Fsid": "syscall", - "syscall.Fstat": "syscall", - "syscall.Fstatfs": "syscall", - "syscall.Fstore_t": "syscall", - "syscall.Fsync": "syscall", - "syscall.Ftruncate": "syscall", - "syscall.FullPath": "syscall", - "syscall.Futimes": "syscall", - "syscall.Futimesat": "syscall", - "syscall.GENERIC_ALL": "syscall", - "syscall.GENERIC_EXECUTE": "syscall", - "syscall.GENERIC_READ": "syscall", - "syscall.GENERIC_WRITE": "syscall", - "syscall.GUID": "syscall", - "syscall.GetAcceptExSockaddrs": "syscall", - "syscall.GetAdaptersInfo": "syscall", - "syscall.GetAddrInfoW": "syscall", - "syscall.GetCommandLine": "syscall", - "syscall.GetComputerName": "syscall", - "syscall.GetConsoleMode": "syscall", - "syscall.GetCurrentDirectory": "syscall", - "syscall.GetCurrentProcess": "syscall", - "syscall.GetEnvironmentStrings": "syscall", - "syscall.GetEnvironmentVariable": "syscall", - "syscall.GetExitCodeProcess": "syscall", - "syscall.GetFileAttributes": "syscall", - "syscall.GetFileAttributesEx": "syscall", - "syscall.GetFileExInfoStandard": "syscall", - "syscall.GetFileExMaxInfoLevel": "syscall", - "syscall.GetFileInformationByHandle": "syscall", - "syscall.GetFileType": "syscall", - "syscall.GetFullPathName": "syscall", - "syscall.GetHostByName": "syscall", - "syscall.GetIfEntry": "syscall", - "syscall.GetLastError": "syscall", - "syscall.GetLengthSid": "syscall", - "syscall.GetLongPathName": "syscall", - "syscall.GetProcAddress": "syscall", - "syscall.GetProcessTimes": "syscall", - "syscall.GetProtoByName": "syscall", - "syscall.GetQueuedCompletionStatus": "syscall", - "syscall.GetServByName": "syscall", - "syscall.GetShortPathName": "syscall", - "syscall.GetStartupInfo": "syscall", - "syscall.GetStdHandle": "syscall", - "syscall.GetSystemTimeAsFileTime": "syscall", - "syscall.GetTempPath": "syscall", - "syscall.GetTimeZoneInformation": "syscall", - "syscall.GetTokenInformation": "syscall", - "syscall.GetUserNameEx": "syscall", - "syscall.GetUserProfileDirectory": "syscall", - "syscall.GetVersion": "syscall", - "syscall.Getcwd": "syscall", - "syscall.Getdents": "syscall", - "syscall.Getdirentries": "syscall", - "syscall.Getdtablesize": "syscall", - "syscall.Getegid": "syscall", - "syscall.Getenv": "syscall", - "syscall.Geteuid": "syscall", - "syscall.Getfsstat": "syscall", - "syscall.Getgid": "syscall", - "syscall.Getgroups": "syscall", - "syscall.Getpagesize": "syscall", - "syscall.Getpeername": "syscall", - "syscall.Getpgid": "syscall", - "syscall.Getpgrp": "syscall", - "syscall.Getpid": "syscall", - "syscall.Getppid": "syscall", - "syscall.Getpriority": "syscall", - "syscall.Getrlimit": "syscall", - "syscall.Getrusage": "syscall", - "syscall.Getsid": "syscall", - "syscall.Getsockname": "syscall", - "syscall.Getsockopt": "syscall", - "syscall.GetsockoptByte": "syscall", - "syscall.GetsockoptICMPv6Filter": "syscall", - "syscall.GetsockoptIPMreq": "syscall", - "syscall.GetsockoptIPMreqn": "syscall", - "syscall.GetsockoptIPv6MTUInfo": "syscall", - "syscall.GetsockoptIPv6Mreq": "syscall", - "syscall.GetsockoptInet4Addr": "syscall", - "syscall.GetsockoptInt": "syscall", - "syscall.GetsockoptUcred": "syscall", - "syscall.Gettid": "syscall", - "syscall.Gettimeofday": "syscall", - "syscall.Getuid": "syscall", - "syscall.Getwd": "syscall", - "syscall.Getxattr": "syscall", - "syscall.HANDLE_FLAG_INHERIT": "syscall", - "syscall.HKEY_CLASSES_ROOT": "syscall", - "syscall.HKEY_CURRENT_CONFIG": "syscall", - "syscall.HKEY_CURRENT_USER": "syscall", - "syscall.HKEY_DYN_DATA": "syscall", - "syscall.HKEY_LOCAL_MACHINE": "syscall", - "syscall.HKEY_PERFORMANCE_DATA": "syscall", - "syscall.HKEY_USERS": "syscall", - "syscall.HUPCL": "syscall", - "syscall.Handle": "syscall", - "syscall.Hostent": "syscall", - "syscall.ICANON": "syscall", - "syscall.ICMP6_FILTER": "syscall", - "syscall.ICMPV6_FILTER": "syscall", - "syscall.ICMPv6Filter": "syscall", - "syscall.ICRNL": "syscall", - "syscall.IEXTEN": "syscall", - "syscall.IFAN_ARRIVAL": "syscall", - "syscall.IFAN_DEPARTURE": "syscall", - "syscall.IFA_ADDRESS": "syscall", - "syscall.IFA_ANYCAST": "syscall", - "syscall.IFA_BROADCAST": "syscall", - "syscall.IFA_CACHEINFO": "syscall", - "syscall.IFA_F_DADFAILED": "syscall", - "syscall.IFA_F_DEPRECATED": "syscall", - "syscall.IFA_F_HOMEADDRESS": "syscall", - "syscall.IFA_F_NODAD": "syscall", - "syscall.IFA_F_OPTIMISTIC": "syscall", - "syscall.IFA_F_PERMANENT": "syscall", - "syscall.IFA_F_SECONDARY": "syscall", - "syscall.IFA_F_TEMPORARY": "syscall", - "syscall.IFA_F_TENTATIVE": "syscall", - "syscall.IFA_LABEL": "syscall", - "syscall.IFA_LOCAL": "syscall", - "syscall.IFA_MAX": "syscall", - "syscall.IFA_MULTICAST": "syscall", - "syscall.IFA_ROUTE": "syscall", - "syscall.IFA_UNSPEC": "syscall", - "syscall.IFF_ALLMULTI": "syscall", - "syscall.IFF_ALTPHYS": "syscall", - "syscall.IFF_AUTOMEDIA": "syscall", - "syscall.IFF_BROADCAST": "syscall", - "syscall.IFF_CANTCHANGE": "syscall", - "syscall.IFF_CANTCONFIG": "syscall", - "syscall.IFF_DEBUG": "syscall", - "syscall.IFF_DRV_OACTIVE": "syscall", - "syscall.IFF_DRV_RUNNING": "syscall", - "syscall.IFF_DYING": "syscall", - "syscall.IFF_DYNAMIC": "syscall", - "syscall.IFF_LINK0": "syscall", - "syscall.IFF_LINK1": "syscall", - "syscall.IFF_LINK2": "syscall", - "syscall.IFF_LOOPBACK": "syscall", - "syscall.IFF_MASTER": "syscall", - "syscall.IFF_MONITOR": "syscall", - "syscall.IFF_MULTICAST": "syscall", - "syscall.IFF_NOARP": "syscall", - "syscall.IFF_NOTRAILERS": "syscall", - "syscall.IFF_NO_PI": "syscall", - "syscall.IFF_OACTIVE": "syscall", - "syscall.IFF_ONE_QUEUE": "syscall", - "syscall.IFF_POINTOPOINT": "syscall", - "syscall.IFF_POINTTOPOINT": "syscall", - "syscall.IFF_PORTSEL": "syscall", - "syscall.IFF_PPROMISC": "syscall", - "syscall.IFF_PROMISC": "syscall", - "syscall.IFF_RENAMING": "syscall", - "syscall.IFF_RUNNING": "syscall", - "syscall.IFF_SIMPLEX": "syscall", - "syscall.IFF_SLAVE": "syscall", - "syscall.IFF_SMART": "syscall", - "syscall.IFF_STATICARP": "syscall", - "syscall.IFF_TAP": "syscall", - "syscall.IFF_TUN": "syscall", - "syscall.IFF_TUN_EXCL": "syscall", - "syscall.IFF_UP": "syscall", - "syscall.IFF_VNET_HDR": "syscall", - "syscall.IFLA_ADDRESS": "syscall", - "syscall.IFLA_BROADCAST": "syscall", - "syscall.IFLA_COST": "syscall", - "syscall.IFLA_IFALIAS": "syscall", - "syscall.IFLA_IFNAME": "syscall", - "syscall.IFLA_LINK": "syscall", - "syscall.IFLA_LINKINFO": "syscall", - "syscall.IFLA_LINKMODE": "syscall", - "syscall.IFLA_MAP": "syscall", - "syscall.IFLA_MASTER": "syscall", - "syscall.IFLA_MAX": "syscall", - "syscall.IFLA_MTU": "syscall", - "syscall.IFLA_NET_NS_PID": "syscall", - "syscall.IFLA_OPERSTATE": "syscall", - "syscall.IFLA_PRIORITY": "syscall", - "syscall.IFLA_PROTINFO": "syscall", - "syscall.IFLA_QDISC": "syscall", - "syscall.IFLA_STATS": "syscall", - "syscall.IFLA_TXQLEN": "syscall", - "syscall.IFLA_UNSPEC": "syscall", - "syscall.IFLA_WEIGHT": "syscall", - "syscall.IFLA_WIRELESS": "syscall", - "syscall.IFNAMSIZ": "syscall", - "syscall.IFT_1822": "syscall", - "syscall.IFT_A12MPPSWITCH": "syscall", - "syscall.IFT_AAL2": "syscall", - "syscall.IFT_AAL5": "syscall", - "syscall.IFT_ADSL": "syscall", - "syscall.IFT_AFLANE8023": "syscall", - "syscall.IFT_AFLANE8025": "syscall", - "syscall.IFT_ARAP": "syscall", - "syscall.IFT_ARCNET": "syscall", - "syscall.IFT_ARCNETPLUS": "syscall", - "syscall.IFT_ASYNC": "syscall", - "syscall.IFT_ATM": "syscall", - "syscall.IFT_ATMDXI": "syscall", - "syscall.IFT_ATMFUNI": "syscall", - "syscall.IFT_ATMIMA": "syscall", - "syscall.IFT_ATMLOGICAL": "syscall", - "syscall.IFT_ATMRADIO": "syscall", - "syscall.IFT_ATMSUBINTERFACE": "syscall", - "syscall.IFT_ATMVCIENDPT": "syscall", - "syscall.IFT_ATMVIRTUAL": "syscall", - "syscall.IFT_BGPPOLICYACCOUNTING": "syscall", - "syscall.IFT_BLUETOOTH": "syscall", - "syscall.IFT_BRIDGE": "syscall", - "syscall.IFT_BSC": "syscall", - "syscall.IFT_CARP": "syscall", - "syscall.IFT_CCTEMUL": "syscall", - "syscall.IFT_CELLULAR": "syscall", - "syscall.IFT_CEPT": "syscall", - "syscall.IFT_CES": "syscall", - "syscall.IFT_CHANNEL": "syscall", - "syscall.IFT_CNR": "syscall", - "syscall.IFT_COFFEE": "syscall", - "syscall.IFT_COMPOSITELINK": "syscall", - "syscall.IFT_DCN": "syscall", - "syscall.IFT_DIGITALPOWERLINE": "syscall", - "syscall.IFT_DIGITALWRAPPEROVERHEADCHANNEL": "syscall", - "syscall.IFT_DLSW": "syscall", - "syscall.IFT_DOCSCABLEDOWNSTREAM": "syscall", - "syscall.IFT_DOCSCABLEMACLAYER": "syscall", - "syscall.IFT_DOCSCABLEUPSTREAM": "syscall", - "syscall.IFT_DOCSCABLEUPSTREAMCHANNEL": "syscall", - "syscall.IFT_DS0": "syscall", - "syscall.IFT_DS0BUNDLE": "syscall", - "syscall.IFT_DS1FDL": "syscall", - "syscall.IFT_DS3": "syscall", - "syscall.IFT_DTM": "syscall", - "syscall.IFT_DUMMY": "syscall", - "syscall.IFT_DVBASILN": "syscall", - "syscall.IFT_DVBASIOUT": "syscall", - "syscall.IFT_DVBRCCDOWNSTREAM": "syscall", - "syscall.IFT_DVBRCCMACLAYER": "syscall", - "syscall.IFT_DVBRCCUPSTREAM": "syscall", - "syscall.IFT_ECONET": "syscall", - "syscall.IFT_ENC": "syscall", - "syscall.IFT_EON": "syscall", - "syscall.IFT_EPLRS": "syscall", - "syscall.IFT_ESCON": "syscall", - "syscall.IFT_ETHER": "syscall", - "syscall.IFT_FAITH": "syscall", - "syscall.IFT_FAST": "syscall", - "syscall.IFT_FASTETHER": "syscall", - "syscall.IFT_FASTETHERFX": "syscall", - "syscall.IFT_FDDI": "syscall", - "syscall.IFT_FIBRECHANNEL": "syscall", - "syscall.IFT_FRAMERELAYINTERCONNECT": "syscall", - "syscall.IFT_FRAMERELAYMPI": "syscall", - "syscall.IFT_FRDLCIENDPT": "syscall", - "syscall.IFT_FRELAY": "syscall", - "syscall.IFT_FRELAYDCE": "syscall", - "syscall.IFT_FRF16MFRBUNDLE": "syscall", - "syscall.IFT_FRFORWARD": "syscall", - "syscall.IFT_G703AT2MB": "syscall", - "syscall.IFT_G703AT64K": "syscall", - "syscall.IFT_GIF": "syscall", - "syscall.IFT_GIGABITETHERNET": "syscall", - "syscall.IFT_GR303IDT": "syscall", - "syscall.IFT_GR303RDT": "syscall", - "syscall.IFT_H323GATEKEEPER": "syscall", - "syscall.IFT_H323PROXY": "syscall", - "syscall.IFT_HDH1822": "syscall", - "syscall.IFT_HDLC": "syscall", - "syscall.IFT_HDSL2": "syscall", - "syscall.IFT_HIPERLAN2": "syscall", - "syscall.IFT_HIPPI": "syscall", - "syscall.IFT_HIPPIINTERFACE": "syscall", - "syscall.IFT_HOSTPAD": "syscall", - "syscall.IFT_HSSI": "syscall", - "syscall.IFT_HY": "syscall", - "syscall.IFT_IBM370PARCHAN": "syscall", - "syscall.IFT_IDSL": "syscall", - "syscall.IFT_IEEE1394": "syscall", - "syscall.IFT_IEEE80211": "syscall", - "syscall.IFT_IEEE80212": "syscall", - "syscall.IFT_IEEE8023ADLAG": "syscall", - "syscall.IFT_IFGSN": "syscall", - "syscall.IFT_IMT": "syscall", - "syscall.IFT_INFINIBAND": "syscall", - "syscall.IFT_INTERLEAVE": "syscall", - "syscall.IFT_IP": "syscall", - "syscall.IFT_IPFORWARD": "syscall", - "syscall.IFT_IPOVERATM": "syscall", - "syscall.IFT_IPOVERCDLC": "syscall", - "syscall.IFT_IPOVERCLAW": "syscall", - "syscall.IFT_IPSWITCH": "syscall", - "syscall.IFT_IPXIP": "syscall", - "syscall.IFT_ISDN": "syscall", - "syscall.IFT_ISDNBASIC": "syscall", - "syscall.IFT_ISDNPRIMARY": "syscall", - "syscall.IFT_ISDNS": "syscall", - "syscall.IFT_ISDNU": "syscall", - "syscall.IFT_ISO88022LLC": "syscall", - "syscall.IFT_ISO88023": "syscall", - "syscall.IFT_ISO88024": "syscall", - "syscall.IFT_ISO88025": "syscall", - "syscall.IFT_ISO88025CRFPINT": "syscall", - "syscall.IFT_ISO88025DTR": "syscall", - "syscall.IFT_ISO88025FIBER": "syscall", - "syscall.IFT_ISO88026": "syscall", - "syscall.IFT_ISUP": "syscall", - "syscall.IFT_L2VLAN": "syscall", - "syscall.IFT_L3IPVLAN": "syscall", - "syscall.IFT_L3IPXVLAN": "syscall", - "syscall.IFT_LAPB": "syscall", - "syscall.IFT_LAPD": "syscall", - "syscall.IFT_LAPF": "syscall", - "syscall.IFT_LINEGROUP": "syscall", - "syscall.IFT_LOCALTALK": "syscall", - "syscall.IFT_LOOP": "syscall", - "syscall.IFT_MEDIAMAILOVERIP": "syscall", - "syscall.IFT_MFSIGLINK": "syscall", - "syscall.IFT_MIOX25": "syscall", - "syscall.IFT_MODEM": "syscall", - "syscall.IFT_MPC": "syscall", - "syscall.IFT_MPLS": "syscall", - "syscall.IFT_MPLSTUNNEL": "syscall", - "syscall.IFT_MSDSL": "syscall", - "syscall.IFT_MVL": "syscall", - "syscall.IFT_MYRINET": "syscall", - "syscall.IFT_NFAS": "syscall", - "syscall.IFT_NSIP": "syscall", - "syscall.IFT_OPTICALCHANNEL": "syscall", - "syscall.IFT_OPTICALTRANSPORT": "syscall", - "syscall.IFT_OTHER": "syscall", - "syscall.IFT_P10": "syscall", - "syscall.IFT_P80": "syscall", - "syscall.IFT_PARA": "syscall", - "syscall.IFT_PDP": "syscall", - "syscall.IFT_PFLOG": "syscall", - "syscall.IFT_PFLOW": "syscall", - "syscall.IFT_PFSYNC": "syscall", - "syscall.IFT_PLC": "syscall", - "syscall.IFT_PON155": "syscall", - "syscall.IFT_PON622": "syscall", - "syscall.IFT_POS": "syscall", - "syscall.IFT_PPP": "syscall", - "syscall.IFT_PPPMULTILINKBUNDLE": "syscall", - "syscall.IFT_PROPATM": "syscall", - "syscall.IFT_PROPBWAP2MP": "syscall", - "syscall.IFT_PROPCNLS": "syscall", - "syscall.IFT_PROPDOCSWIRELESSDOWNSTREAM": "syscall", - "syscall.IFT_PROPDOCSWIRELESSMACLAYER": "syscall", - "syscall.IFT_PROPDOCSWIRELESSUPSTREAM": "syscall", - "syscall.IFT_PROPMUX": "syscall", - "syscall.IFT_PROPVIRTUAL": "syscall", - "syscall.IFT_PROPWIRELESSP2P": "syscall", - "syscall.IFT_PTPSERIAL": "syscall", - "syscall.IFT_PVC": "syscall", - "syscall.IFT_Q2931": "syscall", - "syscall.IFT_QLLC": "syscall", - "syscall.IFT_RADIOMAC": "syscall", - "syscall.IFT_RADSL": "syscall", - "syscall.IFT_REACHDSL": "syscall", - "syscall.IFT_RFC1483": "syscall", - "syscall.IFT_RS232": "syscall", - "syscall.IFT_RSRB": "syscall", - "syscall.IFT_SDLC": "syscall", - "syscall.IFT_SDSL": "syscall", - "syscall.IFT_SHDSL": "syscall", - "syscall.IFT_SIP": "syscall", - "syscall.IFT_SIPSIG": "syscall", - "syscall.IFT_SIPTG": "syscall", - "syscall.IFT_SLIP": "syscall", - "syscall.IFT_SMDSDXI": "syscall", - "syscall.IFT_SMDSICIP": "syscall", - "syscall.IFT_SONET": "syscall", - "syscall.IFT_SONETOVERHEADCHANNEL": "syscall", - "syscall.IFT_SONETPATH": "syscall", - "syscall.IFT_SONETVT": "syscall", - "syscall.IFT_SRP": "syscall", - "syscall.IFT_SS7SIGLINK": "syscall", - "syscall.IFT_STACKTOSTACK": "syscall", - "syscall.IFT_STARLAN": "syscall", - "syscall.IFT_STF": "syscall", - "syscall.IFT_T1": "syscall", - "syscall.IFT_TDLC": "syscall", - "syscall.IFT_TELINK": "syscall", - "syscall.IFT_TERMPAD": "syscall", - "syscall.IFT_TR008": "syscall", - "syscall.IFT_TRANSPHDLC": "syscall", - "syscall.IFT_TUNNEL": "syscall", - "syscall.IFT_ULTRA": "syscall", - "syscall.IFT_USB": "syscall", - "syscall.IFT_V11": "syscall", - "syscall.IFT_V35": "syscall", - "syscall.IFT_V36": "syscall", - "syscall.IFT_V37": "syscall", - "syscall.IFT_VDSL": "syscall", - "syscall.IFT_VIRTUALIPADDRESS": "syscall", - "syscall.IFT_VIRTUALTG": "syscall", - "syscall.IFT_VOICEDID": "syscall", - "syscall.IFT_VOICEEM": "syscall", - "syscall.IFT_VOICEEMFGD": "syscall", - "syscall.IFT_VOICEENCAP": "syscall", - "syscall.IFT_VOICEFGDEANA": "syscall", - "syscall.IFT_VOICEFXO": "syscall", - "syscall.IFT_VOICEFXS": "syscall", - "syscall.IFT_VOICEOVERATM": "syscall", - "syscall.IFT_VOICEOVERCABLE": "syscall", - "syscall.IFT_VOICEOVERFRAMERELAY": "syscall", - "syscall.IFT_VOICEOVERIP": "syscall", - "syscall.IFT_X213": "syscall", - "syscall.IFT_X25": "syscall", - "syscall.IFT_X25DDN": "syscall", - "syscall.IFT_X25HUNTGROUP": "syscall", - "syscall.IFT_X25MLP": "syscall", - "syscall.IFT_X25PLE": "syscall", - "syscall.IFT_XETHER": "syscall", - "syscall.IGNBRK": "syscall", - "syscall.IGNCR": "syscall", - "syscall.IGNORE": "syscall", - "syscall.IGNPAR": "syscall", - "syscall.IMAXBEL": "syscall", - "syscall.INFINITE": "syscall", - "syscall.INLCR": "syscall", - "syscall.INPCK": "syscall", - "syscall.INVALID_FILE_ATTRIBUTES": "syscall", - "syscall.IN_ACCESS": "syscall", - "syscall.IN_ALL_EVENTS": "syscall", - "syscall.IN_ATTRIB": "syscall", - "syscall.IN_CLASSA_HOST": "syscall", - "syscall.IN_CLASSA_MAX": "syscall", - "syscall.IN_CLASSA_NET": "syscall", - "syscall.IN_CLASSA_NSHIFT": "syscall", - "syscall.IN_CLASSB_HOST": "syscall", - "syscall.IN_CLASSB_MAX": "syscall", - "syscall.IN_CLASSB_NET": "syscall", - "syscall.IN_CLASSB_NSHIFT": "syscall", - "syscall.IN_CLASSC_HOST": "syscall", - "syscall.IN_CLASSC_NET": "syscall", - "syscall.IN_CLASSC_NSHIFT": "syscall", - "syscall.IN_CLASSD_HOST": "syscall", - "syscall.IN_CLASSD_NET": "syscall", - "syscall.IN_CLASSD_NSHIFT": "syscall", - "syscall.IN_CLOEXEC": "syscall", - "syscall.IN_CLOSE": "syscall", - "syscall.IN_CLOSE_NOWRITE": "syscall", - "syscall.IN_CLOSE_WRITE": "syscall", - "syscall.IN_CREATE": "syscall", - "syscall.IN_DELETE": "syscall", - "syscall.IN_DELETE_SELF": "syscall", - "syscall.IN_DONT_FOLLOW": "syscall", - "syscall.IN_EXCL_UNLINK": "syscall", - "syscall.IN_IGNORED": "syscall", - "syscall.IN_ISDIR": "syscall", - "syscall.IN_LINKLOCALNETNUM": "syscall", - "syscall.IN_LOOPBACKNET": "syscall", - "syscall.IN_MASK_ADD": "syscall", - "syscall.IN_MODIFY": "syscall", - "syscall.IN_MOVE": "syscall", - "syscall.IN_MOVED_FROM": "syscall", - "syscall.IN_MOVED_TO": "syscall", - "syscall.IN_MOVE_SELF": "syscall", - "syscall.IN_NONBLOCK": "syscall", - "syscall.IN_ONESHOT": "syscall", - "syscall.IN_ONLYDIR": "syscall", - "syscall.IN_OPEN": "syscall", - "syscall.IN_Q_OVERFLOW": "syscall", - "syscall.IN_RFC3021_HOST": "syscall", - "syscall.IN_RFC3021_MASK": "syscall", - "syscall.IN_RFC3021_NET": "syscall", - "syscall.IN_RFC3021_NSHIFT": "syscall", - "syscall.IN_UNMOUNT": "syscall", - "syscall.IOC_IN": "syscall", - "syscall.IOC_INOUT": "syscall", - "syscall.IOC_OUT": "syscall", - "syscall.IOC_VENDOR": "syscall", - "syscall.IOC_WS2": "syscall", - "syscall.IO_REPARSE_TAG_SYMLINK": "syscall", - "syscall.IPMreq": "syscall", - "syscall.IPMreqn": "syscall", - "syscall.IPPROTO_3PC": "syscall", - "syscall.IPPROTO_ADFS": "syscall", - "syscall.IPPROTO_AH": "syscall", - "syscall.IPPROTO_AHIP": "syscall", - "syscall.IPPROTO_APES": "syscall", - "syscall.IPPROTO_ARGUS": "syscall", - "syscall.IPPROTO_AX25": "syscall", - "syscall.IPPROTO_BHA": "syscall", - "syscall.IPPROTO_BLT": "syscall", - "syscall.IPPROTO_BRSATMON": "syscall", - "syscall.IPPROTO_CARP": "syscall", - "syscall.IPPROTO_CFTP": "syscall", - "syscall.IPPROTO_CHAOS": "syscall", - "syscall.IPPROTO_CMTP": "syscall", - "syscall.IPPROTO_COMP": "syscall", - "syscall.IPPROTO_CPHB": "syscall", - "syscall.IPPROTO_CPNX": "syscall", - "syscall.IPPROTO_DCCP": "syscall", - "syscall.IPPROTO_DDP": "syscall", - "syscall.IPPROTO_DGP": "syscall", - "syscall.IPPROTO_DIVERT": "syscall", - "syscall.IPPROTO_DIVERT_INIT": "syscall", - "syscall.IPPROTO_DIVERT_RESP": "syscall", - "syscall.IPPROTO_DONE": "syscall", - "syscall.IPPROTO_DSTOPTS": "syscall", - "syscall.IPPROTO_EGP": "syscall", - "syscall.IPPROTO_EMCON": "syscall", - "syscall.IPPROTO_ENCAP": "syscall", - "syscall.IPPROTO_EON": "syscall", - "syscall.IPPROTO_ESP": "syscall", - "syscall.IPPROTO_ETHERIP": "syscall", - "syscall.IPPROTO_FRAGMENT": "syscall", - "syscall.IPPROTO_GGP": "syscall", - "syscall.IPPROTO_GMTP": "syscall", - "syscall.IPPROTO_GRE": "syscall", - "syscall.IPPROTO_HELLO": "syscall", - "syscall.IPPROTO_HMP": "syscall", - "syscall.IPPROTO_HOPOPTS": "syscall", - "syscall.IPPROTO_ICMP": "syscall", - "syscall.IPPROTO_ICMPV6": "syscall", - "syscall.IPPROTO_IDP": "syscall", - "syscall.IPPROTO_IDPR": "syscall", - "syscall.IPPROTO_IDRP": "syscall", - "syscall.IPPROTO_IGMP": "syscall", - "syscall.IPPROTO_IGP": "syscall", - "syscall.IPPROTO_IGRP": "syscall", - "syscall.IPPROTO_IL": "syscall", - "syscall.IPPROTO_INLSP": "syscall", - "syscall.IPPROTO_INP": "syscall", - "syscall.IPPROTO_IP": "syscall", - "syscall.IPPROTO_IPCOMP": "syscall", - "syscall.IPPROTO_IPCV": "syscall", - "syscall.IPPROTO_IPEIP": "syscall", - "syscall.IPPROTO_IPIP": "syscall", - "syscall.IPPROTO_IPPC": "syscall", - "syscall.IPPROTO_IPV4": "syscall", - "syscall.IPPROTO_IPV6": "syscall", - "syscall.IPPROTO_IPV6_ICMP": "syscall", - "syscall.IPPROTO_IRTP": "syscall", - "syscall.IPPROTO_KRYPTOLAN": "syscall", - "syscall.IPPROTO_LARP": "syscall", - "syscall.IPPROTO_LEAF1": "syscall", - "syscall.IPPROTO_LEAF2": "syscall", - "syscall.IPPROTO_MAX": "syscall", - "syscall.IPPROTO_MAXID": "syscall", - "syscall.IPPROTO_MEAS": "syscall", - "syscall.IPPROTO_MH": "syscall", - "syscall.IPPROTO_MHRP": "syscall", - "syscall.IPPROTO_MICP": "syscall", - "syscall.IPPROTO_MOBILE": "syscall", - "syscall.IPPROTO_MPLS": "syscall", - "syscall.IPPROTO_MTP": "syscall", - "syscall.IPPROTO_MUX": "syscall", - "syscall.IPPROTO_ND": "syscall", - "syscall.IPPROTO_NHRP": "syscall", - "syscall.IPPROTO_NONE": "syscall", - "syscall.IPPROTO_NSP": "syscall", - "syscall.IPPROTO_NVPII": "syscall", - "syscall.IPPROTO_OLD_DIVERT": "syscall", - "syscall.IPPROTO_OSPFIGP": "syscall", - "syscall.IPPROTO_PFSYNC": "syscall", - "syscall.IPPROTO_PGM": "syscall", - "syscall.IPPROTO_PIGP": "syscall", - "syscall.IPPROTO_PIM": "syscall", - "syscall.IPPROTO_PRM": "syscall", - "syscall.IPPROTO_PUP": "syscall", - "syscall.IPPROTO_PVP": "syscall", - "syscall.IPPROTO_RAW": "syscall", - "syscall.IPPROTO_RCCMON": "syscall", - "syscall.IPPROTO_RDP": "syscall", - "syscall.IPPROTO_ROUTING": "syscall", - "syscall.IPPROTO_RSVP": "syscall", - "syscall.IPPROTO_RVD": "syscall", - "syscall.IPPROTO_SATEXPAK": "syscall", - "syscall.IPPROTO_SATMON": "syscall", - "syscall.IPPROTO_SCCSP": "syscall", - "syscall.IPPROTO_SCTP": "syscall", - "syscall.IPPROTO_SDRP": "syscall", - "syscall.IPPROTO_SEND": "syscall", - "syscall.IPPROTO_SEP": "syscall", - "syscall.IPPROTO_SKIP": "syscall", - "syscall.IPPROTO_SPACER": "syscall", - "syscall.IPPROTO_SRPC": "syscall", - "syscall.IPPROTO_ST": "syscall", - "syscall.IPPROTO_SVMTP": "syscall", - "syscall.IPPROTO_SWIPE": "syscall", - "syscall.IPPROTO_TCF": "syscall", - "syscall.IPPROTO_TCP": "syscall", - "syscall.IPPROTO_TLSP": "syscall", - "syscall.IPPROTO_TP": "syscall", - "syscall.IPPROTO_TPXX": "syscall", - "syscall.IPPROTO_TRUNK1": "syscall", - "syscall.IPPROTO_TRUNK2": "syscall", - "syscall.IPPROTO_TTP": "syscall", - "syscall.IPPROTO_UDP": "syscall", - "syscall.IPPROTO_UDPLITE": "syscall", - "syscall.IPPROTO_VINES": "syscall", - "syscall.IPPROTO_VISA": "syscall", - "syscall.IPPROTO_VMTP": "syscall", - "syscall.IPPROTO_VRRP": "syscall", - "syscall.IPPROTO_WBEXPAK": "syscall", - "syscall.IPPROTO_WBMON": "syscall", - "syscall.IPPROTO_WSN": "syscall", - "syscall.IPPROTO_XNET": "syscall", - "syscall.IPPROTO_XTP": "syscall", - "syscall.IPV6_2292DSTOPTS": "syscall", - "syscall.IPV6_2292HOPLIMIT": "syscall", - "syscall.IPV6_2292HOPOPTS": "syscall", - "syscall.IPV6_2292NEXTHOP": "syscall", - "syscall.IPV6_2292PKTINFO": "syscall", - "syscall.IPV6_2292PKTOPTIONS": "syscall", - "syscall.IPV6_2292RTHDR": "syscall", - "syscall.IPV6_ADDRFORM": "syscall", - "syscall.IPV6_ADD_MEMBERSHIP": "syscall", - "syscall.IPV6_AUTHHDR": "syscall", - "syscall.IPV6_AUTH_LEVEL": "syscall", - "syscall.IPV6_AUTOFLOWLABEL": "syscall", - "syscall.IPV6_BINDANY": "syscall", - "syscall.IPV6_BINDV6ONLY": "syscall", - "syscall.IPV6_BOUND_IF": "syscall", - "syscall.IPV6_CHECKSUM": "syscall", - "syscall.IPV6_DEFAULT_MULTICAST_HOPS": "syscall", - "syscall.IPV6_DEFAULT_MULTICAST_LOOP": "syscall", - "syscall.IPV6_DEFHLIM": "syscall", - "syscall.IPV6_DONTFRAG": "syscall", - "syscall.IPV6_DROP_MEMBERSHIP": "syscall", - "syscall.IPV6_DSTOPTS": "syscall", - "syscall.IPV6_ESP_NETWORK_LEVEL": "syscall", - "syscall.IPV6_ESP_TRANS_LEVEL": "syscall", - "syscall.IPV6_FAITH": "syscall", - "syscall.IPV6_FLOWINFO_MASK": "syscall", - "syscall.IPV6_FLOWLABEL_MASK": "syscall", - "syscall.IPV6_FRAGTTL": "syscall", - "syscall.IPV6_FW_ADD": "syscall", - "syscall.IPV6_FW_DEL": "syscall", - "syscall.IPV6_FW_FLUSH": "syscall", - "syscall.IPV6_FW_GET": "syscall", - "syscall.IPV6_FW_ZERO": "syscall", - "syscall.IPV6_HLIMDEC": "syscall", - "syscall.IPV6_HOPLIMIT": "syscall", - "syscall.IPV6_HOPOPTS": "syscall", - "syscall.IPV6_IPCOMP_LEVEL": "syscall", - "syscall.IPV6_IPSEC_POLICY": "syscall", - "syscall.IPV6_JOIN_ANYCAST": "syscall", - "syscall.IPV6_JOIN_GROUP": "syscall", - "syscall.IPV6_LEAVE_ANYCAST": "syscall", - "syscall.IPV6_LEAVE_GROUP": "syscall", - "syscall.IPV6_MAXHLIM": "syscall", - "syscall.IPV6_MAXOPTHDR": "syscall", - "syscall.IPV6_MAXPACKET": "syscall", - "syscall.IPV6_MAX_GROUP_SRC_FILTER": "syscall", - "syscall.IPV6_MAX_MEMBERSHIPS": "syscall", - "syscall.IPV6_MAX_SOCK_SRC_FILTER": "syscall", - "syscall.IPV6_MIN_MEMBERSHIPS": "syscall", - "syscall.IPV6_MMTU": "syscall", - "syscall.IPV6_MSFILTER": "syscall", - "syscall.IPV6_MTU": "syscall", - "syscall.IPV6_MTU_DISCOVER": "syscall", - "syscall.IPV6_MULTICAST_HOPS": "syscall", - "syscall.IPV6_MULTICAST_IF": "syscall", - "syscall.IPV6_MULTICAST_LOOP": "syscall", - "syscall.IPV6_NEXTHOP": "syscall", - "syscall.IPV6_OPTIONS": "syscall", - "syscall.IPV6_PATHMTU": "syscall", - "syscall.IPV6_PIPEX": "syscall", - "syscall.IPV6_PKTINFO": "syscall", - "syscall.IPV6_PMTUDISC_DO": "syscall", - "syscall.IPV6_PMTUDISC_DONT": "syscall", - "syscall.IPV6_PMTUDISC_PROBE": "syscall", - "syscall.IPV6_PMTUDISC_WANT": "syscall", - "syscall.IPV6_PORTRANGE": "syscall", - "syscall.IPV6_PORTRANGE_DEFAULT": "syscall", - "syscall.IPV6_PORTRANGE_HIGH": "syscall", - "syscall.IPV6_PORTRANGE_LOW": "syscall", - "syscall.IPV6_PREFER_TEMPADDR": "syscall", - "syscall.IPV6_RECVDSTOPTS": "syscall", - "syscall.IPV6_RECVDSTPORT": "syscall", - "syscall.IPV6_RECVERR": "syscall", - "syscall.IPV6_RECVHOPLIMIT": "syscall", - "syscall.IPV6_RECVHOPOPTS": "syscall", - "syscall.IPV6_RECVPATHMTU": "syscall", - "syscall.IPV6_RECVPKTINFO": "syscall", - "syscall.IPV6_RECVRTHDR": "syscall", - "syscall.IPV6_RECVTCLASS": "syscall", - "syscall.IPV6_ROUTER_ALERT": "syscall", - "syscall.IPV6_RTABLE": "syscall", - "syscall.IPV6_RTHDR": "syscall", - "syscall.IPV6_RTHDRDSTOPTS": "syscall", - "syscall.IPV6_RTHDR_LOOSE": "syscall", - "syscall.IPV6_RTHDR_STRICT": "syscall", - "syscall.IPV6_RTHDR_TYPE_0": "syscall", - "syscall.IPV6_RXDSTOPTS": "syscall", - "syscall.IPV6_RXHOPOPTS": "syscall", - "syscall.IPV6_SOCKOPT_RESERVED1": "syscall", - "syscall.IPV6_TCLASS": "syscall", - "syscall.IPV6_UNICAST_HOPS": "syscall", - "syscall.IPV6_USE_MIN_MTU": "syscall", - "syscall.IPV6_V6ONLY": "syscall", - "syscall.IPV6_VERSION": "syscall", - "syscall.IPV6_VERSION_MASK": "syscall", - "syscall.IPV6_XFRM_POLICY": "syscall", - "syscall.IP_ADD_MEMBERSHIP": "syscall", - "syscall.IP_ADD_SOURCE_MEMBERSHIP": "syscall", - "syscall.IP_AUTH_LEVEL": "syscall", - "syscall.IP_BINDANY": "syscall", - "syscall.IP_BLOCK_SOURCE": "syscall", - "syscall.IP_BOUND_IF": "syscall", - "syscall.IP_DEFAULT_MULTICAST_LOOP": "syscall", - "syscall.IP_DEFAULT_MULTICAST_TTL": "syscall", - "syscall.IP_DF": "syscall", - "syscall.IP_DIVERTFL": "syscall", - "syscall.IP_DONTFRAG": "syscall", - "syscall.IP_DROP_MEMBERSHIP": "syscall", - "syscall.IP_DROP_SOURCE_MEMBERSHIP": "syscall", - "syscall.IP_DUMMYNET3": "syscall", - "syscall.IP_DUMMYNET_CONFIGURE": "syscall", - "syscall.IP_DUMMYNET_DEL": "syscall", - "syscall.IP_DUMMYNET_FLUSH": "syscall", - "syscall.IP_DUMMYNET_GET": "syscall", - "syscall.IP_EF": "syscall", - "syscall.IP_ERRORMTU": "syscall", - "syscall.IP_ESP_NETWORK_LEVEL": "syscall", - "syscall.IP_ESP_TRANS_LEVEL": "syscall", - "syscall.IP_FAITH": "syscall", - "syscall.IP_FREEBIND": "syscall", - "syscall.IP_FW3": "syscall", - "syscall.IP_FW_ADD": "syscall", - "syscall.IP_FW_DEL": "syscall", - "syscall.IP_FW_FLUSH": "syscall", - "syscall.IP_FW_GET": "syscall", - "syscall.IP_FW_NAT_CFG": "syscall", - "syscall.IP_FW_NAT_DEL": "syscall", - "syscall.IP_FW_NAT_GET_CONFIG": "syscall", - "syscall.IP_FW_NAT_GET_LOG": "syscall", - "syscall.IP_FW_RESETLOG": "syscall", - "syscall.IP_FW_TABLE_ADD": "syscall", - "syscall.IP_FW_TABLE_DEL": "syscall", - "syscall.IP_FW_TABLE_FLUSH": "syscall", - "syscall.IP_FW_TABLE_GETSIZE": "syscall", - "syscall.IP_FW_TABLE_LIST": "syscall", - "syscall.IP_FW_ZERO": "syscall", - "syscall.IP_HDRINCL": "syscall", - "syscall.IP_IPCOMP_LEVEL": "syscall", - "syscall.IP_IPSECFLOWINFO": "syscall", - "syscall.IP_IPSEC_LOCAL_AUTH": "syscall", - "syscall.IP_IPSEC_LOCAL_CRED": "syscall", - "syscall.IP_IPSEC_LOCAL_ID": "syscall", - "syscall.IP_IPSEC_POLICY": "syscall", - "syscall.IP_IPSEC_REMOTE_AUTH": "syscall", - "syscall.IP_IPSEC_REMOTE_CRED": "syscall", - "syscall.IP_IPSEC_REMOTE_ID": "syscall", - "syscall.IP_MAXPACKET": "syscall", - "syscall.IP_MAX_GROUP_SRC_FILTER": "syscall", - "syscall.IP_MAX_MEMBERSHIPS": "syscall", - "syscall.IP_MAX_SOCK_MUTE_FILTER": "syscall", - "syscall.IP_MAX_SOCK_SRC_FILTER": "syscall", - "syscall.IP_MAX_SOURCE_FILTER": "syscall", - "syscall.IP_MF": "syscall", - "syscall.IP_MINFRAGSIZE": "syscall", - "syscall.IP_MINTTL": "syscall", - "syscall.IP_MIN_MEMBERSHIPS": "syscall", - "syscall.IP_MSFILTER": "syscall", - "syscall.IP_MSS": "syscall", - "syscall.IP_MTU": "syscall", - "syscall.IP_MTU_DISCOVER": "syscall", - "syscall.IP_MULTICAST_IF": "syscall", - "syscall.IP_MULTICAST_IFINDEX": "syscall", - "syscall.IP_MULTICAST_LOOP": "syscall", - "syscall.IP_MULTICAST_TTL": "syscall", - "syscall.IP_MULTICAST_VIF": "syscall", - "syscall.IP_NAT__XXX": "syscall", - "syscall.IP_OFFMASK": "syscall", - "syscall.IP_OLD_FW_ADD": "syscall", - "syscall.IP_OLD_FW_DEL": "syscall", - "syscall.IP_OLD_FW_FLUSH": "syscall", - "syscall.IP_OLD_FW_GET": "syscall", - "syscall.IP_OLD_FW_RESETLOG": "syscall", - "syscall.IP_OLD_FW_ZERO": "syscall", - "syscall.IP_ONESBCAST": "syscall", - "syscall.IP_OPTIONS": "syscall", - "syscall.IP_ORIGDSTADDR": "syscall", - "syscall.IP_PASSSEC": "syscall", - "syscall.IP_PIPEX": "syscall", - "syscall.IP_PKTINFO": "syscall", - "syscall.IP_PKTOPTIONS": "syscall", - "syscall.IP_PMTUDISC": "syscall", - "syscall.IP_PMTUDISC_DO": "syscall", - "syscall.IP_PMTUDISC_DONT": "syscall", - "syscall.IP_PMTUDISC_PROBE": "syscall", - "syscall.IP_PMTUDISC_WANT": "syscall", - "syscall.IP_PORTRANGE": "syscall", - "syscall.IP_PORTRANGE_DEFAULT": "syscall", - "syscall.IP_PORTRANGE_HIGH": "syscall", - "syscall.IP_PORTRANGE_LOW": "syscall", - "syscall.IP_RECVDSTADDR": "syscall", - "syscall.IP_RECVDSTPORT": "syscall", - "syscall.IP_RECVERR": "syscall", - "syscall.IP_RECVIF": "syscall", - "syscall.IP_RECVOPTS": "syscall", - "syscall.IP_RECVORIGDSTADDR": "syscall", - "syscall.IP_RECVPKTINFO": "syscall", - "syscall.IP_RECVRETOPTS": "syscall", - "syscall.IP_RECVRTABLE": "syscall", - "syscall.IP_RECVTOS": "syscall", - "syscall.IP_RECVTTL": "syscall", - "syscall.IP_RETOPTS": "syscall", - "syscall.IP_RF": "syscall", - "syscall.IP_ROUTER_ALERT": "syscall", - "syscall.IP_RSVP_OFF": "syscall", - "syscall.IP_RSVP_ON": "syscall", - "syscall.IP_RSVP_VIF_OFF": "syscall", - "syscall.IP_RSVP_VIF_ON": "syscall", - "syscall.IP_RTABLE": "syscall", - "syscall.IP_SENDSRCADDR": "syscall", - "syscall.IP_STRIPHDR": "syscall", - "syscall.IP_TOS": "syscall", - "syscall.IP_TRAFFIC_MGT_BACKGROUND": "syscall", - "syscall.IP_TRANSPARENT": "syscall", - "syscall.IP_TTL": "syscall", - "syscall.IP_UNBLOCK_SOURCE": "syscall", - "syscall.IP_XFRM_POLICY": "syscall", - "syscall.IPv6MTUInfo": "syscall", - "syscall.IPv6Mreq": "syscall", - "syscall.ISIG": "syscall", - "syscall.ISTRIP": "syscall", - "syscall.IUCLC": "syscall", - "syscall.IUTF8": "syscall", - "syscall.IXANY": "syscall", - "syscall.IXOFF": "syscall", - "syscall.IXON": "syscall", - "syscall.IfAddrmsg": "syscall", - "syscall.IfAnnounceMsghdr": "syscall", - "syscall.IfData": "syscall", - "syscall.IfInfomsg": "syscall", - "syscall.IfMsghdr": "syscall", - "syscall.IfaMsghdr": "syscall", - "syscall.IfmaMsghdr": "syscall", - "syscall.IfmaMsghdr2": "syscall", - "syscall.ImplementsGetwd": "syscall", - "syscall.Inet4Pktinfo": "syscall", - "syscall.Inet6Pktinfo": "syscall", - "syscall.InotifyAddWatch": "syscall", - "syscall.InotifyEvent": "syscall", - "syscall.InotifyInit": "syscall", - "syscall.InotifyInit1": "syscall", - "syscall.InotifyRmWatch": "syscall", - "syscall.InterfaceAddrMessage": "syscall", - "syscall.InterfaceAnnounceMessage": "syscall", - "syscall.InterfaceInfo": "syscall", - "syscall.InterfaceMessage": "syscall", - "syscall.InterfaceMulticastAddrMessage": "syscall", - "syscall.InvalidHandle": "syscall", - "syscall.Ioperm": "syscall", - "syscall.Iopl": "syscall", - "syscall.Iovec": "syscall", - "syscall.IpAdapterInfo": "syscall", - "syscall.IpAddrString": "syscall", - "syscall.IpAddressString": "syscall", - "syscall.IpMaskString": "syscall", - "syscall.Issetugid": "syscall", - "syscall.KEY_ALL_ACCESS": "syscall", - "syscall.KEY_CREATE_LINK": "syscall", - "syscall.KEY_CREATE_SUB_KEY": "syscall", - "syscall.KEY_ENUMERATE_SUB_KEYS": "syscall", - "syscall.KEY_EXECUTE": "syscall", - "syscall.KEY_NOTIFY": "syscall", - "syscall.KEY_QUERY_VALUE": "syscall", - "syscall.KEY_READ": "syscall", - "syscall.KEY_SET_VALUE": "syscall", - "syscall.KEY_WOW64_32KEY": "syscall", - "syscall.KEY_WOW64_64KEY": "syscall", - "syscall.KEY_WRITE": "syscall", - "syscall.Kevent": "syscall", - "syscall.Kevent_t": "syscall", - "syscall.Kill": "syscall", - "syscall.Klogctl": "syscall", - "syscall.Kqueue": "syscall", - "syscall.LANG_ENGLISH": "syscall", - "syscall.LAYERED_PROTOCOL": "syscall", - "syscall.LCNT_OVERLOAD_FLUSH": "syscall", - "syscall.LINUX_REBOOT_CMD_CAD_OFF": "syscall", - "syscall.LINUX_REBOOT_CMD_CAD_ON": "syscall", - "syscall.LINUX_REBOOT_CMD_HALT": "syscall", - "syscall.LINUX_REBOOT_CMD_KEXEC": "syscall", - "syscall.LINUX_REBOOT_CMD_POWER_OFF": "syscall", - "syscall.LINUX_REBOOT_CMD_RESTART": "syscall", - "syscall.LINUX_REBOOT_CMD_RESTART2": "syscall", - "syscall.LINUX_REBOOT_CMD_SW_SUSPEND": "syscall", - "syscall.LINUX_REBOOT_MAGIC1": "syscall", - "syscall.LINUX_REBOOT_MAGIC2": "syscall", - "syscall.LOCK_EX": "syscall", - "syscall.LOCK_NB": "syscall", - "syscall.LOCK_SH": "syscall", - "syscall.LOCK_UN": "syscall", - "syscall.LazyDLL": "syscall", - "syscall.LazyProc": "syscall", - "syscall.Lchown": "syscall", - "syscall.Linger": "syscall", - "syscall.Link": "syscall", - "syscall.Listen": "syscall", - "syscall.Listxattr": "syscall", - "syscall.LoadCancelIoEx": "syscall", - "syscall.LoadConnectEx": "syscall", - "syscall.LoadCreateSymbolicLink": "syscall", - "syscall.LoadDLL": "syscall", - "syscall.LoadGetAddrInfo": "syscall", - "syscall.LoadLibrary": "syscall", - "syscall.LoadSetFileCompletionNotificationModes": "syscall", - "syscall.LocalFree": "syscall", - "syscall.Log2phys_t": "syscall", - "syscall.LookupAccountName": "syscall", - "syscall.LookupAccountSid": "syscall", - "syscall.LookupSID": "syscall", - "syscall.LsfJump": "syscall", - "syscall.LsfSocket": "syscall", - "syscall.LsfStmt": "syscall", - "syscall.Lstat": "syscall", - "syscall.MADV_AUTOSYNC": "syscall", - "syscall.MADV_CAN_REUSE": "syscall", - "syscall.MADV_CORE": "syscall", - "syscall.MADV_DOFORK": "syscall", - "syscall.MADV_DONTFORK": "syscall", - "syscall.MADV_DONTNEED": "syscall", - "syscall.MADV_FREE": "syscall", - "syscall.MADV_FREE_REUSABLE": "syscall", - "syscall.MADV_FREE_REUSE": "syscall", - "syscall.MADV_HUGEPAGE": "syscall", - "syscall.MADV_HWPOISON": "syscall", - "syscall.MADV_MERGEABLE": "syscall", - "syscall.MADV_NOCORE": "syscall", - "syscall.MADV_NOHUGEPAGE": "syscall", - "syscall.MADV_NORMAL": "syscall", - "syscall.MADV_NOSYNC": "syscall", - "syscall.MADV_PROTECT": "syscall", - "syscall.MADV_RANDOM": "syscall", - "syscall.MADV_REMOVE": "syscall", - "syscall.MADV_SEQUENTIAL": "syscall", - "syscall.MADV_SPACEAVAIL": "syscall", - "syscall.MADV_UNMERGEABLE": "syscall", - "syscall.MADV_WILLNEED": "syscall", - "syscall.MADV_ZERO_WIRED_PAGES": "syscall", - "syscall.MAP_32BIT": "syscall", - "syscall.MAP_ALIGNED_SUPER": "syscall", - "syscall.MAP_ALIGNMENT_16MB": "syscall", - "syscall.MAP_ALIGNMENT_1TB": "syscall", - "syscall.MAP_ALIGNMENT_256TB": "syscall", - "syscall.MAP_ALIGNMENT_4GB": "syscall", - "syscall.MAP_ALIGNMENT_64KB": "syscall", - "syscall.MAP_ALIGNMENT_64PB": "syscall", - "syscall.MAP_ALIGNMENT_MASK": "syscall", - "syscall.MAP_ALIGNMENT_SHIFT": "syscall", - "syscall.MAP_ANON": "syscall", - "syscall.MAP_ANONYMOUS": "syscall", - "syscall.MAP_COPY": "syscall", - "syscall.MAP_DENYWRITE": "syscall", - "syscall.MAP_EXECUTABLE": "syscall", - "syscall.MAP_FILE": "syscall", - "syscall.MAP_FIXED": "syscall", - "syscall.MAP_FLAGMASK": "syscall", - "syscall.MAP_GROWSDOWN": "syscall", - "syscall.MAP_HASSEMAPHORE": "syscall", - "syscall.MAP_HUGETLB": "syscall", - "syscall.MAP_INHERIT": "syscall", - "syscall.MAP_INHERIT_COPY": "syscall", - "syscall.MAP_INHERIT_DEFAULT": "syscall", - "syscall.MAP_INHERIT_DONATE_COPY": "syscall", - "syscall.MAP_INHERIT_NONE": "syscall", - "syscall.MAP_INHERIT_SHARE": "syscall", - "syscall.MAP_JIT": "syscall", - "syscall.MAP_LOCKED": "syscall", - "syscall.MAP_NOCACHE": "syscall", - "syscall.MAP_NOCORE": "syscall", - "syscall.MAP_NOEXTEND": "syscall", - "syscall.MAP_NONBLOCK": "syscall", - "syscall.MAP_NORESERVE": "syscall", - "syscall.MAP_NOSYNC": "syscall", - "syscall.MAP_POPULATE": "syscall", - "syscall.MAP_PREFAULT_READ": "syscall", - "syscall.MAP_PRIVATE": "syscall", - "syscall.MAP_RENAME": "syscall", - "syscall.MAP_RESERVED0080": "syscall", - "syscall.MAP_RESERVED0100": "syscall", - "syscall.MAP_SHARED": "syscall", - "syscall.MAP_STACK": "syscall", - "syscall.MAP_TRYFIXED": "syscall", - "syscall.MAP_TYPE": "syscall", - "syscall.MAP_WIRED": "syscall", - "syscall.MAXIMUM_REPARSE_DATA_BUFFER_SIZE": "syscall", - "syscall.MAXLEN_IFDESCR": "syscall", - "syscall.MAXLEN_PHYSADDR": "syscall", - "syscall.MAX_ADAPTER_ADDRESS_LENGTH": "syscall", - "syscall.MAX_ADAPTER_DESCRIPTION_LENGTH": "syscall", - "syscall.MAX_ADAPTER_NAME_LENGTH": "syscall", - "syscall.MAX_COMPUTERNAME_LENGTH": "syscall", - "syscall.MAX_INTERFACE_NAME_LEN": "syscall", - "syscall.MAX_LONG_PATH": "syscall", - "syscall.MAX_PATH": "syscall", - "syscall.MAX_PROTOCOL_CHAIN": "syscall", - "syscall.MCL_CURRENT": "syscall", - "syscall.MCL_FUTURE": "syscall", - "syscall.MNT_DETACH": "syscall", - "syscall.MNT_EXPIRE": "syscall", - "syscall.MNT_FORCE": "syscall", - "syscall.MSG_BCAST": "syscall", - "syscall.MSG_CMSG_CLOEXEC": "syscall", - "syscall.MSG_COMPAT": "syscall", - "syscall.MSG_CONFIRM": "syscall", - "syscall.MSG_CONTROLMBUF": "syscall", - "syscall.MSG_CTRUNC": "syscall", - "syscall.MSG_DONTROUTE": "syscall", - "syscall.MSG_DONTWAIT": "syscall", - "syscall.MSG_EOF": "syscall", - "syscall.MSG_EOR": "syscall", - "syscall.MSG_ERRQUEUE": "syscall", - "syscall.MSG_FASTOPEN": "syscall", - "syscall.MSG_FIN": "syscall", - "syscall.MSG_FLUSH": "syscall", - "syscall.MSG_HAVEMORE": "syscall", - "syscall.MSG_HOLD": "syscall", - "syscall.MSG_IOVUSRSPACE": "syscall", - "syscall.MSG_LENUSRSPACE": "syscall", - "syscall.MSG_MCAST": "syscall", - "syscall.MSG_MORE": "syscall", - "syscall.MSG_NAMEMBUF": "syscall", - "syscall.MSG_NBIO": "syscall", - "syscall.MSG_NEEDSA": "syscall", - "syscall.MSG_NOSIGNAL": "syscall", - "syscall.MSG_NOTIFICATION": "syscall", - "syscall.MSG_OOB": "syscall", - "syscall.MSG_PEEK": "syscall", - "syscall.MSG_PROXY": "syscall", - "syscall.MSG_RCVMORE": "syscall", - "syscall.MSG_RST": "syscall", - "syscall.MSG_SEND": "syscall", - "syscall.MSG_SYN": "syscall", - "syscall.MSG_TRUNC": "syscall", - "syscall.MSG_TRYHARD": "syscall", - "syscall.MSG_USERFLAGS": "syscall", - "syscall.MSG_WAITALL": "syscall", - "syscall.MSG_WAITFORONE": "syscall", - "syscall.MSG_WAITSTREAM": "syscall", - "syscall.MS_ACTIVE": "syscall", - "syscall.MS_ASYNC": "syscall", - "syscall.MS_BIND": "syscall", - "syscall.MS_DEACTIVATE": "syscall", - "syscall.MS_DIRSYNC": "syscall", - "syscall.MS_INVALIDATE": "syscall", - "syscall.MS_I_VERSION": "syscall", - "syscall.MS_KERNMOUNT": "syscall", - "syscall.MS_KILLPAGES": "syscall", - "syscall.MS_MANDLOCK": "syscall", - "syscall.MS_MGC_MSK": "syscall", - "syscall.MS_MGC_VAL": "syscall", - "syscall.MS_MOVE": "syscall", - "syscall.MS_NOATIME": "syscall", - "syscall.MS_NODEV": "syscall", - "syscall.MS_NODIRATIME": "syscall", - "syscall.MS_NOEXEC": "syscall", - "syscall.MS_NOSUID": "syscall", - "syscall.MS_NOUSER": "syscall", - "syscall.MS_POSIXACL": "syscall", - "syscall.MS_PRIVATE": "syscall", - "syscall.MS_RDONLY": "syscall", - "syscall.MS_REC": "syscall", - "syscall.MS_RELATIME": "syscall", - "syscall.MS_REMOUNT": "syscall", - "syscall.MS_RMT_MASK": "syscall", - "syscall.MS_SHARED": "syscall", - "syscall.MS_SILENT": "syscall", - "syscall.MS_SLAVE": "syscall", - "syscall.MS_STRICTATIME": "syscall", - "syscall.MS_SYNC": "syscall", - "syscall.MS_SYNCHRONOUS": "syscall", - "syscall.MS_UNBINDABLE": "syscall", - "syscall.Madvise": "syscall", - "syscall.MapViewOfFile": "syscall", - "syscall.MaxTokenInfoClass": "syscall", - "syscall.Mclpool": "syscall", - "syscall.MibIfRow": "syscall", - "syscall.Mkdir": "syscall", - "syscall.Mkdirat": "syscall", - "syscall.Mkfifo": "syscall", - "syscall.Mknod": "syscall", - "syscall.Mknodat": "syscall", - "syscall.Mlock": "syscall", - "syscall.Mlockall": "syscall", - "syscall.Mmap": "syscall", - "syscall.Mount": "syscall", - "syscall.MoveFile": "syscall", - "syscall.Mprotect": "syscall", - "syscall.Msghdr": "syscall", - "syscall.Munlock": "syscall", - "syscall.Munlockall": "syscall", - "syscall.Munmap": "syscall", - "syscall.MustLoadDLL": "syscall", - "syscall.NAME_MAX": "syscall", - "syscall.NETLINK_ADD_MEMBERSHIP": "syscall", - "syscall.NETLINK_AUDIT": "syscall", - "syscall.NETLINK_BROADCAST_ERROR": "syscall", - "syscall.NETLINK_CONNECTOR": "syscall", - "syscall.NETLINK_DNRTMSG": "syscall", - "syscall.NETLINK_DROP_MEMBERSHIP": "syscall", - "syscall.NETLINK_ECRYPTFS": "syscall", - "syscall.NETLINK_FIB_LOOKUP": "syscall", - "syscall.NETLINK_FIREWALL": "syscall", - "syscall.NETLINK_GENERIC": "syscall", - "syscall.NETLINK_INET_DIAG": "syscall", - "syscall.NETLINK_IP6_FW": "syscall", - "syscall.NETLINK_ISCSI": "syscall", - "syscall.NETLINK_KOBJECT_UEVENT": "syscall", - "syscall.NETLINK_NETFILTER": "syscall", - "syscall.NETLINK_NFLOG": "syscall", - "syscall.NETLINK_NO_ENOBUFS": "syscall", - "syscall.NETLINK_PKTINFO": "syscall", - "syscall.NETLINK_RDMA": "syscall", - "syscall.NETLINK_ROUTE": "syscall", - "syscall.NETLINK_SCSITRANSPORT": "syscall", - "syscall.NETLINK_SELINUX": "syscall", - "syscall.NETLINK_UNUSED": "syscall", - "syscall.NETLINK_USERSOCK": "syscall", - "syscall.NETLINK_XFRM": "syscall", - "syscall.NET_RT_DUMP": "syscall", - "syscall.NET_RT_DUMP2": "syscall", - "syscall.NET_RT_FLAGS": "syscall", - "syscall.NET_RT_IFLIST": "syscall", - "syscall.NET_RT_IFLIST2": "syscall", - "syscall.NET_RT_IFLISTL": "syscall", - "syscall.NET_RT_IFMALIST": "syscall", - "syscall.NET_RT_MAXID": "syscall", - "syscall.NET_RT_OIFLIST": "syscall", - "syscall.NET_RT_OOIFLIST": "syscall", - "syscall.NET_RT_STAT": "syscall", - "syscall.NET_RT_STATS": "syscall", - "syscall.NET_RT_TABLE": "syscall", - "syscall.NET_RT_TRASH": "syscall", - "syscall.NLA_ALIGNTO": "syscall", - "syscall.NLA_F_NESTED": "syscall", - "syscall.NLA_F_NET_BYTEORDER": "syscall", - "syscall.NLA_HDRLEN": "syscall", - "syscall.NLMSG_ALIGNTO": "syscall", - "syscall.NLMSG_DONE": "syscall", - "syscall.NLMSG_ERROR": "syscall", - "syscall.NLMSG_HDRLEN": "syscall", - "syscall.NLMSG_MIN_TYPE": "syscall", - "syscall.NLMSG_NOOP": "syscall", - "syscall.NLMSG_OVERRUN": "syscall", - "syscall.NLM_F_ACK": "syscall", - "syscall.NLM_F_APPEND": "syscall", - "syscall.NLM_F_ATOMIC": "syscall", - "syscall.NLM_F_CREATE": "syscall", - "syscall.NLM_F_DUMP": "syscall", - "syscall.NLM_F_ECHO": "syscall", - "syscall.NLM_F_EXCL": "syscall", - "syscall.NLM_F_MATCH": "syscall", - "syscall.NLM_F_MULTI": "syscall", - "syscall.NLM_F_REPLACE": "syscall", - "syscall.NLM_F_REQUEST": "syscall", - "syscall.NLM_F_ROOT": "syscall", - "syscall.NOFLSH": "syscall", - "syscall.NOTE_ABSOLUTE": "syscall", - "syscall.NOTE_ATTRIB": "syscall", - "syscall.NOTE_CHILD": "syscall", - "syscall.NOTE_DELETE": "syscall", - "syscall.NOTE_EOF": "syscall", - "syscall.NOTE_EXEC": "syscall", - "syscall.NOTE_EXIT": "syscall", - "syscall.NOTE_EXITSTATUS": "syscall", - "syscall.NOTE_EXTEND": "syscall", - "syscall.NOTE_FFAND": "syscall", - "syscall.NOTE_FFCOPY": "syscall", - "syscall.NOTE_FFCTRLMASK": "syscall", - "syscall.NOTE_FFLAGSMASK": "syscall", - "syscall.NOTE_FFNOP": "syscall", - "syscall.NOTE_FFOR": "syscall", - "syscall.NOTE_FORK": "syscall", - "syscall.NOTE_LINK": "syscall", - "syscall.NOTE_LOWAT": "syscall", - "syscall.NOTE_NONE": "syscall", - "syscall.NOTE_NSECONDS": "syscall", - "syscall.NOTE_PCTRLMASK": "syscall", - "syscall.NOTE_PDATAMASK": "syscall", - "syscall.NOTE_REAP": "syscall", - "syscall.NOTE_RENAME": "syscall", - "syscall.NOTE_RESOURCEEND": "syscall", - "syscall.NOTE_REVOKE": "syscall", - "syscall.NOTE_SECONDS": "syscall", - "syscall.NOTE_SIGNAL": "syscall", - "syscall.NOTE_TRACK": "syscall", - "syscall.NOTE_TRACKERR": "syscall", - "syscall.NOTE_TRIGGER": "syscall", - "syscall.NOTE_TRUNCATE": "syscall", - "syscall.NOTE_USECONDS": "syscall", - "syscall.NOTE_VM_ERROR": "syscall", - "syscall.NOTE_VM_PRESSURE": "syscall", - "syscall.NOTE_VM_PRESSURE_SUDDEN_TERMINATE": "syscall", - "syscall.NOTE_VM_PRESSURE_TERMINATE": "syscall", - "syscall.NOTE_WRITE": "syscall", - "syscall.NameCanonical": "syscall", - "syscall.NameCanonicalEx": "syscall", - "syscall.NameDisplay": "syscall", - "syscall.NameDnsDomain": "syscall", - "syscall.NameFullyQualifiedDN": "syscall", - "syscall.NameSamCompatible": "syscall", - "syscall.NameServicePrincipal": "syscall", - "syscall.NameUniqueId": "syscall", - "syscall.NameUnknown": "syscall", - "syscall.NameUserPrincipal": "syscall", - "syscall.Nanosleep": "syscall", - "syscall.NetApiBufferFree": "syscall", - "syscall.NetGetJoinInformation": "syscall", - "syscall.NetSetupDomainName": "syscall", - "syscall.NetSetupUnjoined": "syscall", - "syscall.NetSetupUnknownStatus": "syscall", - "syscall.NetSetupWorkgroupName": "syscall", - "syscall.NetUserGetInfo": "syscall", - "syscall.NetlinkMessage": "syscall", - "syscall.NetlinkRIB": "syscall", - "syscall.NetlinkRouteAttr": "syscall", - "syscall.NetlinkRouteRequest": "syscall", - "syscall.NewCallback": "syscall", - "syscall.NewCallbackCDecl": "syscall", - "syscall.NewLazyDLL": "syscall", - "syscall.NlAttr": "syscall", - "syscall.NlMsgerr": "syscall", - "syscall.NlMsghdr": "syscall", - "syscall.NsecToFiletime": "syscall", - "syscall.NsecToTimespec": "syscall", - "syscall.NsecToTimeval": "syscall", - "syscall.Ntohs": "syscall", - "syscall.OCRNL": "syscall", - "syscall.OFDEL": "syscall", - "syscall.OFILL": "syscall", - "syscall.OFIOGETBMAP": "syscall", - "syscall.OID_PKIX_KP_SERVER_AUTH": "syscall", - "syscall.OID_SERVER_GATED_CRYPTO": "syscall", - "syscall.OID_SGC_NETSCAPE": "syscall", - "syscall.OLCUC": "syscall", - "syscall.ONLCR": "syscall", - "syscall.ONLRET": "syscall", - "syscall.ONOCR": "syscall", - "syscall.ONOEOT": "syscall", - "syscall.OPEN_ALWAYS": "syscall", - "syscall.OPEN_EXISTING": "syscall", - "syscall.OPOST": "syscall", - "syscall.O_ACCMODE": "syscall", - "syscall.O_ALERT": "syscall", - "syscall.O_ALT_IO": "syscall", - "syscall.O_APPEND": "syscall", - "syscall.O_ASYNC": "syscall", - "syscall.O_CLOEXEC": "syscall", - "syscall.O_CREAT": "syscall", - "syscall.O_DIRECT": "syscall", - "syscall.O_DIRECTORY": "syscall", - "syscall.O_DSYNC": "syscall", - "syscall.O_EVTONLY": "syscall", - "syscall.O_EXCL": "syscall", - "syscall.O_EXEC": "syscall", - "syscall.O_EXLOCK": "syscall", - "syscall.O_FSYNC": "syscall", - "syscall.O_LARGEFILE": "syscall", - "syscall.O_NDELAY": "syscall", - "syscall.O_NOATIME": "syscall", - "syscall.O_NOCTTY": "syscall", - "syscall.O_NOFOLLOW": "syscall", - "syscall.O_NONBLOCK": "syscall", - "syscall.O_NOSIGPIPE": "syscall", - "syscall.O_POPUP": "syscall", - "syscall.O_RDONLY": "syscall", - "syscall.O_RDWR": "syscall", - "syscall.O_RSYNC": "syscall", - "syscall.O_SHLOCK": "syscall", - "syscall.O_SYMLINK": "syscall", - "syscall.O_SYNC": "syscall", - "syscall.O_TRUNC": "syscall", - "syscall.O_TTY_INIT": "syscall", - "syscall.O_WRONLY": "syscall", - "syscall.Open": "syscall", - "syscall.OpenCurrentProcessToken": "syscall", - "syscall.OpenProcess": "syscall", - "syscall.OpenProcessToken": "syscall", - "syscall.Openat": "syscall", - "syscall.Overlapped": "syscall", - "syscall.PACKET_ADD_MEMBERSHIP": "syscall", - "syscall.PACKET_BROADCAST": "syscall", - "syscall.PACKET_DROP_MEMBERSHIP": "syscall", - "syscall.PACKET_FASTROUTE": "syscall", - "syscall.PACKET_HOST": "syscall", - "syscall.PACKET_LOOPBACK": "syscall", - "syscall.PACKET_MR_ALLMULTI": "syscall", - "syscall.PACKET_MR_MULTICAST": "syscall", - "syscall.PACKET_MR_PROMISC": "syscall", - "syscall.PACKET_MULTICAST": "syscall", - "syscall.PACKET_OTHERHOST": "syscall", - "syscall.PACKET_OUTGOING": "syscall", - "syscall.PACKET_RECV_OUTPUT": "syscall", - "syscall.PACKET_RX_RING": "syscall", - "syscall.PACKET_STATISTICS": "syscall", - "syscall.PAGE_EXECUTE_READ": "syscall", - "syscall.PAGE_EXECUTE_READWRITE": "syscall", - "syscall.PAGE_EXECUTE_WRITECOPY": "syscall", - "syscall.PAGE_READONLY": "syscall", - "syscall.PAGE_READWRITE": "syscall", - "syscall.PAGE_WRITECOPY": "syscall", - "syscall.PARENB": "syscall", - "syscall.PARMRK": "syscall", - "syscall.PARODD": "syscall", - "syscall.PENDIN": "syscall", - "syscall.PFL_HIDDEN": "syscall", - "syscall.PFL_MATCHES_PROTOCOL_ZERO": "syscall", - "syscall.PFL_MULTIPLE_PROTO_ENTRIES": "syscall", - "syscall.PFL_NETWORKDIRECT_PROVIDER": "syscall", - "syscall.PFL_RECOMMENDED_PROTO_ENTRY": "syscall", - "syscall.PF_FLUSH": "syscall", - "syscall.PKCS_7_ASN_ENCODING": "syscall", - "syscall.PMC5_PIPELINE_FLUSH": "syscall", - "syscall.PRIO_PGRP": "syscall", - "syscall.PRIO_PROCESS": "syscall", - "syscall.PRIO_USER": "syscall", - "syscall.PRI_IOFLUSH": "syscall", - "syscall.PROCESS_QUERY_INFORMATION": "syscall", - "syscall.PROCESS_TERMINATE": "syscall", - "syscall.PROT_EXEC": "syscall", - "syscall.PROT_GROWSDOWN": "syscall", - "syscall.PROT_GROWSUP": "syscall", - "syscall.PROT_NONE": "syscall", - "syscall.PROT_READ": "syscall", - "syscall.PROT_WRITE": "syscall", - "syscall.PROV_DH_SCHANNEL": "syscall", - "syscall.PROV_DSS": "syscall", - "syscall.PROV_DSS_DH": "syscall", - "syscall.PROV_EC_ECDSA_FULL": "syscall", - "syscall.PROV_EC_ECDSA_SIG": "syscall", - "syscall.PROV_EC_ECNRA_FULL": "syscall", - "syscall.PROV_EC_ECNRA_SIG": "syscall", - "syscall.PROV_FORTEZZA": "syscall", - "syscall.PROV_INTEL_SEC": "syscall", - "syscall.PROV_MS_EXCHANGE": "syscall", - "syscall.PROV_REPLACE_OWF": "syscall", - "syscall.PROV_RNG": "syscall", - "syscall.PROV_RSA_AES": "syscall", - "syscall.PROV_RSA_FULL": "syscall", - "syscall.PROV_RSA_SCHANNEL": "syscall", - "syscall.PROV_RSA_SIG": "syscall", - "syscall.PROV_SPYRUS_LYNKS": "syscall", - "syscall.PROV_SSL": "syscall", - "syscall.PR_CAPBSET_DROP": "syscall", - "syscall.PR_CAPBSET_READ": "syscall", - "syscall.PR_CLEAR_SECCOMP_FILTER": "syscall", - "syscall.PR_ENDIAN_BIG": "syscall", - "syscall.PR_ENDIAN_LITTLE": "syscall", - "syscall.PR_ENDIAN_PPC_LITTLE": "syscall", - "syscall.PR_FPEMU_NOPRINT": "syscall", - "syscall.PR_FPEMU_SIGFPE": "syscall", - "syscall.PR_FP_EXC_ASYNC": "syscall", - "syscall.PR_FP_EXC_DISABLED": "syscall", - "syscall.PR_FP_EXC_DIV": "syscall", - "syscall.PR_FP_EXC_INV": "syscall", - "syscall.PR_FP_EXC_NONRECOV": "syscall", - "syscall.PR_FP_EXC_OVF": "syscall", - "syscall.PR_FP_EXC_PRECISE": "syscall", - "syscall.PR_FP_EXC_RES": "syscall", - "syscall.PR_FP_EXC_SW_ENABLE": "syscall", - "syscall.PR_FP_EXC_UND": "syscall", - "syscall.PR_GET_DUMPABLE": "syscall", - "syscall.PR_GET_ENDIAN": "syscall", - "syscall.PR_GET_FPEMU": "syscall", - "syscall.PR_GET_FPEXC": "syscall", - "syscall.PR_GET_KEEPCAPS": "syscall", - "syscall.PR_GET_NAME": "syscall", - "syscall.PR_GET_PDEATHSIG": "syscall", - "syscall.PR_GET_SECCOMP": "syscall", - "syscall.PR_GET_SECCOMP_FILTER": "syscall", - "syscall.PR_GET_SECUREBITS": "syscall", - "syscall.PR_GET_TIMERSLACK": "syscall", - "syscall.PR_GET_TIMING": "syscall", - "syscall.PR_GET_TSC": "syscall", - "syscall.PR_GET_UNALIGN": "syscall", - "syscall.PR_MCE_KILL": "syscall", - "syscall.PR_MCE_KILL_CLEAR": "syscall", - "syscall.PR_MCE_KILL_DEFAULT": "syscall", - "syscall.PR_MCE_KILL_EARLY": "syscall", - "syscall.PR_MCE_KILL_GET": "syscall", - "syscall.PR_MCE_KILL_LATE": "syscall", - "syscall.PR_MCE_KILL_SET": "syscall", - "syscall.PR_SECCOMP_FILTER_EVENT": "syscall", - "syscall.PR_SECCOMP_FILTER_SYSCALL": "syscall", - "syscall.PR_SET_DUMPABLE": "syscall", - "syscall.PR_SET_ENDIAN": "syscall", - "syscall.PR_SET_FPEMU": "syscall", - "syscall.PR_SET_FPEXC": "syscall", - "syscall.PR_SET_KEEPCAPS": "syscall", - "syscall.PR_SET_NAME": "syscall", - "syscall.PR_SET_PDEATHSIG": "syscall", - "syscall.PR_SET_PTRACER": "syscall", - "syscall.PR_SET_SECCOMP": "syscall", - "syscall.PR_SET_SECCOMP_FILTER": "syscall", - "syscall.PR_SET_SECUREBITS": "syscall", - "syscall.PR_SET_TIMERSLACK": "syscall", - "syscall.PR_SET_TIMING": "syscall", - "syscall.PR_SET_TSC": "syscall", - "syscall.PR_SET_UNALIGN": "syscall", - "syscall.PR_TASK_PERF_EVENTS_DISABLE": "syscall", - "syscall.PR_TASK_PERF_EVENTS_ENABLE": "syscall", - "syscall.PR_TIMING_STATISTICAL": "syscall", - "syscall.PR_TIMING_TIMESTAMP": "syscall", - "syscall.PR_TSC_ENABLE": "syscall", - "syscall.PR_TSC_SIGSEGV": "syscall", - "syscall.PR_UNALIGN_NOPRINT": "syscall", - "syscall.PR_UNALIGN_SIGBUS": "syscall", - "syscall.PTRACE_ARCH_PRCTL": "syscall", - "syscall.PTRACE_ATTACH": "syscall", - "syscall.PTRACE_CONT": "syscall", - "syscall.PTRACE_DETACH": "syscall", - "syscall.PTRACE_EVENT_CLONE": "syscall", - "syscall.PTRACE_EVENT_EXEC": "syscall", - "syscall.PTRACE_EVENT_EXIT": "syscall", - "syscall.PTRACE_EVENT_FORK": "syscall", - "syscall.PTRACE_EVENT_VFORK": "syscall", - "syscall.PTRACE_EVENT_VFORK_DONE": "syscall", - "syscall.PTRACE_GETCRUNCHREGS": "syscall", - "syscall.PTRACE_GETEVENTMSG": "syscall", - "syscall.PTRACE_GETFPREGS": "syscall", - "syscall.PTRACE_GETFPXREGS": "syscall", - "syscall.PTRACE_GETHBPREGS": "syscall", - "syscall.PTRACE_GETREGS": "syscall", - "syscall.PTRACE_GETREGSET": "syscall", - "syscall.PTRACE_GETSIGINFO": "syscall", - "syscall.PTRACE_GETVFPREGS": "syscall", - "syscall.PTRACE_GETWMMXREGS": "syscall", - "syscall.PTRACE_GET_THREAD_AREA": "syscall", - "syscall.PTRACE_KILL": "syscall", - "syscall.PTRACE_OLDSETOPTIONS": "syscall", - "syscall.PTRACE_O_MASK": "syscall", - "syscall.PTRACE_O_TRACECLONE": "syscall", - "syscall.PTRACE_O_TRACEEXEC": "syscall", - "syscall.PTRACE_O_TRACEEXIT": "syscall", - "syscall.PTRACE_O_TRACEFORK": "syscall", - "syscall.PTRACE_O_TRACESYSGOOD": "syscall", - "syscall.PTRACE_O_TRACEVFORK": "syscall", - "syscall.PTRACE_O_TRACEVFORKDONE": "syscall", - "syscall.PTRACE_PEEKDATA": "syscall", - "syscall.PTRACE_PEEKTEXT": "syscall", - "syscall.PTRACE_PEEKUSR": "syscall", - "syscall.PTRACE_POKEDATA": "syscall", - "syscall.PTRACE_POKETEXT": "syscall", - "syscall.PTRACE_POKEUSR": "syscall", - "syscall.PTRACE_SETCRUNCHREGS": "syscall", - "syscall.PTRACE_SETFPREGS": "syscall", - "syscall.PTRACE_SETFPXREGS": "syscall", - "syscall.PTRACE_SETHBPREGS": "syscall", - "syscall.PTRACE_SETOPTIONS": "syscall", - "syscall.PTRACE_SETREGS": "syscall", - "syscall.PTRACE_SETREGSET": "syscall", - "syscall.PTRACE_SETSIGINFO": "syscall", - "syscall.PTRACE_SETVFPREGS": "syscall", - "syscall.PTRACE_SETWMMXREGS": "syscall", - "syscall.PTRACE_SET_SYSCALL": "syscall", - "syscall.PTRACE_SET_THREAD_AREA": "syscall", - "syscall.PTRACE_SINGLEBLOCK": "syscall", - "syscall.PTRACE_SINGLESTEP": "syscall", - "syscall.PTRACE_SYSCALL": "syscall", - "syscall.PTRACE_SYSEMU": "syscall", - "syscall.PTRACE_SYSEMU_SINGLESTEP": "syscall", - "syscall.PTRACE_TRACEME": "syscall", - "syscall.PT_ATTACH": "syscall", - "syscall.PT_ATTACHEXC": "syscall", - "syscall.PT_CONTINUE": "syscall", - "syscall.PT_DATA_ADDR": "syscall", - "syscall.PT_DENY_ATTACH": "syscall", - "syscall.PT_DETACH": "syscall", - "syscall.PT_FIRSTMACH": "syscall", - "syscall.PT_FORCEQUOTA": "syscall", - "syscall.PT_KILL": "syscall", - "syscall.PT_MASK": "syscall", - "syscall.PT_READ_D": "syscall", - "syscall.PT_READ_I": "syscall", - "syscall.PT_READ_U": "syscall", - "syscall.PT_SIGEXC": "syscall", - "syscall.PT_STEP": "syscall", - "syscall.PT_TEXT_ADDR": "syscall", - "syscall.PT_TEXT_END_ADDR": "syscall", - "syscall.PT_THUPDATE": "syscall", - "syscall.PT_TRACE_ME": "syscall", - "syscall.PT_WRITE_D": "syscall", - "syscall.PT_WRITE_I": "syscall", - "syscall.PT_WRITE_U": "syscall", - "syscall.ParseDirent": "syscall", - "syscall.ParseNetlinkMessage": "syscall", - "syscall.ParseNetlinkRouteAttr": "syscall", - "syscall.ParseRoutingMessage": "syscall", - "syscall.ParseRoutingSockaddr": "syscall", - "syscall.ParseSocketControlMessage": "syscall", - "syscall.ParseUnixCredentials": "syscall", - "syscall.ParseUnixRights": "syscall", - "syscall.PathMax": "syscall", - "syscall.Pathconf": "syscall", - "syscall.Pause": "syscall", - "syscall.Pipe": "syscall", - "syscall.Pipe2": "syscall", - "syscall.PivotRoot": "syscall", - "syscall.PostQueuedCompletionStatus": "syscall", - "syscall.Pread": "syscall", - "syscall.Proc": "syscall", - "syscall.ProcAttr": "syscall", - "syscall.Process32First": "syscall", - "syscall.Process32Next": "syscall", - "syscall.ProcessEntry32": "syscall", - "syscall.ProcessInformation": "syscall", - "syscall.Protoent": "syscall", - "syscall.PtraceAttach": "syscall", - "syscall.PtraceCont": "syscall", - "syscall.PtraceDetach": "syscall", - "syscall.PtraceGetEventMsg": "syscall", - "syscall.PtraceGetRegs": "syscall", - "syscall.PtracePeekData": "syscall", - "syscall.PtracePeekText": "syscall", - "syscall.PtracePokeData": "syscall", - "syscall.PtracePokeText": "syscall", - "syscall.PtraceRegs": "syscall", - "syscall.PtraceSetOptions": "syscall", - "syscall.PtraceSetRegs": "syscall", - "syscall.PtraceSingleStep": "syscall", - "syscall.PtraceSyscall": "syscall", - "syscall.Pwrite": "syscall", - "syscall.REG_BINARY": "syscall", - "syscall.REG_DWORD": "syscall", - "syscall.REG_DWORD_BIG_ENDIAN": "syscall", - "syscall.REG_DWORD_LITTLE_ENDIAN": "syscall", - "syscall.REG_EXPAND_SZ": "syscall", - "syscall.REG_FULL_RESOURCE_DESCRIPTOR": "syscall", - "syscall.REG_LINK": "syscall", - "syscall.REG_MULTI_SZ": "syscall", - "syscall.REG_NONE": "syscall", - "syscall.REG_QWORD": "syscall", - "syscall.REG_QWORD_LITTLE_ENDIAN": "syscall", - "syscall.REG_RESOURCE_LIST": "syscall", - "syscall.REG_RESOURCE_REQUIREMENTS_LIST": "syscall", - "syscall.REG_SZ": "syscall", - "syscall.RLIMIT_AS": "syscall", - "syscall.RLIMIT_CORE": "syscall", - "syscall.RLIMIT_CPU": "syscall", - "syscall.RLIMIT_DATA": "syscall", - "syscall.RLIMIT_FSIZE": "syscall", - "syscall.RLIMIT_NOFILE": "syscall", - "syscall.RLIMIT_STACK": "syscall", - "syscall.RLIM_INFINITY": "syscall", - "syscall.RTAX_ADVMSS": "syscall", - "syscall.RTAX_AUTHOR": "syscall", - "syscall.RTAX_BRD": "syscall", - "syscall.RTAX_CWND": "syscall", - "syscall.RTAX_DST": "syscall", - "syscall.RTAX_FEATURES": "syscall", - "syscall.RTAX_FEATURE_ALLFRAG": "syscall", - "syscall.RTAX_FEATURE_ECN": "syscall", - "syscall.RTAX_FEATURE_SACK": "syscall", - "syscall.RTAX_FEATURE_TIMESTAMP": "syscall", - "syscall.RTAX_GATEWAY": "syscall", - "syscall.RTAX_GENMASK": "syscall", - "syscall.RTAX_HOPLIMIT": "syscall", - "syscall.RTAX_IFA": "syscall", - "syscall.RTAX_IFP": "syscall", - "syscall.RTAX_INITCWND": "syscall", - "syscall.RTAX_INITRWND": "syscall", - "syscall.RTAX_LABEL": "syscall", - "syscall.RTAX_LOCK": "syscall", - "syscall.RTAX_MAX": "syscall", - "syscall.RTAX_MTU": "syscall", - "syscall.RTAX_NETMASK": "syscall", - "syscall.RTAX_REORDERING": "syscall", - "syscall.RTAX_RTO_MIN": "syscall", - "syscall.RTAX_RTT": "syscall", - "syscall.RTAX_RTTVAR": "syscall", - "syscall.RTAX_SRC": "syscall", - "syscall.RTAX_SRCMASK": "syscall", - "syscall.RTAX_SSTHRESH": "syscall", - "syscall.RTAX_TAG": "syscall", - "syscall.RTAX_UNSPEC": "syscall", - "syscall.RTAX_WINDOW": "syscall", - "syscall.RTA_ALIGNTO": "syscall", - "syscall.RTA_AUTHOR": "syscall", - "syscall.RTA_BRD": "syscall", - "syscall.RTA_CACHEINFO": "syscall", - "syscall.RTA_DST": "syscall", - "syscall.RTA_FLOW": "syscall", - "syscall.RTA_GATEWAY": "syscall", - "syscall.RTA_GENMASK": "syscall", - "syscall.RTA_IFA": "syscall", - "syscall.RTA_IFP": "syscall", - "syscall.RTA_IIF": "syscall", - "syscall.RTA_LABEL": "syscall", - "syscall.RTA_MAX": "syscall", - "syscall.RTA_METRICS": "syscall", - "syscall.RTA_MULTIPATH": "syscall", - "syscall.RTA_NETMASK": "syscall", - "syscall.RTA_OIF": "syscall", - "syscall.RTA_PREFSRC": "syscall", - "syscall.RTA_PRIORITY": "syscall", - "syscall.RTA_SRC": "syscall", - "syscall.RTA_SRCMASK": "syscall", - "syscall.RTA_TABLE": "syscall", - "syscall.RTA_TAG": "syscall", - "syscall.RTA_UNSPEC": "syscall", - "syscall.RTCF_DIRECTSRC": "syscall", - "syscall.RTCF_DOREDIRECT": "syscall", - "syscall.RTCF_LOG": "syscall", - "syscall.RTCF_MASQ": "syscall", - "syscall.RTCF_NAT": "syscall", - "syscall.RTCF_VALVE": "syscall", - "syscall.RTF_ADDRCLASSMASK": "syscall", - "syscall.RTF_ADDRCONF": "syscall", - "syscall.RTF_ALLONLINK": "syscall", - "syscall.RTF_ANNOUNCE": "syscall", - "syscall.RTF_BLACKHOLE": "syscall", - "syscall.RTF_BROADCAST": "syscall", - "syscall.RTF_CACHE": "syscall", - "syscall.RTF_CLONED": "syscall", - "syscall.RTF_CLONING": "syscall", - "syscall.RTF_CONDEMNED": "syscall", - "syscall.RTF_DEFAULT": "syscall", - "syscall.RTF_DELCLONE": "syscall", - "syscall.RTF_DONE": "syscall", - "syscall.RTF_DYNAMIC": "syscall", - "syscall.RTF_FLOW": "syscall", - "syscall.RTF_FMASK": "syscall", - "syscall.RTF_GATEWAY": "syscall", - "syscall.RTF_GWFLAG_COMPAT": "syscall", - "syscall.RTF_HOST": "syscall", - "syscall.RTF_IFREF": "syscall", - "syscall.RTF_IFSCOPE": "syscall", - "syscall.RTF_INTERFACE": "syscall", - "syscall.RTF_IRTT": "syscall", - "syscall.RTF_LINKRT": "syscall", - "syscall.RTF_LLDATA": "syscall", - "syscall.RTF_LLINFO": "syscall", - "syscall.RTF_LOCAL": "syscall", - "syscall.RTF_MASK": "syscall", - "syscall.RTF_MODIFIED": "syscall", - "syscall.RTF_MPATH": "syscall", - "syscall.RTF_MPLS": "syscall", - "syscall.RTF_MSS": "syscall", - "syscall.RTF_MTU": "syscall", - "syscall.RTF_MULTICAST": "syscall", - "syscall.RTF_NAT": "syscall", - "syscall.RTF_NOFORWARD": "syscall", - "syscall.RTF_NONEXTHOP": "syscall", - "syscall.RTF_NOPMTUDISC": "syscall", - "syscall.RTF_PERMANENT_ARP": "syscall", - "syscall.RTF_PINNED": "syscall", - "syscall.RTF_POLICY": "syscall", - "syscall.RTF_PRCLONING": "syscall", - "syscall.RTF_PROTO1": "syscall", - "syscall.RTF_PROTO2": "syscall", - "syscall.RTF_PROTO3": "syscall", - "syscall.RTF_REINSTATE": "syscall", - "syscall.RTF_REJECT": "syscall", - "syscall.RTF_RNH_LOCKED": "syscall", - "syscall.RTF_SOURCE": "syscall", - "syscall.RTF_SRC": "syscall", - "syscall.RTF_STATIC": "syscall", - "syscall.RTF_STICKY": "syscall", - "syscall.RTF_THROW": "syscall", - "syscall.RTF_TUNNEL": "syscall", - "syscall.RTF_UP": "syscall", - "syscall.RTF_USETRAILERS": "syscall", - "syscall.RTF_WASCLONED": "syscall", - "syscall.RTF_WINDOW": "syscall", - "syscall.RTF_XRESOLVE": "syscall", - "syscall.RTM_ADD": "syscall", - "syscall.RTM_BASE": "syscall", - "syscall.RTM_CHANGE": "syscall", - "syscall.RTM_CHGADDR": "syscall", - "syscall.RTM_DELACTION": "syscall", - "syscall.RTM_DELADDR": "syscall", - "syscall.RTM_DELADDRLABEL": "syscall", - "syscall.RTM_DELETE": "syscall", - "syscall.RTM_DELLINK": "syscall", - "syscall.RTM_DELMADDR": "syscall", - "syscall.RTM_DELNEIGH": "syscall", - "syscall.RTM_DELQDISC": "syscall", - "syscall.RTM_DELROUTE": "syscall", - "syscall.RTM_DELRULE": "syscall", - "syscall.RTM_DELTCLASS": "syscall", - "syscall.RTM_DELTFILTER": "syscall", - "syscall.RTM_DESYNC": "syscall", - "syscall.RTM_F_CLONED": "syscall", - "syscall.RTM_F_EQUALIZE": "syscall", - "syscall.RTM_F_NOTIFY": "syscall", - "syscall.RTM_F_PREFIX": "syscall", - "syscall.RTM_GET": "syscall", - "syscall.RTM_GET2": "syscall", - "syscall.RTM_GETACTION": "syscall", - "syscall.RTM_GETADDR": "syscall", - "syscall.RTM_GETADDRLABEL": "syscall", - "syscall.RTM_GETANYCAST": "syscall", - "syscall.RTM_GETDCB": "syscall", - "syscall.RTM_GETLINK": "syscall", - "syscall.RTM_GETMULTICAST": "syscall", - "syscall.RTM_GETNEIGH": "syscall", - "syscall.RTM_GETNEIGHTBL": "syscall", - "syscall.RTM_GETQDISC": "syscall", - "syscall.RTM_GETROUTE": "syscall", - "syscall.RTM_GETRULE": "syscall", - "syscall.RTM_GETTCLASS": "syscall", - "syscall.RTM_GETTFILTER": "syscall", - "syscall.RTM_IEEE80211": "syscall", - "syscall.RTM_IFANNOUNCE": "syscall", - "syscall.RTM_IFINFO": "syscall", - "syscall.RTM_IFINFO2": "syscall", - "syscall.RTM_LLINFO_UPD": "syscall", - "syscall.RTM_LOCK": "syscall", - "syscall.RTM_LOSING": "syscall", - "syscall.RTM_MAX": "syscall", - "syscall.RTM_MAXSIZE": "syscall", - "syscall.RTM_MISS": "syscall", - "syscall.RTM_NEWACTION": "syscall", - "syscall.RTM_NEWADDR": "syscall", - "syscall.RTM_NEWADDRLABEL": "syscall", - "syscall.RTM_NEWLINK": "syscall", - "syscall.RTM_NEWMADDR": "syscall", - "syscall.RTM_NEWMADDR2": "syscall", - "syscall.RTM_NEWNDUSEROPT": "syscall", - "syscall.RTM_NEWNEIGH": "syscall", - "syscall.RTM_NEWNEIGHTBL": "syscall", - "syscall.RTM_NEWPREFIX": "syscall", - "syscall.RTM_NEWQDISC": "syscall", - "syscall.RTM_NEWROUTE": "syscall", - "syscall.RTM_NEWRULE": "syscall", - "syscall.RTM_NEWTCLASS": "syscall", - "syscall.RTM_NEWTFILTER": "syscall", - "syscall.RTM_NR_FAMILIES": "syscall", - "syscall.RTM_NR_MSGTYPES": "syscall", - "syscall.RTM_OIFINFO": "syscall", - "syscall.RTM_OLDADD": "syscall", - "syscall.RTM_OLDDEL": "syscall", - "syscall.RTM_OOIFINFO": "syscall", - "syscall.RTM_REDIRECT": "syscall", - "syscall.RTM_RESOLVE": "syscall", - "syscall.RTM_RTTUNIT": "syscall", - "syscall.RTM_SETDCB": "syscall", - "syscall.RTM_SETGATE": "syscall", - "syscall.RTM_SETLINK": "syscall", - "syscall.RTM_SETNEIGHTBL": "syscall", - "syscall.RTM_VERSION": "syscall", - "syscall.RTNH_ALIGNTO": "syscall", - "syscall.RTNH_F_DEAD": "syscall", - "syscall.RTNH_F_ONLINK": "syscall", - "syscall.RTNH_F_PERVASIVE": "syscall", - "syscall.RTNLGRP_IPV4_IFADDR": "syscall", - "syscall.RTNLGRP_IPV4_MROUTE": "syscall", - "syscall.RTNLGRP_IPV4_ROUTE": "syscall", - "syscall.RTNLGRP_IPV4_RULE": "syscall", - "syscall.RTNLGRP_IPV6_IFADDR": "syscall", - "syscall.RTNLGRP_IPV6_IFINFO": "syscall", - "syscall.RTNLGRP_IPV6_MROUTE": "syscall", - "syscall.RTNLGRP_IPV6_PREFIX": "syscall", - "syscall.RTNLGRP_IPV6_ROUTE": "syscall", - "syscall.RTNLGRP_IPV6_RULE": "syscall", - "syscall.RTNLGRP_LINK": "syscall", - "syscall.RTNLGRP_ND_USEROPT": "syscall", - "syscall.RTNLGRP_NEIGH": "syscall", - "syscall.RTNLGRP_NONE": "syscall", - "syscall.RTNLGRP_NOTIFY": "syscall", - "syscall.RTNLGRP_TC": "syscall", - "syscall.RTN_ANYCAST": "syscall", - "syscall.RTN_BLACKHOLE": "syscall", - "syscall.RTN_BROADCAST": "syscall", - "syscall.RTN_LOCAL": "syscall", - "syscall.RTN_MAX": "syscall", - "syscall.RTN_MULTICAST": "syscall", - "syscall.RTN_NAT": "syscall", - "syscall.RTN_PROHIBIT": "syscall", - "syscall.RTN_THROW": "syscall", - "syscall.RTN_UNICAST": "syscall", - "syscall.RTN_UNREACHABLE": "syscall", - "syscall.RTN_UNSPEC": "syscall", - "syscall.RTN_XRESOLVE": "syscall", - "syscall.RTPROT_BIRD": "syscall", - "syscall.RTPROT_BOOT": "syscall", - "syscall.RTPROT_DHCP": "syscall", - "syscall.RTPROT_DNROUTED": "syscall", - "syscall.RTPROT_GATED": "syscall", - "syscall.RTPROT_KERNEL": "syscall", - "syscall.RTPROT_MRT": "syscall", - "syscall.RTPROT_NTK": "syscall", - "syscall.RTPROT_RA": "syscall", - "syscall.RTPROT_REDIRECT": "syscall", - "syscall.RTPROT_STATIC": "syscall", - "syscall.RTPROT_UNSPEC": "syscall", - "syscall.RTPROT_XORP": "syscall", - "syscall.RTPROT_ZEBRA": "syscall", - "syscall.RTV_EXPIRE": "syscall", - "syscall.RTV_HOPCOUNT": "syscall", - "syscall.RTV_MTU": "syscall", - "syscall.RTV_RPIPE": "syscall", - "syscall.RTV_RTT": "syscall", - "syscall.RTV_RTTVAR": "syscall", - "syscall.RTV_SPIPE": "syscall", - "syscall.RTV_SSTHRESH": "syscall", - "syscall.RTV_WEIGHT": "syscall", - "syscall.RT_CACHING_CONTEXT": "syscall", - "syscall.RT_CLASS_DEFAULT": "syscall", - "syscall.RT_CLASS_LOCAL": "syscall", - "syscall.RT_CLASS_MAIN": "syscall", - "syscall.RT_CLASS_MAX": "syscall", - "syscall.RT_CLASS_UNSPEC": "syscall", - "syscall.RT_DEFAULT_FIB": "syscall", - "syscall.RT_NORTREF": "syscall", - "syscall.RT_SCOPE_HOST": "syscall", - "syscall.RT_SCOPE_LINK": "syscall", - "syscall.RT_SCOPE_NOWHERE": "syscall", - "syscall.RT_SCOPE_SITE": "syscall", - "syscall.RT_SCOPE_UNIVERSE": "syscall", - "syscall.RT_TABLEID_MAX": "syscall", - "syscall.RT_TABLE_COMPAT": "syscall", - "syscall.RT_TABLE_DEFAULT": "syscall", - "syscall.RT_TABLE_LOCAL": "syscall", - "syscall.RT_TABLE_MAIN": "syscall", - "syscall.RT_TABLE_MAX": "syscall", - "syscall.RT_TABLE_UNSPEC": "syscall", - "syscall.RUSAGE_CHILDREN": "syscall", - "syscall.RUSAGE_SELF": "syscall", - "syscall.RUSAGE_THREAD": "syscall", - "syscall.Radvisory_t": "syscall", - "syscall.RawSockaddr": "syscall", - "syscall.RawSockaddrAny": "syscall", - "syscall.RawSockaddrDatalink": "syscall", - "syscall.RawSockaddrInet4": "syscall", - "syscall.RawSockaddrInet6": "syscall", - "syscall.RawSockaddrLinklayer": "syscall", - "syscall.RawSockaddrNetlink": "syscall", - "syscall.RawSockaddrUnix": "syscall", - "syscall.RawSyscall": "syscall", - "syscall.RawSyscall6": "syscall", - "syscall.Read": "syscall", - "syscall.ReadConsole": "syscall", - "syscall.ReadDirectoryChanges": "syscall", - "syscall.ReadDirent": "syscall", - "syscall.ReadFile": "syscall", - "syscall.Readlink": "syscall", - "syscall.Reboot": "syscall", - "syscall.Recvfrom": "syscall", - "syscall.Recvmsg": "syscall", - "syscall.RegCloseKey": "syscall", - "syscall.RegEnumKeyEx": "syscall", - "syscall.RegOpenKeyEx": "syscall", - "syscall.RegQueryInfoKey": "syscall", - "syscall.RegQueryValueEx": "syscall", - "syscall.RemoveDirectory": "syscall", - "syscall.Removexattr": "syscall", - "syscall.Rename": "syscall", - "syscall.Renameat": "syscall", - "syscall.Revoke": "syscall", - "syscall.Rlimit": "syscall", - "syscall.Rmdir": "syscall", - "syscall.RouteMessage": "syscall", - "syscall.RouteRIB": "syscall", - "syscall.RtAttr": "syscall", - "syscall.RtGenmsg": "syscall", - "syscall.RtMetrics": "syscall", - "syscall.RtMsg": "syscall", - "syscall.RtMsghdr": "syscall", - "syscall.RtNexthop": "syscall", - "syscall.Rusage": "syscall", - "syscall.SCM_BINTIME": "syscall", - "syscall.SCM_CREDENTIALS": "syscall", - "syscall.SCM_CREDS": "syscall", - "syscall.SCM_RIGHTS": "syscall", - "syscall.SCM_TIMESTAMP": "syscall", - "syscall.SCM_TIMESTAMPING": "syscall", - "syscall.SCM_TIMESTAMPNS": "syscall", - "syscall.SCM_TIMESTAMP_MONOTONIC": "syscall", - "syscall.SHUT_RD": "syscall", - "syscall.SHUT_RDWR": "syscall", - "syscall.SHUT_WR": "syscall", - "syscall.SID": "syscall", - "syscall.SIDAndAttributes": "syscall", - "syscall.SIGABRT": "syscall", - "syscall.SIGALRM": "syscall", - "syscall.SIGBUS": "syscall", - "syscall.SIGCHLD": "syscall", - "syscall.SIGCLD": "syscall", - "syscall.SIGCONT": "syscall", - "syscall.SIGEMT": "syscall", - "syscall.SIGFPE": "syscall", - "syscall.SIGHUP": "syscall", - "syscall.SIGILL": "syscall", - "syscall.SIGINFO": "syscall", - "syscall.SIGINT": "syscall", - "syscall.SIGIO": "syscall", - "syscall.SIGIOT": "syscall", - "syscall.SIGKILL": "syscall", - "syscall.SIGLIBRT": "syscall", - "syscall.SIGLWP": "syscall", - "syscall.SIGPIPE": "syscall", - "syscall.SIGPOLL": "syscall", - "syscall.SIGPROF": "syscall", - "syscall.SIGPWR": "syscall", - "syscall.SIGQUIT": "syscall", - "syscall.SIGSEGV": "syscall", - "syscall.SIGSTKFLT": "syscall", - "syscall.SIGSTOP": "syscall", - "syscall.SIGSYS": "syscall", - "syscall.SIGTERM": "syscall", - "syscall.SIGTHR": "syscall", - "syscall.SIGTRAP": "syscall", - "syscall.SIGTSTP": "syscall", - "syscall.SIGTTIN": "syscall", - "syscall.SIGTTOU": "syscall", - "syscall.SIGUNUSED": "syscall", - "syscall.SIGURG": "syscall", - "syscall.SIGUSR1": "syscall", - "syscall.SIGUSR2": "syscall", - "syscall.SIGVTALRM": "syscall", - "syscall.SIGWINCH": "syscall", - "syscall.SIGXCPU": "syscall", - "syscall.SIGXFSZ": "syscall", - "syscall.SIOCADDDLCI": "syscall", - "syscall.SIOCADDMULTI": "syscall", - "syscall.SIOCADDRT": "syscall", - "syscall.SIOCAIFADDR": "syscall", - "syscall.SIOCAIFGROUP": "syscall", - "syscall.SIOCALIFADDR": "syscall", - "syscall.SIOCARPIPLL": "syscall", - "syscall.SIOCATMARK": "syscall", - "syscall.SIOCAUTOADDR": "syscall", - "syscall.SIOCAUTONETMASK": "syscall", - "syscall.SIOCBRDGADD": "syscall", - "syscall.SIOCBRDGADDS": "syscall", - "syscall.SIOCBRDGARL": "syscall", - "syscall.SIOCBRDGDADDR": "syscall", - "syscall.SIOCBRDGDEL": "syscall", - "syscall.SIOCBRDGDELS": "syscall", - "syscall.SIOCBRDGFLUSH": "syscall", - "syscall.SIOCBRDGFRL": "syscall", - "syscall.SIOCBRDGGCACHE": "syscall", - "syscall.SIOCBRDGGFD": "syscall", - "syscall.SIOCBRDGGHT": "syscall", - "syscall.SIOCBRDGGIFFLGS": "syscall", - "syscall.SIOCBRDGGMA": "syscall", - "syscall.SIOCBRDGGPARAM": "syscall", - "syscall.SIOCBRDGGPRI": "syscall", - "syscall.SIOCBRDGGRL": "syscall", - "syscall.SIOCBRDGGSIFS": "syscall", - "syscall.SIOCBRDGGTO": "syscall", - "syscall.SIOCBRDGIFS": "syscall", - "syscall.SIOCBRDGRTS": "syscall", - "syscall.SIOCBRDGSADDR": "syscall", - "syscall.SIOCBRDGSCACHE": "syscall", - "syscall.SIOCBRDGSFD": "syscall", - "syscall.SIOCBRDGSHT": "syscall", - "syscall.SIOCBRDGSIFCOST": "syscall", - "syscall.SIOCBRDGSIFFLGS": "syscall", - "syscall.SIOCBRDGSIFPRIO": "syscall", - "syscall.SIOCBRDGSMA": "syscall", - "syscall.SIOCBRDGSPRI": "syscall", - "syscall.SIOCBRDGSPROTO": "syscall", - "syscall.SIOCBRDGSTO": "syscall", - "syscall.SIOCBRDGSTXHC": "syscall", - "syscall.SIOCDARP": "syscall", - "syscall.SIOCDELDLCI": "syscall", - "syscall.SIOCDELMULTI": "syscall", - "syscall.SIOCDELRT": "syscall", - "syscall.SIOCDEVPRIVATE": "syscall", - "syscall.SIOCDIFADDR": "syscall", - "syscall.SIOCDIFGROUP": "syscall", - "syscall.SIOCDIFPHYADDR": "syscall", - "syscall.SIOCDLIFADDR": "syscall", - "syscall.SIOCDRARP": "syscall", - "syscall.SIOCGARP": "syscall", - "syscall.SIOCGDRVSPEC": "syscall", - "syscall.SIOCGETKALIVE": "syscall", - "syscall.SIOCGETLABEL": "syscall", - "syscall.SIOCGETPFLOW": "syscall", - "syscall.SIOCGETPFSYNC": "syscall", - "syscall.SIOCGETSGCNT": "syscall", - "syscall.SIOCGETVIFCNT": "syscall", - "syscall.SIOCGETVLAN": "syscall", - "syscall.SIOCGHIWAT": "syscall", - "syscall.SIOCGIFADDR": "syscall", - "syscall.SIOCGIFADDRPREF": "syscall", - "syscall.SIOCGIFALIAS": "syscall", - "syscall.SIOCGIFALTMTU": "syscall", - "syscall.SIOCGIFASYNCMAP": "syscall", - "syscall.SIOCGIFBOND": "syscall", - "syscall.SIOCGIFBR": "syscall", - "syscall.SIOCGIFBRDADDR": "syscall", - "syscall.SIOCGIFCAP": "syscall", - "syscall.SIOCGIFCONF": "syscall", - "syscall.SIOCGIFCOUNT": "syscall", - "syscall.SIOCGIFDATA": "syscall", - "syscall.SIOCGIFDESCR": "syscall", - "syscall.SIOCGIFDEVMTU": "syscall", - "syscall.SIOCGIFDLT": "syscall", - "syscall.SIOCGIFDSTADDR": "syscall", - "syscall.SIOCGIFENCAP": "syscall", - "syscall.SIOCGIFFIB": "syscall", - "syscall.SIOCGIFFLAGS": "syscall", - "syscall.SIOCGIFGATTR": "syscall", - "syscall.SIOCGIFGENERIC": "syscall", - "syscall.SIOCGIFGMEMB": "syscall", - "syscall.SIOCGIFGROUP": "syscall", - "syscall.SIOCGIFHARDMTU": "syscall", - "syscall.SIOCGIFHWADDR": "syscall", - "syscall.SIOCGIFINDEX": "syscall", - "syscall.SIOCGIFKPI": "syscall", - "syscall.SIOCGIFMAC": "syscall", - "syscall.SIOCGIFMAP": "syscall", - "syscall.SIOCGIFMEDIA": "syscall", - "syscall.SIOCGIFMEM": "syscall", - "syscall.SIOCGIFMETRIC": "syscall", - "syscall.SIOCGIFMTU": "syscall", - "syscall.SIOCGIFNAME": "syscall", - "syscall.SIOCGIFNETMASK": "syscall", - "syscall.SIOCGIFPDSTADDR": "syscall", - "syscall.SIOCGIFPFLAGS": "syscall", - "syscall.SIOCGIFPHYS": "syscall", - "syscall.SIOCGIFPRIORITY": "syscall", - "syscall.SIOCGIFPSRCADDR": "syscall", - "syscall.SIOCGIFRDOMAIN": "syscall", - "syscall.SIOCGIFRTLABEL": "syscall", - "syscall.SIOCGIFSLAVE": "syscall", - "syscall.SIOCGIFSTATUS": "syscall", - "syscall.SIOCGIFTIMESLOT": "syscall", - "syscall.SIOCGIFTXQLEN": "syscall", - "syscall.SIOCGIFVLAN": "syscall", - "syscall.SIOCGIFWAKEFLAGS": "syscall", - "syscall.SIOCGIFXFLAGS": "syscall", - "syscall.SIOCGLIFADDR": "syscall", - "syscall.SIOCGLIFPHYADDR": "syscall", - "syscall.SIOCGLIFPHYRTABLE": "syscall", - "syscall.SIOCGLIFPHYTTL": "syscall", - "syscall.SIOCGLINKSTR": "syscall", - "syscall.SIOCGLOWAT": "syscall", - "syscall.SIOCGPGRP": "syscall", - "syscall.SIOCGPRIVATE_0": "syscall", - "syscall.SIOCGPRIVATE_1": "syscall", - "syscall.SIOCGRARP": "syscall", - "syscall.SIOCGSPPPPARAMS": "syscall", - "syscall.SIOCGSTAMP": "syscall", - "syscall.SIOCGSTAMPNS": "syscall", - "syscall.SIOCGVH": "syscall", - "syscall.SIOCGVNETID": "syscall", - "syscall.SIOCIFCREATE": "syscall", - "syscall.SIOCIFCREATE2": "syscall", - "syscall.SIOCIFDESTROY": "syscall", - "syscall.SIOCIFGCLONERS": "syscall", - "syscall.SIOCINITIFADDR": "syscall", - "syscall.SIOCPROTOPRIVATE": "syscall", - "syscall.SIOCRSLVMULTI": "syscall", - "syscall.SIOCRTMSG": "syscall", - "syscall.SIOCSARP": "syscall", - "syscall.SIOCSDRVSPEC": "syscall", - "syscall.SIOCSETKALIVE": "syscall", - "syscall.SIOCSETLABEL": "syscall", - "syscall.SIOCSETPFLOW": "syscall", - "syscall.SIOCSETPFSYNC": "syscall", - "syscall.SIOCSETVLAN": "syscall", - "syscall.SIOCSHIWAT": "syscall", - "syscall.SIOCSIFADDR": "syscall", - "syscall.SIOCSIFADDRPREF": "syscall", - "syscall.SIOCSIFALTMTU": "syscall", - "syscall.SIOCSIFASYNCMAP": "syscall", - "syscall.SIOCSIFBOND": "syscall", - "syscall.SIOCSIFBR": "syscall", - "syscall.SIOCSIFBRDADDR": "syscall", - "syscall.SIOCSIFCAP": "syscall", - "syscall.SIOCSIFDESCR": "syscall", - "syscall.SIOCSIFDSTADDR": "syscall", - "syscall.SIOCSIFENCAP": "syscall", - "syscall.SIOCSIFFIB": "syscall", - "syscall.SIOCSIFFLAGS": "syscall", - "syscall.SIOCSIFGATTR": "syscall", - "syscall.SIOCSIFGENERIC": "syscall", - "syscall.SIOCSIFHWADDR": "syscall", - "syscall.SIOCSIFHWBROADCAST": "syscall", - "syscall.SIOCSIFKPI": "syscall", - "syscall.SIOCSIFLINK": "syscall", - "syscall.SIOCSIFLLADDR": "syscall", - "syscall.SIOCSIFMAC": "syscall", - "syscall.SIOCSIFMAP": "syscall", - "syscall.SIOCSIFMEDIA": "syscall", - "syscall.SIOCSIFMEM": "syscall", - "syscall.SIOCSIFMETRIC": "syscall", - "syscall.SIOCSIFMTU": "syscall", - "syscall.SIOCSIFNAME": "syscall", - "syscall.SIOCSIFNETMASK": "syscall", - "syscall.SIOCSIFPFLAGS": "syscall", - "syscall.SIOCSIFPHYADDR": "syscall", - "syscall.SIOCSIFPHYS": "syscall", - "syscall.SIOCSIFPRIORITY": "syscall", - "syscall.SIOCSIFRDOMAIN": "syscall", - "syscall.SIOCSIFRTLABEL": "syscall", - "syscall.SIOCSIFRVNET": "syscall", - "syscall.SIOCSIFSLAVE": "syscall", - "syscall.SIOCSIFTIMESLOT": "syscall", - "syscall.SIOCSIFTXQLEN": "syscall", - "syscall.SIOCSIFVLAN": "syscall", - "syscall.SIOCSIFVNET": "syscall", - "syscall.SIOCSIFXFLAGS": "syscall", - "syscall.SIOCSLIFPHYADDR": "syscall", - "syscall.SIOCSLIFPHYRTABLE": "syscall", - "syscall.SIOCSLIFPHYTTL": "syscall", - "syscall.SIOCSLINKSTR": "syscall", - "syscall.SIOCSLOWAT": "syscall", - "syscall.SIOCSPGRP": "syscall", - "syscall.SIOCSRARP": "syscall", - "syscall.SIOCSSPPPPARAMS": "syscall", - "syscall.SIOCSVH": "syscall", - "syscall.SIOCSVNETID": "syscall", - "syscall.SIOCZIFDATA": "syscall", - "syscall.SIO_GET_EXTENSION_FUNCTION_POINTER": "syscall", - "syscall.SIO_GET_INTERFACE_LIST": "syscall", - "syscall.SIO_KEEPALIVE_VALS": "syscall", - "syscall.SIO_UDP_CONNRESET": "syscall", - "syscall.SOCK_CLOEXEC": "syscall", - "syscall.SOCK_DCCP": "syscall", - "syscall.SOCK_DGRAM": "syscall", - "syscall.SOCK_FLAGS_MASK": "syscall", - "syscall.SOCK_MAXADDRLEN": "syscall", - "syscall.SOCK_NONBLOCK": "syscall", - "syscall.SOCK_NOSIGPIPE": "syscall", - "syscall.SOCK_PACKET": "syscall", - "syscall.SOCK_RAW": "syscall", - "syscall.SOCK_RDM": "syscall", - "syscall.SOCK_SEQPACKET": "syscall", - "syscall.SOCK_STREAM": "syscall", - "syscall.SOL_AAL": "syscall", - "syscall.SOL_ATM": "syscall", - "syscall.SOL_DECNET": "syscall", - "syscall.SOL_ICMPV6": "syscall", - "syscall.SOL_IP": "syscall", - "syscall.SOL_IPV6": "syscall", - "syscall.SOL_IRDA": "syscall", - "syscall.SOL_PACKET": "syscall", - "syscall.SOL_RAW": "syscall", - "syscall.SOL_SOCKET": "syscall", - "syscall.SOL_TCP": "syscall", - "syscall.SOL_X25": "syscall", - "syscall.SOMAXCONN": "syscall", - "syscall.SO_ACCEPTCONN": "syscall", - "syscall.SO_ACCEPTFILTER": "syscall", - "syscall.SO_ATTACH_FILTER": "syscall", - "syscall.SO_BINDANY": "syscall", - "syscall.SO_BINDTODEVICE": "syscall", - "syscall.SO_BINTIME": "syscall", - "syscall.SO_BROADCAST": "syscall", - "syscall.SO_BSDCOMPAT": "syscall", - "syscall.SO_DEBUG": "syscall", - "syscall.SO_DETACH_FILTER": "syscall", - "syscall.SO_DOMAIN": "syscall", - "syscall.SO_DONTROUTE": "syscall", - "syscall.SO_DONTTRUNC": "syscall", - "syscall.SO_ERROR": "syscall", - "syscall.SO_KEEPALIVE": "syscall", - "syscall.SO_LABEL": "syscall", - "syscall.SO_LINGER": "syscall", - "syscall.SO_LINGER_SEC": "syscall", - "syscall.SO_LISTENINCQLEN": "syscall", - "syscall.SO_LISTENQLEN": "syscall", - "syscall.SO_LISTENQLIMIT": "syscall", - "syscall.SO_MARK": "syscall", - "syscall.SO_NETPROC": "syscall", - "syscall.SO_NKE": "syscall", - "syscall.SO_NOADDRERR": "syscall", - "syscall.SO_NOHEADER": "syscall", - "syscall.SO_NOSIGPIPE": "syscall", - "syscall.SO_NOTIFYCONFLICT": "syscall", - "syscall.SO_NO_CHECK": "syscall", - "syscall.SO_NO_DDP": "syscall", - "syscall.SO_NO_OFFLOAD": "syscall", - "syscall.SO_NP_EXTENSIONS": "syscall", - "syscall.SO_NREAD": "syscall", - "syscall.SO_NWRITE": "syscall", - "syscall.SO_OOBINLINE": "syscall", - "syscall.SO_OVERFLOWED": "syscall", - "syscall.SO_PASSCRED": "syscall", - "syscall.SO_PASSSEC": "syscall", - "syscall.SO_PEERCRED": "syscall", - "syscall.SO_PEERLABEL": "syscall", - "syscall.SO_PEERNAME": "syscall", - "syscall.SO_PEERSEC": "syscall", - "syscall.SO_PRIORITY": "syscall", - "syscall.SO_PROTOCOL": "syscall", - "syscall.SO_PROTOTYPE": "syscall", - "syscall.SO_RANDOMPORT": "syscall", - "syscall.SO_RCVBUF": "syscall", - "syscall.SO_RCVBUFFORCE": "syscall", - "syscall.SO_RCVLOWAT": "syscall", - "syscall.SO_RCVTIMEO": "syscall", - "syscall.SO_RESTRICTIONS": "syscall", - "syscall.SO_RESTRICT_DENYIN": "syscall", - "syscall.SO_RESTRICT_DENYOUT": "syscall", - "syscall.SO_RESTRICT_DENYSET": "syscall", - "syscall.SO_REUSEADDR": "syscall", - "syscall.SO_REUSEPORT": "syscall", - "syscall.SO_REUSESHAREUID": "syscall", - "syscall.SO_RTABLE": "syscall", - "syscall.SO_RXQ_OVFL": "syscall", - "syscall.SO_SECURITY_AUTHENTICATION": "syscall", - "syscall.SO_SECURITY_ENCRYPTION_NETWORK": "syscall", - "syscall.SO_SECURITY_ENCRYPTION_TRANSPORT": "syscall", - "syscall.SO_SETFIB": "syscall", - "syscall.SO_SNDBUF": "syscall", - "syscall.SO_SNDBUFFORCE": "syscall", - "syscall.SO_SNDLOWAT": "syscall", - "syscall.SO_SNDTIMEO": "syscall", - "syscall.SO_SPLICE": "syscall", - "syscall.SO_TIMESTAMP": "syscall", - "syscall.SO_TIMESTAMPING": "syscall", - "syscall.SO_TIMESTAMPNS": "syscall", - "syscall.SO_TIMESTAMP_MONOTONIC": "syscall", - "syscall.SO_TYPE": "syscall", - "syscall.SO_UPCALLCLOSEWAIT": "syscall", - "syscall.SO_UPDATE_ACCEPT_CONTEXT": "syscall", - "syscall.SO_UPDATE_CONNECT_CONTEXT": "syscall", - "syscall.SO_USELOOPBACK": "syscall", - "syscall.SO_USER_COOKIE": "syscall", - "syscall.SO_VENDOR": "syscall", - "syscall.SO_WANTMORE": "syscall", - "syscall.SO_WANTOOBFLAG": "syscall", - "syscall.SSLExtraCertChainPolicyPara": "syscall", - "syscall.STANDARD_RIGHTS_ALL": "syscall", - "syscall.STANDARD_RIGHTS_EXECUTE": "syscall", - "syscall.STANDARD_RIGHTS_READ": "syscall", - "syscall.STANDARD_RIGHTS_REQUIRED": "syscall", - "syscall.STANDARD_RIGHTS_WRITE": "syscall", - "syscall.STARTF_USESHOWWINDOW": "syscall", - "syscall.STARTF_USESTDHANDLES": "syscall", - "syscall.STD_ERROR_HANDLE": "syscall", - "syscall.STD_INPUT_HANDLE": "syscall", - "syscall.STD_OUTPUT_HANDLE": "syscall", - "syscall.SUBLANG_ENGLISH_US": "syscall", - "syscall.SW_FORCEMINIMIZE": "syscall", - "syscall.SW_HIDE": "syscall", - "syscall.SW_MAXIMIZE": "syscall", - "syscall.SW_MINIMIZE": "syscall", - "syscall.SW_NORMAL": "syscall", - "syscall.SW_RESTORE": "syscall", - "syscall.SW_SHOW": "syscall", - "syscall.SW_SHOWDEFAULT": "syscall", - "syscall.SW_SHOWMAXIMIZED": "syscall", - "syscall.SW_SHOWMINIMIZED": "syscall", - "syscall.SW_SHOWMINNOACTIVE": "syscall", - "syscall.SW_SHOWNA": "syscall", - "syscall.SW_SHOWNOACTIVATE": "syscall", - "syscall.SW_SHOWNORMAL": "syscall", - "syscall.SYMBOLIC_LINK_FLAG_DIRECTORY": "syscall", - "syscall.SYNCHRONIZE": "syscall", - "syscall.SYSCTL_VERSION": "syscall", - "syscall.SYSCTL_VERS_0": "syscall", - "syscall.SYSCTL_VERS_1": "syscall", - "syscall.SYSCTL_VERS_MASK": "syscall", - "syscall.SYS_ABORT2": "syscall", - "syscall.SYS_ACCEPT": "syscall", - "syscall.SYS_ACCEPT4": "syscall", - "syscall.SYS_ACCEPT_NOCANCEL": "syscall", - "syscall.SYS_ACCESS": "syscall", - "syscall.SYS_ACCESS_EXTENDED": "syscall", - "syscall.SYS_ACCT": "syscall", - "syscall.SYS_ADD_KEY": "syscall", - "syscall.SYS_ADD_PROFIL": "syscall", - "syscall.SYS_ADJFREQ": "syscall", - "syscall.SYS_ADJTIME": "syscall", - "syscall.SYS_ADJTIMEX": "syscall", - "syscall.SYS_AFS_SYSCALL": "syscall", - "syscall.SYS_AIO_CANCEL": "syscall", - "syscall.SYS_AIO_ERROR": "syscall", - "syscall.SYS_AIO_FSYNC": "syscall", - "syscall.SYS_AIO_READ": "syscall", - "syscall.SYS_AIO_RETURN": "syscall", - "syscall.SYS_AIO_SUSPEND": "syscall", - "syscall.SYS_AIO_SUSPEND_NOCANCEL": "syscall", - "syscall.SYS_AIO_WRITE": "syscall", - "syscall.SYS_ALARM": "syscall", - "syscall.SYS_ARCH_PRCTL": "syscall", - "syscall.SYS_ARM_FADVISE64_64": "syscall", - "syscall.SYS_ARM_SYNC_FILE_RANGE": "syscall", - "syscall.SYS_ATGETMSG": "syscall", - "syscall.SYS_ATPGETREQ": "syscall", - "syscall.SYS_ATPGETRSP": "syscall", - "syscall.SYS_ATPSNDREQ": "syscall", - "syscall.SYS_ATPSNDRSP": "syscall", - "syscall.SYS_ATPUTMSG": "syscall", - "syscall.SYS_ATSOCKET": "syscall", - "syscall.SYS_AUDIT": "syscall", - "syscall.SYS_AUDITCTL": "syscall", - "syscall.SYS_AUDITON": "syscall", - "syscall.SYS_AUDIT_SESSION_JOIN": "syscall", - "syscall.SYS_AUDIT_SESSION_PORT": "syscall", - "syscall.SYS_AUDIT_SESSION_SELF": "syscall", - "syscall.SYS_BDFLUSH": "syscall", - "syscall.SYS_BIND": "syscall", - "syscall.SYS_BINDAT": "syscall", - "syscall.SYS_BREAK": "syscall", - "syscall.SYS_BRK": "syscall", - "syscall.SYS_BSDTHREAD_CREATE": "syscall", - "syscall.SYS_BSDTHREAD_REGISTER": "syscall", - "syscall.SYS_BSDTHREAD_TERMINATE": "syscall", - "syscall.SYS_CAPGET": "syscall", - "syscall.SYS_CAPSET": "syscall", - "syscall.SYS_CAP_ENTER": "syscall", - "syscall.SYS_CAP_FCNTLS_GET": "syscall", - "syscall.SYS_CAP_FCNTLS_LIMIT": "syscall", - "syscall.SYS_CAP_GETMODE": "syscall", - "syscall.SYS_CAP_GETRIGHTS": "syscall", - "syscall.SYS_CAP_IOCTLS_GET": "syscall", - "syscall.SYS_CAP_IOCTLS_LIMIT": "syscall", - "syscall.SYS_CAP_NEW": "syscall", - "syscall.SYS_CAP_RIGHTS_GET": "syscall", - "syscall.SYS_CAP_RIGHTS_LIMIT": "syscall", - "syscall.SYS_CHDIR": "syscall", - "syscall.SYS_CHFLAGS": "syscall", - "syscall.SYS_CHFLAGSAT": "syscall", - "syscall.SYS_CHMOD": "syscall", - "syscall.SYS_CHMOD_EXTENDED": "syscall", - "syscall.SYS_CHOWN": "syscall", - "syscall.SYS_CHOWN32": "syscall", - "syscall.SYS_CHROOT": "syscall", - "syscall.SYS_CHUD": "syscall", - "syscall.SYS_CLOCK_ADJTIME": "syscall", - "syscall.SYS_CLOCK_GETCPUCLOCKID2": "syscall", - "syscall.SYS_CLOCK_GETRES": "syscall", - "syscall.SYS_CLOCK_GETTIME": "syscall", - "syscall.SYS_CLOCK_NANOSLEEP": "syscall", - "syscall.SYS_CLOCK_SETTIME": "syscall", - "syscall.SYS_CLONE": "syscall", - "syscall.SYS_CLOSE": "syscall", - "syscall.SYS_CLOSEFROM": "syscall", - "syscall.SYS_CLOSE_NOCANCEL": "syscall", - "syscall.SYS_CONNECT": "syscall", - "syscall.SYS_CONNECTAT": "syscall", - "syscall.SYS_CONNECT_NOCANCEL": "syscall", - "syscall.SYS_COPYFILE": "syscall", - "syscall.SYS_CPUSET": "syscall", - "syscall.SYS_CPUSET_GETAFFINITY": "syscall", - "syscall.SYS_CPUSET_GETID": "syscall", - "syscall.SYS_CPUSET_SETAFFINITY": "syscall", - "syscall.SYS_CPUSET_SETID": "syscall", - "syscall.SYS_CREAT": "syscall", - "syscall.SYS_CREATE_MODULE": "syscall", - "syscall.SYS_CSOPS": "syscall", - "syscall.SYS_DELETE": "syscall", - "syscall.SYS_DELETE_MODULE": "syscall", - "syscall.SYS_DUP": "syscall", - "syscall.SYS_DUP2": "syscall", - "syscall.SYS_DUP3": "syscall", - "syscall.SYS_EACCESS": "syscall", - "syscall.SYS_EPOLL_CREATE": "syscall", - "syscall.SYS_EPOLL_CREATE1": "syscall", - "syscall.SYS_EPOLL_CTL": "syscall", - "syscall.SYS_EPOLL_CTL_OLD": "syscall", - "syscall.SYS_EPOLL_PWAIT": "syscall", - "syscall.SYS_EPOLL_WAIT": "syscall", - "syscall.SYS_EPOLL_WAIT_OLD": "syscall", - "syscall.SYS_EVENTFD": "syscall", - "syscall.SYS_EVENTFD2": "syscall", - "syscall.SYS_EXCHANGEDATA": "syscall", - "syscall.SYS_EXECVE": "syscall", - "syscall.SYS_EXIT": "syscall", - "syscall.SYS_EXIT_GROUP": "syscall", - "syscall.SYS_EXTATTRCTL": "syscall", - "syscall.SYS_EXTATTR_DELETE_FD": "syscall", - "syscall.SYS_EXTATTR_DELETE_FILE": "syscall", - "syscall.SYS_EXTATTR_DELETE_LINK": "syscall", - "syscall.SYS_EXTATTR_GET_FD": "syscall", - "syscall.SYS_EXTATTR_GET_FILE": "syscall", - "syscall.SYS_EXTATTR_GET_LINK": "syscall", - "syscall.SYS_EXTATTR_LIST_FD": "syscall", - "syscall.SYS_EXTATTR_LIST_FILE": "syscall", - "syscall.SYS_EXTATTR_LIST_LINK": "syscall", - "syscall.SYS_EXTATTR_SET_FD": "syscall", - "syscall.SYS_EXTATTR_SET_FILE": "syscall", - "syscall.SYS_EXTATTR_SET_LINK": "syscall", - "syscall.SYS_FACCESSAT": "syscall", - "syscall.SYS_FADVISE64": "syscall", - "syscall.SYS_FADVISE64_64": "syscall", - "syscall.SYS_FALLOCATE": "syscall", - "syscall.SYS_FANOTIFY_INIT": "syscall", - "syscall.SYS_FANOTIFY_MARK": "syscall", - "syscall.SYS_FCHDIR": "syscall", - "syscall.SYS_FCHFLAGS": "syscall", - "syscall.SYS_FCHMOD": "syscall", - "syscall.SYS_FCHMODAT": "syscall", - "syscall.SYS_FCHMOD_EXTENDED": "syscall", - "syscall.SYS_FCHOWN": "syscall", - "syscall.SYS_FCHOWN32": "syscall", - "syscall.SYS_FCHOWNAT": "syscall", - "syscall.SYS_FCHROOT": "syscall", - "syscall.SYS_FCNTL": "syscall", - "syscall.SYS_FCNTL64": "syscall", - "syscall.SYS_FCNTL_NOCANCEL": "syscall", - "syscall.SYS_FDATASYNC": "syscall", - "syscall.SYS_FEXECVE": "syscall", - "syscall.SYS_FFCLOCK_GETCOUNTER": "syscall", - "syscall.SYS_FFCLOCK_GETESTIMATE": "syscall", - "syscall.SYS_FFCLOCK_SETESTIMATE": "syscall", - "syscall.SYS_FFSCTL": "syscall", - "syscall.SYS_FGETATTRLIST": "syscall", - "syscall.SYS_FGETXATTR": "syscall", - "syscall.SYS_FHOPEN": "syscall", - "syscall.SYS_FHSTAT": "syscall", - "syscall.SYS_FHSTATFS": "syscall", - "syscall.SYS_FILEPORT_MAKEFD": "syscall", - "syscall.SYS_FILEPORT_MAKEPORT": "syscall", - "syscall.SYS_FKTRACE": "syscall", - "syscall.SYS_FLISTXATTR": "syscall", - "syscall.SYS_FLOCK": "syscall", - "syscall.SYS_FORK": "syscall", - "syscall.SYS_FPATHCONF": "syscall", - "syscall.SYS_FREEBSD6_FTRUNCATE": "syscall", - "syscall.SYS_FREEBSD6_LSEEK": "syscall", - "syscall.SYS_FREEBSD6_MMAP": "syscall", - "syscall.SYS_FREEBSD6_PREAD": "syscall", - "syscall.SYS_FREEBSD6_PWRITE": "syscall", - "syscall.SYS_FREEBSD6_TRUNCATE": "syscall", - "syscall.SYS_FREMOVEXATTR": "syscall", - "syscall.SYS_FSCTL": "syscall", - "syscall.SYS_FSETATTRLIST": "syscall", - "syscall.SYS_FSETXATTR": "syscall", - "syscall.SYS_FSGETPATH": "syscall", - "syscall.SYS_FSTAT": "syscall", - "syscall.SYS_FSTAT64": "syscall", - "syscall.SYS_FSTAT64_EXTENDED": "syscall", - "syscall.SYS_FSTATAT": "syscall", - "syscall.SYS_FSTATAT64": "syscall", - "syscall.SYS_FSTATFS": "syscall", - "syscall.SYS_FSTATFS64": "syscall", - "syscall.SYS_FSTATV": "syscall", - "syscall.SYS_FSTATVFS1": "syscall", - "syscall.SYS_FSTAT_EXTENDED": "syscall", - "syscall.SYS_FSYNC": "syscall", - "syscall.SYS_FSYNC_NOCANCEL": "syscall", - "syscall.SYS_FSYNC_RANGE": "syscall", - "syscall.SYS_FTIME": "syscall", - "syscall.SYS_FTRUNCATE": "syscall", - "syscall.SYS_FTRUNCATE64": "syscall", - "syscall.SYS_FUTEX": "syscall", - "syscall.SYS_FUTIMENS": "syscall", - "syscall.SYS_FUTIMES": "syscall", - "syscall.SYS_FUTIMESAT": "syscall", - "syscall.SYS_GETATTRLIST": "syscall", - "syscall.SYS_GETAUDIT": "syscall", - "syscall.SYS_GETAUDIT_ADDR": "syscall", - "syscall.SYS_GETAUID": "syscall", - "syscall.SYS_GETCONTEXT": "syscall", - "syscall.SYS_GETCPU": "syscall", - "syscall.SYS_GETCWD": "syscall", - "syscall.SYS_GETDENTS": "syscall", - "syscall.SYS_GETDENTS64": "syscall", - "syscall.SYS_GETDIRENTRIES": "syscall", - "syscall.SYS_GETDIRENTRIES64": "syscall", - "syscall.SYS_GETDIRENTRIESATTR": "syscall", - "syscall.SYS_GETDTABLECOUNT": "syscall", - "syscall.SYS_GETDTABLESIZE": "syscall", - "syscall.SYS_GETEGID": "syscall", - "syscall.SYS_GETEGID32": "syscall", - "syscall.SYS_GETEUID": "syscall", - "syscall.SYS_GETEUID32": "syscall", - "syscall.SYS_GETFH": "syscall", - "syscall.SYS_GETFSSTAT": "syscall", - "syscall.SYS_GETFSSTAT64": "syscall", - "syscall.SYS_GETGID": "syscall", - "syscall.SYS_GETGID32": "syscall", - "syscall.SYS_GETGROUPS": "syscall", - "syscall.SYS_GETGROUPS32": "syscall", - "syscall.SYS_GETHOSTUUID": "syscall", - "syscall.SYS_GETITIMER": "syscall", - "syscall.SYS_GETLCID": "syscall", - "syscall.SYS_GETLOGIN": "syscall", - "syscall.SYS_GETLOGINCLASS": "syscall", - "syscall.SYS_GETPEERNAME": "syscall", - "syscall.SYS_GETPGID": "syscall", - "syscall.SYS_GETPGRP": "syscall", - "syscall.SYS_GETPID": "syscall", - "syscall.SYS_GETPMSG": "syscall", - "syscall.SYS_GETPPID": "syscall", - "syscall.SYS_GETPRIORITY": "syscall", - "syscall.SYS_GETRESGID": "syscall", - "syscall.SYS_GETRESGID32": "syscall", - "syscall.SYS_GETRESUID": "syscall", - "syscall.SYS_GETRESUID32": "syscall", - "syscall.SYS_GETRLIMIT": "syscall", - "syscall.SYS_GETRTABLE": "syscall", - "syscall.SYS_GETRUSAGE": "syscall", - "syscall.SYS_GETSGROUPS": "syscall", - "syscall.SYS_GETSID": "syscall", - "syscall.SYS_GETSOCKNAME": "syscall", - "syscall.SYS_GETSOCKOPT": "syscall", - "syscall.SYS_GETTHRID": "syscall", - "syscall.SYS_GETTID": "syscall", - "syscall.SYS_GETTIMEOFDAY": "syscall", - "syscall.SYS_GETUID": "syscall", - "syscall.SYS_GETUID32": "syscall", - "syscall.SYS_GETVFSSTAT": "syscall", - "syscall.SYS_GETWGROUPS": "syscall", - "syscall.SYS_GETXATTR": "syscall", - "syscall.SYS_GET_KERNEL_SYMS": "syscall", - "syscall.SYS_GET_MEMPOLICY": "syscall", - "syscall.SYS_GET_ROBUST_LIST": "syscall", - "syscall.SYS_GET_THREAD_AREA": "syscall", - "syscall.SYS_GTTY": "syscall", - "syscall.SYS_IDENTITYSVC": "syscall", - "syscall.SYS_IDLE": "syscall", - "syscall.SYS_INITGROUPS": "syscall", - "syscall.SYS_INIT_MODULE": "syscall", - "syscall.SYS_INOTIFY_ADD_WATCH": "syscall", - "syscall.SYS_INOTIFY_INIT": "syscall", - "syscall.SYS_INOTIFY_INIT1": "syscall", - "syscall.SYS_INOTIFY_RM_WATCH": "syscall", - "syscall.SYS_IOCTL": "syscall", - "syscall.SYS_IOPERM": "syscall", - "syscall.SYS_IOPL": "syscall", - "syscall.SYS_IOPOLICYSYS": "syscall", - "syscall.SYS_IOPRIO_GET": "syscall", - "syscall.SYS_IOPRIO_SET": "syscall", - "syscall.SYS_IO_CANCEL": "syscall", - "syscall.SYS_IO_DESTROY": "syscall", - "syscall.SYS_IO_GETEVENTS": "syscall", - "syscall.SYS_IO_SETUP": "syscall", - "syscall.SYS_IO_SUBMIT": "syscall", - "syscall.SYS_IPC": "syscall", - "syscall.SYS_ISSETUGID": "syscall", - "syscall.SYS_JAIL": "syscall", - "syscall.SYS_JAIL_ATTACH": "syscall", - "syscall.SYS_JAIL_GET": "syscall", - "syscall.SYS_JAIL_REMOVE": "syscall", - "syscall.SYS_JAIL_SET": "syscall", - "syscall.SYS_KDEBUG_TRACE": "syscall", - "syscall.SYS_KENV": "syscall", - "syscall.SYS_KEVENT": "syscall", - "syscall.SYS_KEVENT64": "syscall", - "syscall.SYS_KEXEC_LOAD": "syscall", - "syscall.SYS_KEYCTL": "syscall", - "syscall.SYS_KILL": "syscall", - "syscall.SYS_KLDFIND": "syscall", - "syscall.SYS_KLDFIRSTMOD": "syscall", - "syscall.SYS_KLDLOAD": "syscall", - "syscall.SYS_KLDNEXT": "syscall", - "syscall.SYS_KLDSTAT": "syscall", - "syscall.SYS_KLDSYM": "syscall", - "syscall.SYS_KLDUNLOAD": "syscall", - "syscall.SYS_KLDUNLOADF": "syscall", - "syscall.SYS_KQUEUE": "syscall", - "syscall.SYS_KQUEUE1": "syscall", - "syscall.SYS_KTIMER_CREATE": "syscall", - "syscall.SYS_KTIMER_DELETE": "syscall", - "syscall.SYS_KTIMER_GETOVERRUN": "syscall", - "syscall.SYS_KTIMER_GETTIME": "syscall", - "syscall.SYS_KTIMER_SETTIME": "syscall", - "syscall.SYS_KTRACE": "syscall", - "syscall.SYS_LCHFLAGS": "syscall", - "syscall.SYS_LCHMOD": "syscall", - "syscall.SYS_LCHOWN": "syscall", - "syscall.SYS_LCHOWN32": "syscall", - "syscall.SYS_LGETFH": "syscall", - "syscall.SYS_LGETXATTR": "syscall", - "syscall.SYS_LINK": "syscall", - "syscall.SYS_LINKAT": "syscall", - "syscall.SYS_LIO_LISTIO": "syscall", - "syscall.SYS_LISTEN": "syscall", - "syscall.SYS_LISTXATTR": "syscall", - "syscall.SYS_LLISTXATTR": "syscall", - "syscall.SYS_LOCK": "syscall", - "syscall.SYS_LOOKUP_DCOOKIE": "syscall", - "syscall.SYS_LPATHCONF": "syscall", - "syscall.SYS_LREMOVEXATTR": "syscall", - "syscall.SYS_LSEEK": "syscall", - "syscall.SYS_LSETXATTR": "syscall", - "syscall.SYS_LSTAT": "syscall", - "syscall.SYS_LSTAT64": "syscall", - "syscall.SYS_LSTAT64_EXTENDED": "syscall", - "syscall.SYS_LSTATV": "syscall", - "syscall.SYS_LSTAT_EXTENDED": "syscall", - "syscall.SYS_LUTIMES": "syscall", - "syscall.SYS_MAC_SYSCALL": "syscall", - "syscall.SYS_MADVISE": "syscall", - "syscall.SYS_MADVISE1": "syscall", - "syscall.SYS_MAXSYSCALL": "syscall", - "syscall.SYS_MBIND": "syscall", - "syscall.SYS_MIGRATE_PAGES": "syscall", - "syscall.SYS_MINCORE": "syscall", - "syscall.SYS_MINHERIT": "syscall", - "syscall.SYS_MKCOMPLEX": "syscall", - "syscall.SYS_MKDIR": "syscall", - "syscall.SYS_MKDIRAT": "syscall", - "syscall.SYS_MKDIR_EXTENDED": "syscall", - "syscall.SYS_MKFIFO": "syscall", - "syscall.SYS_MKFIFOAT": "syscall", - "syscall.SYS_MKFIFO_EXTENDED": "syscall", - "syscall.SYS_MKNOD": "syscall", - "syscall.SYS_MKNODAT": "syscall", - "syscall.SYS_MLOCK": "syscall", - "syscall.SYS_MLOCKALL": "syscall", - "syscall.SYS_MMAP": "syscall", - "syscall.SYS_MMAP2": "syscall", - "syscall.SYS_MODCTL": "syscall", - "syscall.SYS_MODFIND": "syscall", - "syscall.SYS_MODFNEXT": "syscall", - "syscall.SYS_MODIFY_LDT": "syscall", - "syscall.SYS_MODNEXT": "syscall", - "syscall.SYS_MODSTAT": "syscall", - "syscall.SYS_MODWATCH": "syscall", - "syscall.SYS_MOUNT": "syscall", - "syscall.SYS_MOVE_PAGES": "syscall", - "syscall.SYS_MPROTECT": "syscall", - "syscall.SYS_MPX": "syscall", - "syscall.SYS_MQUERY": "syscall", - "syscall.SYS_MQ_GETSETATTR": "syscall", - "syscall.SYS_MQ_NOTIFY": "syscall", - "syscall.SYS_MQ_OPEN": "syscall", - "syscall.SYS_MQ_TIMEDRECEIVE": "syscall", - "syscall.SYS_MQ_TIMEDSEND": "syscall", - "syscall.SYS_MQ_UNLINK": "syscall", - "syscall.SYS_MREMAP": "syscall", - "syscall.SYS_MSGCTL": "syscall", - "syscall.SYS_MSGGET": "syscall", - "syscall.SYS_MSGRCV": "syscall", - "syscall.SYS_MSGRCV_NOCANCEL": "syscall", - "syscall.SYS_MSGSND": "syscall", - "syscall.SYS_MSGSND_NOCANCEL": "syscall", - "syscall.SYS_MSGSYS": "syscall", - "syscall.SYS_MSYNC": "syscall", - "syscall.SYS_MSYNC_NOCANCEL": "syscall", - "syscall.SYS_MUNLOCK": "syscall", - "syscall.SYS_MUNLOCKALL": "syscall", - "syscall.SYS_MUNMAP": "syscall", - "syscall.SYS_NAME_TO_HANDLE_AT": "syscall", - "syscall.SYS_NANOSLEEP": "syscall", - "syscall.SYS_NEWFSTATAT": "syscall", - "syscall.SYS_NFSCLNT": "syscall", - "syscall.SYS_NFSSERVCTL": "syscall", - "syscall.SYS_NFSSVC": "syscall", - "syscall.SYS_NFSTAT": "syscall", - "syscall.SYS_NICE": "syscall", - "syscall.SYS_NLSTAT": "syscall", - "syscall.SYS_NMOUNT": "syscall", - "syscall.SYS_NSTAT": "syscall", - "syscall.SYS_NTP_ADJTIME": "syscall", - "syscall.SYS_NTP_GETTIME": "syscall", - "syscall.SYS_OABI_SYSCALL_BASE": "syscall", - "syscall.SYS_OBREAK": "syscall", - "syscall.SYS_OLDFSTAT": "syscall", - "syscall.SYS_OLDLSTAT": "syscall", - "syscall.SYS_OLDOLDUNAME": "syscall", - "syscall.SYS_OLDSTAT": "syscall", - "syscall.SYS_OLDUNAME": "syscall", - "syscall.SYS_OPEN": "syscall", - "syscall.SYS_OPENAT": "syscall", - "syscall.SYS_OPENBSD_POLL": "syscall", - "syscall.SYS_OPEN_BY_HANDLE_AT": "syscall", - "syscall.SYS_OPEN_EXTENDED": "syscall", - "syscall.SYS_OPEN_NOCANCEL": "syscall", - "syscall.SYS_OVADVISE": "syscall", - "syscall.SYS_PACCEPT": "syscall", - "syscall.SYS_PATHCONF": "syscall", - "syscall.SYS_PAUSE": "syscall", - "syscall.SYS_PCICONFIG_IOBASE": "syscall", - "syscall.SYS_PCICONFIG_READ": "syscall", - "syscall.SYS_PCICONFIG_WRITE": "syscall", - "syscall.SYS_PDFORK": "syscall", - "syscall.SYS_PDGETPID": "syscall", - "syscall.SYS_PDKILL": "syscall", - "syscall.SYS_PERF_EVENT_OPEN": "syscall", - "syscall.SYS_PERSONALITY": "syscall", - "syscall.SYS_PID_HIBERNATE": "syscall", - "syscall.SYS_PID_RESUME": "syscall", - "syscall.SYS_PID_SHUTDOWN_SOCKETS": "syscall", - "syscall.SYS_PID_SUSPEND": "syscall", - "syscall.SYS_PIPE": "syscall", - "syscall.SYS_PIPE2": "syscall", - "syscall.SYS_PIVOT_ROOT": "syscall", - "syscall.SYS_PMC_CONTROL": "syscall", - "syscall.SYS_PMC_GET_INFO": "syscall", - "syscall.SYS_POLL": "syscall", - "syscall.SYS_POLLTS": "syscall", - "syscall.SYS_POLL_NOCANCEL": "syscall", - "syscall.SYS_POSIX_FADVISE": "syscall", - "syscall.SYS_POSIX_FALLOCATE": "syscall", - "syscall.SYS_POSIX_OPENPT": "syscall", - "syscall.SYS_POSIX_SPAWN": "syscall", - "syscall.SYS_PPOLL": "syscall", - "syscall.SYS_PRCTL": "syscall", - "syscall.SYS_PREAD": "syscall", - "syscall.SYS_PREAD64": "syscall", - "syscall.SYS_PREADV": "syscall", - "syscall.SYS_PREAD_NOCANCEL": "syscall", - "syscall.SYS_PRLIMIT64": "syscall", - "syscall.SYS_PROCCTL": "syscall", - "syscall.SYS_PROCESS_POLICY": "syscall", - "syscall.SYS_PROCESS_VM_READV": "syscall", - "syscall.SYS_PROCESS_VM_WRITEV": "syscall", - "syscall.SYS_PROC_INFO": "syscall", - "syscall.SYS_PROF": "syscall", - "syscall.SYS_PROFIL": "syscall", - "syscall.SYS_PSELECT": "syscall", - "syscall.SYS_PSELECT6": "syscall", - "syscall.SYS_PSET_ASSIGN": "syscall", - "syscall.SYS_PSET_CREATE": "syscall", - "syscall.SYS_PSET_DESTROY": "syscall", - "syscall.SYS_PSYNCH_CVBROAD": "syscall", - "syscall.SYS_PSYNCH_CVCLRPREPOST": "syscall", - "syscall.SYS_PSYNCH_CVSIGNAL": "syscall", - "syscall.SYS_PSYNCH_CVWAIT": "syscall", - "syscall.SYS_PSYNCH_MUTEXDROP": "syscall", - "syscall.SYS_PSYNCH_MUTEXWAIT": "syscall", - "syscall.SYS_PSYNCH_RW_DOWNGRADE": "syscall", - "syscall.SYS_PSYNCH_RW_LONGRDLOCK": "syscall", - "syscall.SYS_PSYNCH_RW_RDLOCK": "syscall", - "syscall.SYS_PSYNCH_RW_UNLOCK": "syscall", - "syscall.SYS_PSYNCH_RW_UNLOCK2": "syscall", - "syscall.SYS_PSYNCH_RW_UPGRADE": "syscall", - "syscall.SYS_PSYNCH_RW_WRLOCK": "syscall", - "syscall.SYS_PSYNCH_RW_YIELDWRLOCK": "syscall", - "syscall.SYS_PTRACE": "syscall", - "syscall.SYS_PUTPMSG": "syscall", - "syscall.SYS_PWRITE": "syscall", - "syscall.SYS_PWRITE64": "syscall", - "syscall.SYS_PWRITEV": "syscall", - "syscall.SYS_PWRITE_NOCANCEL": "syscall", - "syscall.SYS_QUERY_MODULE": "syscall", - "syscall.SYS_QUOTACTL": "syscall", - "syscall.SYS_RASCTL": "syscall", - "syscall.SYS_RCTL_ADD_RULE": "syscall", - "syscall.SYS_RCTL_GET_LIMITS": "syscall", - "syscall.SYS_RCTL_GET_RACCT": "syscall", - "syscall.SYS_RCTL_GET_RULES": "syscall", - "syscall.SYS_RCTL_REMOVE_RULE": "syscall", - "syscall.SYS_READ": "syscall", - "syscall.SYS_READAHEAD": "syscall", - "syscall.SYS_READDIR": "syscall", - "syscall.SYS_READLINK": "syscall", - "syscall.SYS_READLINKAT": "syscall", - "syscall.SYS_READV": "syscall", - "syscall.SYS_READV_NOCANCEL": "syscall", - "syscall.SYS_READ_NOCANCEL": "syscall", - "syscall.SYS_REBOOT": "syscall", - "syscall.SYS_RECV": "syscall", - "syscall.SYS_RECVFROM": "syscall", - "syscall.SYS_RECVFROM_NOCANCEL": "syscall", - "syscall.SYS_RECVMMSG": "syscall", - "syscall.SYS_RECVMSG": "syscall", - "syscall.SYS_RECVMSG_NOCANCEL": "syscall", - "syscall.SYS_REMAP_FILE_PAGES": "syscall", - "syscall.SYS_REMOVEXATTR": "syscall", - "syscall.SYS_RENAME": "syscall", - "syscall.SYS_RENAMEAT": "syscall", - "syscall.SYS_REQUEST_KEY": "syscall", - "syscall.SYS_RESTART_SYSCALL": "syscall", - "syscall.SYS_REVOKE": "syscall", - "syscall.SYS_RFORK": "syscall", - "syscall.SYS_RMDIR": "syscall", - "syscall.SYS_RTPRIO": "syscall", - "syscall.SYS_RTPRIO_THREAD": "syscall", - "syscall.SYS_RT_SIGACTION": "syscall", - "syscall.SYS_RT_SIGPENDING": "syscall", - "syscall.SYS_RT_SIGPROCMASK": "syscall", - "syscall.SYS_RT_SIGQUEUEINFO": "syscall", - "syscall.SYS_RT_SIGRETURN": "syscall", - "syscall.SYS_RT_SIGSUSPEND": "syscall", - "syscall.SYS_RT_SIGTIMEDWAIT": "syscall", - "syscall.SYS_RT_TGSIGQUEUEINFO": "syscall", - "syscall.SYS_SBRK": "syscall", - "syscall.SYS_SCHED_GETAFFINITY": "syscall", - "syscall.SYS_SCHED_GETPARAM": "syscall", - "syscall.SYS_SCHED_GETSCHEDULER": "syscall", - "syscall.SYS_SCHED_GET_PRIORITY_MAX": "syscall", - "syscall.SYS_SCHED_GET_PRIORITY_MIN": "syscall", - "syscall.SYS_SCHED_RR_GET_INTERVAL": "syscall", - "syscall.SYS_SCHED_SETAFFINITY": "syscall", - "syscall.SYS_SCHED_SETPARAM": "syscall", - "syscall.SYS_SCHED_SETSCHEDULER": "syscall", - "syscall.SYS_SCHED_YIELD": "syscall", - "syscall.SYS_SCTP_GENERIC_RECVMSG": "syscall", - "syscall.SYS_SCTP_GENERIC_SENDMSG": "syscall", - "syscall.SYS_SCTP_GENERIC_SENDMSG_IOV": "syscall", - "syscall.SYS_SCTP_PEELOFF": "syscall", - "syscall.SYS_SEARCHFS": "syscall", - "syscall.SYS_SECURITY": "syscall", - "syscall.SYS_SELECT": "syscall", - "syscall.SYS_SELECT_NOCANCEL": "syscall", - "syscall.SYS_SEMCONFIG": "syscall", - "syscall.SYS_SEMCTL": "syscall", - "syscall.SYS_SEMGET": "syscall", - "syscall.SYS_SEMOP": "syscall", - "syscall.SYS_SEMSYS": "syscall", - "syscall.SYS_SEMTIMEDOP": "syscall", - "syscall.SYS_SEM_CLOSE": "syscall", - "syscall.SYS_SEM_DESTROY": "syscall", - "syscall.SYS_SEM_GETVALUE": "syscall", - "syscall.SYS_SEM_INIT": "syscall", - "syscall.SYS_SEM_OPEN": "syscall", - "syscall.SYS_SEM_POST": "syscall", - "syscall.SYS_SEM_TRYWAIT": "syscall", - "syscall.SYS_SEM_UNLINK": "syscall", - "syscall.SYS_SEM_WAIT": "syscall", - "syscall.SYS_SEM_WAIT_NOCANCEL": "syscall", - "syscall.SYS_SEND": "syscall", - "syscall.SYS_SENDFILE": "syscall", - "syscall.SYS_SENDFILE64": "syscall", - "syscall.SYS_SENDMMSG": "syscall", - "syscall.SYS_SENDMSG": "syscall", - "syscall.SYS_SENDMSG_NOCANCEL": "syscall", - "syscall.SYS_SENDTO": "syscall", - "syscall.SYS_SENDTO_NOCANCEL": "syscall", - "syscall.SYS_SETATTRLIST": "syscall", - "syscall.SYS_SETAUDIT": "syscall", - "syscall.SYS_SETAUDIT_ADDR": "syscall", - "syscall.SYS_SETAUID": "syscall", - "syscall.SYS_SETCONTEXT": "syscall", - "syscall.SYS_SETDOMAINNAME": "syscall", - "syscall.SYS_SETEGID": "syscall", - "syscall.SYS_SETEUID": "syscall", - "syscall.SYS_SETFIB": "syscall", - "syscall.SYS_SETFSGID": "syscall", - "syscall.SYS_SETFSGID32": "syscall", - "syscall.SYS_SETFSUID": "syscall", - "syscall.SYS_SETFSUID32": "syscall", - "syscall.SYS_SETGID": "syscall", - "syscall.SYS_SETGID32": "syscall", - "syscall.SYS_SETGROUPS": "syscall", - "syscall.SYS_SETGROUPS32": "syscall", - "syscall.SYS_SETHOSTNAME": "syscall", - "syscall.SYS_SETITIMER": "syscall", - "syscall.SYS_SETLCID": "syscall", - "syscall.SYS_SETLOGIN": "syscall", - "syscall.SYS_SETLOGINCLASS": "syscall", - "syscall.SYS_SETNS": "syscall", - "syscall.SYS_SETPGID": "syscall", - "syscall.SYS_SETPRIORITY": "syscall", - "syscall.SYS_SETPRIVEXEC": "syscall", - "syscall.SYS_SETREGID": "syscall", - "syscall.SYS_SETREGID32": "syscall", - "syscall.SYS_SETRESGID": "syscall", - "syscall.SYS_SETRESGID32": "syscall", - "syscall.SYS_SETRESUID": "syscall", - "syscall.SYS_SETRESUID32": "syscall", - "syscall.SYS_SETREUID": "syscall", - "syscall.SYS_SETREUID32": "syscall", - "syscall.SYS_SETRLIMIT": "syscall", - "syscall.SYS_SETRTABLE": "syscall", - "syscall.SYS_SETSGROUPS": "syscall", - "syscall.SYS_SETSID": "syscall", - "syscall.SYS_SETSOCKOPT": "syscall", - "syscall.SYS_SETTID": "syscall", - "syscall.SYS_SETTID_WITH_PID": "syscall", - "syscall.SYS_SETTIMEOFDAY": "syscall", - "syscall.SYS_SETUID": "syscall", - "syscall.SYS_SETUID32": "syscall", - "syscall.SYS_SETWGROUPS": "syscall", - "syscall.SYS_SETXATTR": "syscall", - "syscall.SYS_SET_MEMPOLICY": "syscall", - "syscall.SYS_SET_ROBUST_LIST": "syscall", - "syscall.SYS_SET_THREAD_AREA": "syscall", - "syscall.SYS_SET_TID_ADDRESS": "syscall", - "syscall.SYS_SGETMASK": "syscall", - "syscall.SYS_SHARED_REGION_CHECK_NP": "syscall", - "syscall.SYS_SHARED_REGION_MAP_AND_SLIDE_NP": "syscall", - "syscall.SYS_SHMAT": "syscall", - "syscall.SYS_SHMCTL": "syscall", - "syscall.SYS_SHMDT": "syscall", - "syscall.SYS_SHMGET": "syscall", - "syscall.SYS_SHMSYS": "syscall", - "syscall.SYS_SHM_OPEN": "syscall", - "syscall.SYS_SHM_UNLINK": "syscall", - "syscall.SYS_SHUTDOWN": "syscall", - "syscall.SYS_SIGACTION": "syscall", - "syscall.SYS_SIGALTSTACK": "syscall", - "syscall.SYS_SIGNAL": "syscall", - "syscall.SYS_SIGNALFD": "syscall", - "syscall.SYS_SIGNALFD4": "syscall", - "syscall.SYS_SIGPENDING": "syscall", - "syscall.SYS_SIGPROCMASK": "syscall", - "syscall.SYS_SIGQUEUE": "syscall", - "syscall.SYS_SIGQUEUEINFO": "syscall", - "syscall.SYS_SIGRETURN": "syscall", - "syscall.SYS_SIGSUSPEND": "syscall", - "syscall.SYS_SIGSUSPEND_NOCANCEL": "syscall", - "syscall.SYS_SIGTIMEDWAIT": "syscall", - "syscall.SYS_SIGWAIT": "syscall", - "syscall.SYS_SIGWAITINFO": "syscall", - "syscall.SYS_SOCKET": "syscall", - "syscall.SYS_SOCKETCALL": "syscall", - "syscall.SYS_SOCKETPAIR": "syscall", - "syscall.SYS_SPLICE": "syscall", - "syscall.SYS_SSETMASK": "syscall", - "syscall.SYS_SSTK": "syscall", - "syscall.SYS_STACK_SNAPSHOT": "syscall", - "syscall.SYS_STAT": "syscall", - "syscall.SYS_STAT64": "syscall", - "syscall.SYS_STAT64_EXTENDED": "syscall", - "syscall.SYS_STATFS": "syscall", - "syscall.SYS_STATFS64": "syscall", - "syscall.SYS_STATV": "syscall", - "syscall.SYS_STATVFS1": "syscall", - "syscall.SYS_STAT_EXTENDED": "syscall", - "syscall.SYS_STIME": "syscall", - "syscall.SYS_STTY": "syscall", - "syscall.SYS_SWAPCONTEXT": "syscall", - "syscall.SYS_SWAPCTL": "syscall", - "syscall.SYS_SWAPOFF": "syscall", - "syscall.SYS_SWAPON": "syscall", - "syscall.SYS_SYMLINK": "syscall", - "syscall.SYS_SYMLINKAT": "syscall", - "syscall.SYS_SYNC": "syscall", - "syscall.SYS_SYNCFS": "syscall", - "syscall.SYS_SYNC_FILE_RANGE": "syscall", - "syscall.SYS_SYSARCH": "syscall", - "syscall.SYS_SYSCALL": "syscall", - "syscall.SYS_SYSCALL_BASE": "syscall", - "syscall.SYS_SYSFS": "syscall", - "syscall.SYS_SYSINFO": "syscall", - "syscall.SYS_SYSLOG": "syscall", - "syscall.SYS_TEE": "syscall", - "syscall.SYS_TGKILL": "syscall", - "syscall.SYS_THREAD_SELFID": "syscall", - "syscall.SYS_THR_CREATE": "syscall", - "syscall.SYS_THR_EXIT": "syscall", - "syscall.SYS_THR_KILL": "syscall", - "syscall.SYS_THR_KILL2": "syscall", - "syscall.SYS_THR_NEW": "syscall", - "syscall.SYS_THR_SELF": "syscall", - "syscall.SYS_THR_SET_NAME": "syscall", - "syscall.SYS_THR_SUSPEND": "syscall", - "syscall.SYS_THR_WAKE": "syscall", - "syscall.SYS_TIME": "syscall", - "syscall.SYS_TIMERFD_CREATE": "syscall", - "syscall.SYS_TIMERFD_GETTIME": "syscall", - "syscall.SYS_TIMERFD_SETTIME": "syscall", - "syscall.SYS_TIMER_CREATE": "syscall", - "syscall.SYS_TIMER_DELETE": "syscall", - "syscall.SYS_TIMER_GETOVERRUN": "syscall", - "syscall.SYS_TIMER_GETTIME": "syscall", - "syscall.SYS_TIMER_SETTIME": "syscall", - "syscall.SYS_TIMES": "syscall", - "syscall.SYS_TKILL": "syscall", - "syscall.SYS_TRUNCATE": "syscall", - "syscall.SYS_TRUNCATE64": "syscall", - "syscall.SYS_TUXCALL": "syscall", - "syscall.SYS_UGETRLIMIT": "syscall", - "syscall.SYS_ULIMIT": "syscall", - "syscall.SYS_UMASK": "syscall", - "syscall.SYS_UMASK_EXTENDED": "syscall", - "syscall.SYS_UMOUNT": "syscall", - "syscall.SYS_UMOUNT2": "syscall", - "syscall.SYS_UNAME": "syscall", - "syscall.SYS_UNDELETE": "syscall", - "syscall.SYS_UNLINK": "syscall", - "syscall.SYS_UNLINKAT": "syscall", - "syscall.SYS_UNMOUNT": "syscall", - "syscall.SYS_UNSHARE": "syscall", - "syscall.SYS_USELIB": "syscall", - "syscall.SYS_USTAT": "syscall", - "syscall.SYS_UTIME": "syscall", - "syscall.SYS_UTIMENSAT": "syscall", - "syscall.SYS_UTIMES": "syscall", - "syscall.SYS_UTRACE": "syscall", - "syscall.SYS_UUIDGEN": "syscall", - "syscall.SYS_VADVISE": "syscall", - "syscall.SYS_VFORK": "syscall", - "syscall.SYS_VHANGUP": "syscall", - "syscall.SYS_VM86": "syscall", - "syscall.SYS_VM86OLD": "syscall", - "syscall.SYS_VMSPLICE": "syscall", - "syscall.SYS_VM_PRESSURE_MONITOR": "syscall", - "syscall.SYS_VSERVER": "syscall", - "syscall.SYS_WAIT4": "syscall", - "syscall.SYS_WAIT4_NOCANCEL": "syscall", - "syscall.SYS_WAIT6": "syscall", - "syscall.SYS_WAITEVENT": "syscall", - "syscall.SYS_WAITID": "syscall", - "syscall.SYS_WAITID_NOCANCEL": "syscall", - "syscall.SYS_WAITPID": "syscall", - "syscall.SYS_WATCHEVENT": "syscall", - "syscall.SYS_WORKQ_KERNRETURN": "syscall", - "syscall.SYS_WORKQ_OPEN": "syscall", - "syscall.SYS_WRITE": "syscall", - "syscall.SYS_WRITEV": "syscall", - "syscall.SYS_WRITEV_NOCANCEL": "syscall", - "syscall.SYS_WRITE_NOCANCEL": "syscall", - "syscall.SYS_YIELD": "syscall", - "syscall.SYS__LLSEEK": "syscall", - "syscall.SYS__LWP_CONTINUE": "syscall", - "syscall.SYS__LWP_CREATE": "syscall", - "syscall.SYS__LWP_CTL": "syscall", - "syscall.SYS__LWP_DETACH": "syscall", - "syscall.SYS__LWP_EXIT": "syscall", - "syscall.SYS__LWP_GETNAME": "syscall", - "syscall.SYS__LWP_GETPRIVATE": "syscall", - "syscall.SYS__LWP_KILL": "syscall", - "syscall.SYS__LWP_PARK": "syscall", - "syscall.SYS__LWP_SELF": "syscall", - "syscall.SYS__LWP_SETNAME": "syscall", - "syscall.SYS__LWP_SETPRIVATE": "syscall", - "syscall.SYS__LWP_SUSPEND": "syscall", - "syscall.SYS__LWP_UNPARK": "syscall", - "syscall.SYS__LWP_UNPARK_ALL": "syscall", - "syscall.SYS__LWP_WAIT": "syscall", - "syscall.SYS__LWP_WAKEUP": "syscall", - "syscall.SYS__NEWSELECT": "syscall", - "syscall.SYS__PSET_BIND": "syscall", - "syscall.SYS__SCHED_GETAFFINITY": "syscall", - "syscall.SYS__SCHED_GETPARAM": "syscall", - "syscall.SYS__SCHED_SETAFFINITY": "syscall", - "syscall.SYS__SCHED_SETPARAM": "syscall", - "syscall.SYS__SYSCTL": "syscall", - "syscall.SYS__UMTX_LOCK": "syscall", - "syscall.SYS__UMTX_OP": "syscall", - "syscall.SYS__UMTX_UNLOCK": "syscall", - "syscall.SYS___ACL_ACLCHECK_FD": "syscall", - "syscall.SYS___ACL_ACLCHECK_FILE": "syscall", - "syscall.SYS___ACL_ACLCHECK_LINK": "syscall", - "syscall.SYS___ACL_DELETE_FD": "syscall", - "syscall.SYS___ACL_DELETE_FILE": "syscall", - "syscall.SYS___ACL_DELETE_LINK": "syscall", - "syscall.SYS___ACL_GET_FD": "syscall", - "syscall.SYS___ACL_GET_FILE": "syscall", - "syscall.SYS___ACL_GET_LINK": "syscall", - "syscall.SYS___ACL_SET_FD": "syscall", - "syscall.SYS___ACL_SET_FILE": "syscall", - "syscall.SYS___ACL_SET_LINK": "syscall", - "syscall.SYS___CLONE": "syscall", - "syscall.SYS___DISABLE_THREADSIGNAL": "syscall", - "syscall.SYS___GETCWD": "syscall", - "syscall.SYS___GETLOGIN": "syscall", - "syscall.SYS___GET_TCB": "syscall", - "syscall.SYS___MAC_EXECVE": "syscall", - "syscall.SYS___MAC_GETFSSTAT": "syscall", - "syscall.SYS___MAC_GET_FD": "syscall", - "syscall.SYS___MAC_GET_FILE": "syscall", - "syscall.SYS___MAC_GET_LCID": "syscall", - "syscall.SYS___MAC_GET_LCTX": "syscall", - "syscall.SYS___MAC_GET_LINK": "syscall", - "syscall.SYS___MAC_GET_MOUNT": "syscall", - "syscall.SYS___MAC_GET_PID": "syscall", - "syscall.SYS___MAC_GET_PROC": "syscall", - "syscall.SYS___MAC_MOUNT": "syscall", - "syscall.SYS___MAC_SET_FD": "syscall", - "syscall.SYS___MAC_SET_FILE": "syscall", - "syscall.SYS___MAC_SET_LCTX": "syscall", - "syscall.SYS___MAC_SET_LINK": "syscall", - "syscall.SYS___MAC_SET_PROC": "syscall", - "syscall.SYS___MAC_SYSCALL": "syscall", - "syscall.SYS___OLD_SEMWAIT_SIGNAL": "syscall", - "syscall.SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL": "syscall", - "syscall.SYS___POSIX_CHOWN": "syscall", - "syscall.SYS___POSIX_FCHOWN": "syscall", - "syscall.SYS___POSIX_LCHOWN": "syscall", - "syscall.SYS___POSIX_RENAME": "syscall", - "syscall.SYS___PTHREAD_CANCELED": "syscall", - "syscall.SYS___PTHREAD_CHDIR": "syscall", - "syscall.SYS___PTHREAD_FCHDIR": "syscall", - "syscall.SYS___PTHREAD_KILL": "syscall", - "syscall.SYS___PTHREAD_MARKCANCEL": "syscall", - "syscall.SYS___PTHREAD_SIGMASK": "syscall", - "syscall.SYS___QUOTACTL": "syscall", - "syscall.SYS___SEMCTL": "syscall", - "syscall.SYS___SEMWAIT_SIGNAL": "syscall", - "syscall.SYS___SEMWAIT_SIGNAL_NOCANCEL": "syscall", - "syscall.SYS___SETLOGIN": "syscall", - "syscall.SYS___SETUGID": "syscall", - "syscall.SYS___SET_TCB": "syscall", - "syscall.SYS___SIGACTION_SIGTRAMP": "syscall", - "syscall.SYS___SIGTIMEDWAIT": "syscall", - "syscall.SYS___SIGWAIT": "syscall", - "syscall.SYS___SIGWAIT_NOCANCEL": "syscall", - "syscall.SYS___SYSCTL": "syscall", - "syscall.SYS___TFORK": "syscall", - "syscall.SYS___THREXIT": "syscall", - "syscall.SYS___THRSIGDIVERT": "syscall", - "syscall.SYS___THRSLEEP": "syscall", - "syscall.SYS___THRWAKEUP": "syscall", - "syscall.S_ARCH1": "syscall", - "syscall.S_ARCH2": "syscall", - "syscall.S_BLKSIZE": "syscall", - "syscall.S_IEXEC": "syscall", - "syscall.S_IFBLK": "syscall", - "syscall.S_IFCHR": "syscall", - "syscall.S_IFDIR": "syscall", - "syscall.S_IFIFO": "syscall", - "syscall.S_IFLNK": "syscall", - "syscall.S_IFMT": "syscall", - "syscall.S_IFREG": "syscall", - "syscall.S_IFSOCK": "syscall", - "syscall.S_IFWHT": "syscall", - "syscall.S_IREAD": "syscall", - "syscall.S_IRGRP": "syscall", - "syscall.S_IROTH": "syscall", - "syscall.S_IRUSR": "syscall", - "syscall.S_IRWXG": "syscall", - "syscall.S_IRWXO": "syscall", - "syscall.S_IRWXU": "syscall", - "syscall.S_ISGID": "syscall", - "syscall.S_ISTXT": "syscall", - "syscall.S_ISUID": "syscall", - "syscall.S_ISVTX": "syscall", - "syscall.S_IWGRP": "syscall", - "syscall.S_IWOTH": "syscall", - "syscall.S_IWRITE": "syscall", - "syscall.S_IWUSR": "syscall", - "syscall.S_IXGRP": "syscall", - "syscall.S_IXOTH": "syscall", - "syscall.S_IXUSR": "syscall", - "syscall.S_LOGIN_SET": "syscall", - "syscall.SecurityAttributes": "syscall", - "syscall.Seek": "syscall", - "syscall.Select": "syscall", - "syscall.Sendfile": "syscall", - "syscall.Sendmsg": "syscall", - "syscall.SendmsgN": "syscall", - "syscall.Sendto": "syscall", - "syscall.Servent": "syscall", - "syscall.SetBpf": "syscall", - "syscall.SetBpfBuflen": "syscall", - "syscall.SetBpfDatalink": "syscall", - "syscall.SetBpfHeadercmpl": "syscall", - "syscall.SetBpfImmediate": "syscall", - "syscall.SetBpfInterface": "syscall", - "syscall.SetBpfPromisc": "syscall", - "syscall.SetBpfTimeout": "syscall", - "syscall.SetCurrentDirectory": "syscall", - "syscall.SetEndOfFile": "syscall", - "syscall.SetEnvironmentVariable": "syscall", - "syscall.SetFileAttributes": "syscall", - "syscall.SetFileCompletionNotificationModes": "syscall", - "syscall.SetFilePointer": "syscall", - "syscall.SetFileTime": "syscall", - "syscall.SetHandleInformation": "syscall", - "syscall.SetKevent": "syscall", - "syscall.SetLsfPromisc": "syscall", - "syscall.SetNonblock": "syscall", - "syscall.Setdomainname": "syscall", - "syscall.Setegid": "syscall", - "syscall.Setenv": "syscall", - "syscall.Seteuid": "syscall", - "syscall.Setfsgid": "syscall", - "syscall.Setfsuid": "syscall", - "syscall.Setgid": "syscall", - "syscall.Setgroups": "syscall", - "syscall.Sethostname": "syscall", - "syscall.Setlogin": "syscall", - "syscall.Setpgid": "syscall", - "syscall.Setpriority": "syscall", - "syscall.Setprivexec": "syscall", - "syscall.Setregid": "syscall", - "syscall.Setresgid": "syscall", - "syscall.Setresuid": "syscall", - "syscall.Setreuid": "syscall", - "syscall.Setrlimit": "syscall", - "syscall.Setsid": "syscall", - "syscall.Setsockopt": "syscall", - "syscall.SetsockoptByte": "syscall", - "syscall.SetsockoptICMPv6Filter": "syscall", - "syscall.SetsockoptIPMreq": "syscall", - "syscall.SetsockoptIPMreqn": "syscall", - "syscall.SetsockoptIPv6Mreq": "syscall", - "syscall.SetsockoptInet4Addr": "syscall", - "syscall.SetsockoptInt": "syscall", - "syscall.SetsockoptLinger": "syscall", - "syscall.SetsockoptString": "syscall", - "syscall.SetsockoptTimeval": "syscall", - "syscall.Settimeofday": "syscall", - "syscall.Setuid": "syscall", - "syscall.Setxattr": "syscall", - "syscall.Shutdown": "syscall", - "syscall.SidTypeAlias": "syscall", - "syscall.SidTypeComputer": "syscall", - "syscall.SidTypeDeletedAccount": "syscall", - "syscall.SidTypeDomain": "syscall", - "syscall.SidTypeGroup": "syscall", - "syscall.SidTypeInvalid": "syscall", - "syscall.SidTypeLabel": "syscall", - "syscall.SidTypeUnknown": "syscall", - "syscall.SidTypeUser": "syscall", - "syscall.SidTypeWellKnownGroup": "syscall", - "syscall.Signal": "syscall", - "syscall.SizeofBpfHdr": "syscall", - "syscall.SizeofBpfInsn": "syscall", - "syscall.SizeofBpfProgram": "syscall", - "syscall.SizeofBpfStat": "syscall", - "syscall.SizeofBpfVersion": "syscall", - "syscall.SizeofBpfZbuf": "syscall", - "syscall.SizeofBpfZbufHeader": "syscall", - "syscall.SizeofCmsghdr": "syscall", - "syscall.SizeofICMPv6Filter": "syscall", - "syscall.SizeofIPMreq": "syscall", - "syscall.SizeofIPMreqn": "syscall", - "syscall.SizeofIPv6MTUInfo": "syscall", - "syscall.SizeofIPv6Mreq": "syscall", - "syscall.SizeofIfAddrmsg": "syscall", - "syscall.SizeofIfAnnounceMsghdr": "syscall", - "syscall.SizeofIfData": "syscall", - "syscall.SizeofIfInfomsg": "syscall", - "syscall.SizeofIfMsghdr": "syscall", - "syscall.SizeofIfaMsghdr": "syscall", - "syscall.SizeofIfmaMsghdr": "syscall", - "syscall.SizeofIfmaMsghdr2": "syscall", - "syscall.SizeofInet4Pktinfo": "syscall", - "syscall.SizeofInet6Pktinfo": "syscall", - "syscall.SizeofInotifyEvent": "syscall", - "syscall.SizeofLinger": "syscall", - "syscall.SizeofMsghdr": "syscall", - "syscall.SizeofNlAttr": "syscall", - "syscall.SizeofNlMsgerr": "syscall", - "syscall.SizeofNlMsghdr": "syscall", - "syscall.SizeofRtAttr": "syscall", - "syscall.SizeofRtGenmsg": "syscall", - "syscall.SizeofRtMetrics": "syscall", - "syscall.SizeofRtMsg": "syscall", - "syscall.SizeofRtMsghdr": "syscall", - "syscall.SizeofRtNexthop": "syscall", - "syscall.SizeofSockFilter": "syscall", - "syscall.SizeofSockFprog": "syscall", - "syscall.SizeofSockaddrAny": "syscall", - "syscall.SizeofSockaddrDatalink": "syscall", - "syscall.SizeofSockaddrInet4": "syscall", - "syscall.SizeofSockaddrInet6": "syscall", - "syscall.SizeofSockaddrLinklayer": "syscall", - "syscall.SizeofSockaddrNetlink": "syscall", - "syscall.SizeofSockaddrUnix": "syscall", - "syscall.SizeofTCPInfo": "syscall", - "syscall.SizeofUcred": "syscall", - "syscall.SlicePtrFromStrings": "syscall", - "syscall.SockFilter": "syscall", - "syscall.SockFprog": "syscall", - "syscall.SockaddrDatalink": "syscall", - "syscall.SockaddrGen": "syscall", - "syscall.SockaddrInet4": "syscall", - "syscall.SockaddrInet6": "syscall", - "syscall.SockaddrLinklayer": "syscall", - "syscall.SockaddrNetlink": "syscall", - "syscall.SockaddrUnix": "syscall", - "syscall.Socket": "syscall", - "syscall.SocketControlMessage": "syscall", - "syscall.SocketDisableIPv6": "syscall", - "syscall.Socketpair": "syscall", - "syscall.Splice": "syscall", - "syscall.StartProcess": "syscall", - "syscall.StartupInfo": "syscall", - "syscall.Stat": "syscall", - "syscall.Stat_t": "syscall", - "syscall.Statfs": "syscall", - "syscall.Statfs_t": "syscall", - "syscall.Stderr": "syscall", - "syscall.Stdin": "syscall", - "syscall.Stdout": "syscall", - "syscall.StringBytePtr": "syscall", - "syscall.StringByteSlice": "syscall", - "syscall.StringSlicePtr": "syscall", - "syscall.StringToSid": "syscall", - "syscall.StringToUTF16": "syscall", - "syscall.StringToUTF16Ptr": "syscall", - "syscall.Symlink": "syscall", - "syscall.Sync": "syscall", - "syscall.SyncFileRange": "syscall", - "syscall.SysProcAttr": "syscall", - "syscall.SysProcIDMap": "syscall", - "syscall.Syscall": "syscall", - "syscall.Syscall12": "syscall", - "syscall.Syscall15": "syscall", - "syscall.Syscall6": "syscall", - "syscall.Syscall9": "syscall", - "syscall.Sysctl": "syscall", - "syscall.SysctlUint32": "syscall", - "syscall.Sysctlnode": "syscall", - "syscall.Sysinfo": "syscall", - "syscall.Sysinfo_t": "syscall", - "syscall.Systemtime": "syscall", - "syscall.TCGETS": "syscall", - "syscall.TCIFLUSH": "syscall", - "syscall.TCIOFLUSH": "syscall", - "syscall.TCOFLUSH": "syscall", - "syscall.TCPInfo": "syscall", - "syscall.TCPKeepalive": "syscall", - "syscall.TCP_CA_NAME_MAX": "syscall", - "syscall.TCP_CONGCTL": "syscall", - "syscall.TCP_CONGESTION": "syscall", - "syscall.TCP_CONNECTIONTIMEOUT": "syscall", - "syscall.TCP_CORK": "syscall", - "syscall.TCP_DEFER_ACCEPT": "syscall", - "syscall.TCP_INFO": "syscall", - "syscall.TCP_KEEPALIVE": "syscall", - "syscall.TCP_KEEPCNT": "syscall", - "syscall.TCP_KEEPIDLE": "syscall", - "syscall.TCP_KEEPINIT": "syscall", - "syscall.TCP_KEEPINTVL": "syscall", - "syscall.TCP_LINGER2": "syscall", - "syscall.TCP_MAXBURST": "syscall", - "syscall.TCP_MAXHLEN": "syscall", - "syscall.TCP_MAXOLEN": "syscall", - "syscall.TCP_MAXSEG": "syscall", - "syscall.TCP_MAXWIN": "syscall", - "syscall.TCP_MAX_SACK": "syscall", - "syscall.TCP_MAX_WINSHIFT": "syscall", - "syscall.TCP_MD5SIG": "syscall", - "syscall.TCP_MD5SIG_MAXKEYLEN": "syscall", - "syscall.TCP_MINMSS": "syscall", - "syscall.TCP_MINMSSOVERLOAD": "syscall", - "syscall.TCP_MSS": "syscall", - "syscall.TCP_NODELAY": "syscall", - "syscall.TCP_NOOPT": "syscall", - "syscall.TCP_NOPUSH": "syscall", - "syscall.TCP_NSTATES": "syscall", - "syscall.TCP_QUICKACK": "syscall", - "syscall.TCP_RXT_CONNDROPTIME": "syscall", - "syscall.TCP_RXT_FINDROP": "syscall", - "syscall.TCP_SACK_ENABLE": "syscall", - "syscall.TCP_SYNCNT": "syscall", - "syscall.TCP_VENDOR": "syscall", - "syscall.TCP_WINDOW_CLAMP": "syscall", - "syscall.TCSAFLUSH": "syscall", - "syscall.TCSETS": "syscall", - "syscall.TF_DISCONNECT": "syscall", - "syscall.TF_REUSE_SOCKET": "syscall", - "syscall.TF_USE_DEFAULT_WORKER": "syscall", - "syscall.TF_USE_KERNEL_APC": "syscall", - "syscall.TF_USE_SYSTEM_THREAD": "syscall", - "syscall.TF_WRITE_BEHIND": "syscall", - "syscall.TH32CS_INHERIT": "syscall", - "syscall.TH32CS_SNAPALL": "syscall", - "syscall.TH32CS_SNAPHEAPLIST": "syscall", - "syscall.TH32CS_SNAPMODULE": "syscall", - "syscall.TH32CS_SNAPMODULE32": "syscall", - "syscall.TH32CS_SNAPPROCESS": "syscall", - "syscall.TH32CS_SNAPTHREAD": "syscall", - "syscall.TIME_ZONE_ID_DAYLIGHT": "syscall", - "syscall.TIME_ZONE_ID_STANDARD": "syscall", - "syscall.TIME_ZONE_ID_UNKNOWN": "syscall", - "syscall.TIOCCBRK": "syscall", - "syscall.TIOCCDTR": "syscall", - "syscall.TIOCCONS": "syscall", - "syscall.TIOCDCDTIMESTAMP": "syscall", - "syscall.TIOCDRAIN": "syscall", - "syscall.TIOCDSIMICROCODE": "syscall", - "syscall.TIOCEXCL": "syscall", - "syscall.TIOCEXT": "syscall", - "syscall.TIOCFLAG_CDTRCTS": "syscall", - "syscall.TIOCFLAG_CLOCAL": "syscall", - "syscall.TIOCFLAG_CRTSCTS": "syscall", - "syscall.TIOCFLAG_MDMBUF": "syscall", - "syscall.TIOCFLAG_PPS": "syscall", - "syscall.TIOCFLAG_SOFTCAR": "syscall", - "syscall.TIOCFLUSH": "syscall", - "syscall.TIOCGDEV": "syscall", - "syscall.TIOCGDRAINWAIT": "syscall", - "syscall.TIOCGETA": "syscall", - "syscall.TIOCGETD": "syscall", - "syscall.TIOCGFLAGS": "syscall", - "syscall.TIOCGICOUNT": "syscall", - "syscall.TIOCGLCKTRMIOS": "syscall", - "syscall.TIOCGLINED": "syscall", - "syscall.TIOCGPGRP": "syscall", - "syscall.TIOCGPTN": "syscall", - "syscall.TIOCGQSIZE": "syscall", - "syscall.TIOCGRANTPT": "syscall", - "syscall.TIOCGRS485": "syscall", - "syscall.TIOCGSERIAL": "syscall", - "syscall.TIOCGSID": "syscall", - "syscall.TIOCGSIZE": "syscall", - "syscall.TIOCGSOFTCAR": "syscall", - "syscall.TIOCGTSTAMP": "syscall", - "syscall.TIOCGWINSZ": "syscall", - "syscall.TIOCINQ": "syscall", - "syscall.TIOCIXOFF": "syscall", - "syscall.TIOCIXON": "syscall", - "syscall.TIOCLINUX": "syscall", - "syscall.TIOCMBIC": "syscall", - "syscall.TIOCMBIS": "syscall", - "syscall.TIOCMGDTRWAIT": "syscall", - "syscall.TIOCMGET": "syscall", - "syscall.TIOCMIWAIT": "syscall", - "syscall.TIOCMODG": "syscall", - "syscall.TIOCMODS": "syscall", - "syscall.TIOCMSDTRWAIT": "syscall", - "syscall.TIOCMSET": "syscall", - "syscall.TIOCM_CAR": "syscall", - "syscall.TIOCM_CD": "syscall", - "syscall.TIOCM_CTS": "syscall", - "syscall.TIOCM_DCD": "syscall", - "syscall.TIOCM_DSR": "syscall", - "syscall.TIOCM_DTR": "syscall", - "syscall.TIOCM_LE": "syscall", - "syscall.TIOCM_RI": "syscall", - "syscall.TIOCM_RNG": "syscall", - "syscall.TIOCM_RTS": "syscall", - "syscall.TIOCM_SR": "syscall", - "syscall.TIOCM_ST": "syscall", - "syscall.TIOCNOTTY": "syscall", - "syscall.TIOCNXCL": "syscall", - "syscall.TIOCOUTQ": "syscall", - "syscall.TIOCPKT": "syscall", - "syscall.TIOCPKT_DATA": "syscall", - "syscall.TIOCPKT_DOSTOP": "syscall", - "syscall.TIOCPKT_FLUSHREAD": "syscall", - "syscall.TIOCPKT_FLUSHWRITE": "syscall", - "syscall.TIOCPKT_IOCTL": "syscall", - "syscall.TIOCPKT_NOSTOP": "syscall", - "syscall.TIOCPKT_START": "syscall", - "syscall.TIOCPKT_STOP": "syscall", - "syscall.TIOCPTMASTER": "syscall", - "syscall.TIOCPTMGET": "syscall", - "syscall.TIOCPTSNAME": "syscall", - "syscall.TIOCPTYGNAME": "syscall", - "syscall.TIOCPTYGRANT": "syscall", - "syscall.TIOCPTYUNLK": "syscall", - "syscall.TIOCRCVFRAME": "syscall", - "syscall.TIOCREMOTE": "syscall", - "syscall.TIOCSBRK": "syscall", - "syscall.TIOCSCONS": "syscall", - "syscall.TIOCSCTTY": "syscall", - "syscall.TIOCSDRAINWAIT": "syscall", - "syscall.TIOCSDTR": "syscall", - "syscall.TIOCSERCONFIG": "syscall", - "syscall.TIOCSERGETLSR": "syscall", - "syscall.TIOCSERGETMULTI": "syscall", - "syscall.TIOCSERGSTRUCT": "syscall", - "syscall.TIOCSERGWILD": "syscall", - "syscall.TIOCSERSETMULTI": "syscall", - "syscall.TIOCSERSWILD": "syscall", - "syscall.TIOCSER_TEMT": "syscall", - "syscall.TIOCSETA": "syscall", - "syscall.TIOCSETAF": "syscall", - "syscall.TIOCSETAW": "syscall", - "syscall.TIOCSETD": "syscall", - "syscall.TIOCSFLAGS": "syscall", - "syscall.TIOCSIG": "syscall", - "syscall.TIOCSLCKTRMIOS": "syscall", - "syscall.TIOCSLINED": "syscall", - "syscall.TIOCSPGRP": "syscall", - "syscall.TIOCSPTLCK": "syscall", - "syscall.TIOCSQSIZE": "syscall", - "syscall.TIOCSRS485": "syscall", - "syscall.TIOCSSERIAL": "syscall", - "syscall.TIOCSSIZE": "syscall", - "syscall.TIOCSSOFTCAR": "syscall", - "syscall.TIOCSTART": "syscall", - "syscall.TIOCSTAT": "syscall", - "syscall.TIOCSTI": "syscall", - "syscall.TIOCSTOP": "syscall", - "syscall.TIOCSTSTAMP": "syscall", - "syscall.TIOCSWINSZ": "syscall", - "syscall.TIOCTIMESTAMP": "syscall", - "syscall.TIOCUCNTL": "syscall", - "syscall.TIOCVHANGUP": "syscall", - "syscall.TIOCXMTFRAME": "syscall", - "syscall.TOKEN_ADJUST_DEFAULT": "syscall", - "syscall.TOKEN_ADJUST_GROUPS": "syscall", - "syscall.TOKEN_ADJUST_PRIVILEGES": "syscall", - "syscall.TOKEN_ALL_ACCESS": "syscall", - "syscall.TOKEN_ASSIGN_PRIMARY": "syscall", - "syscall.TOKEN_DUPLICATE": "syscall", - "syscall.TOKEN_EXECUTE": "syscall", - "syscall.TOKEN_IMPERSONATE": "syscall", - "syscall.TOKEN_QUERY": "syscall", - "syscall.TOKEN_QUERY_SOURCE": "syscall", - "syscall.TOKEN_READ": "syscall", - "syscall.TOKEN_WRITE": "syscall", - "syscall.TOSTOP": "syscall", - "syscall.TRUNCATE_EXISTING": "syscall", - "syscall.TUNATTACHFILTER": "syscall", - "syscall.TUNDETACHFILTER": "syscall", - "syscall.TUNGETFEATURES": "syscall", - "syscall.TUNGETIFF": "syscall", - "syscall.TUNGETSNDBUF": "syscall", - "syscall.TUNGETVNETHDRSZ": "syscall", - "syscall.TUNSETDEBUG": "syscall", - "syscall.TUNSETGROUP": "syscall", - "syscall.TUNSETIFF": "syscall", - "syscall.TUNSETLINK": "syscall", - "syscall.TUNSETNOCSUM": "syscall", - "syscall.TUNSETOFFLOAD": "syscall", - "syscall.TUNSETOWNER": "syscall", - "syscall.TUNSETPERSIST": "syscall", - "syscall.TUNSETSNDBUF": "syscall", - "syscall.TUNSETTXFILTER": "syscall", - "syscall.TUNSETVNETHDRSZ": "syscall", - "syscall.Tee": "syscall", - "syscall.TerminateProcess": "syscall", - "syscall.Termios": "syscall", - "syscall.Tgkill": "syscall", - "syscall.Time": "syscall", - "syscall.Time_t": "syscall", - "syscall.Times": "syscall", - "syscall.Timespec": "syscall", - "syscall.TimespecToNsec": "syscall", - "syscall.Timeval": "syscall", - "syscall.Timeval32": "syscall", - "syscall.TimevalToNsec": "syscall", - "syscall.Timex": "syscall", - "syscall.Timezoneinformation": "syscall", - "syscall.Tms": "syscall", - "syscall.Token": "syscall", - "syscall.TokenAccessInformation": "syscall", - "syscall.TokenAuditPolicy": "syscall", - "syscall.TokenDefaultDacl": "syscall", - "syscall.TokenElevation": "syscall", - "syscall.TokenElevationType": "syscall", - "syscall.TokenGroups": "syscall", - "syscall.TokenGroupsAndPrivileges": "syscall", - "syscall.TokenHasRestrictions": "syscall", - "syscall.TokenImpersonationLevel": "syscall", - "syscall.TokenIntegrityLevel": "syscall", - "syscall.TokenLinkedToken": "syscall", - "syscall.TokenLogonSid": "syscall", - "syscall.TokenMandatoryPolicy": "syscall", - "syscall.TokenOrigin": "syscall", - "syscall.TokenOwner": "syscall", - "syscall.TokenPrimaryGroup": "syscall", - "syscall.TokenPrivileges": "syscall", - "syscall.TokenRestrictedSids": "syscall", - "syscall.TokenSandBoxInert": "syscall", - "syscall.TokenSessionId": "syscall", - "syscall.TokenSessionReference": "syscall", - "syscall.TokenSource": "syscall", - "syscall.TokenStatistics": "syscall", - "syscall.TokenType": "syscall", - "syscall.TokenUIAccess": "syscall", - "syscall.TokenUser": "syscall", - "syscall.TokenVirtualizationAllowed": "syscall", - "syscall.TokenVirtualizationEnabled": "syscall", - "syscall.Tokenprimarygroup": "syscall", - "syscall.Tokenuser": "syscall", - "syscall.TranslateAccountName": "syscall", - "syscall.TranslateName": "syscall", - "syscall.TransmitFile": "syscall", - "syscall.TransmitFileBuffers": "syscall", - "syscall.Truncate": "syscall", - "syscall.USAGE_MATCH_TYPE_AND": "syscall", - "syscall.USAGE_MATCH_TYPE_OR": "syscall", - "syscall.UTF16FromString": "syscall", - "syscall.UTF16PtrFromString": "syscall", - "syscall.UTF16ToString": "syscall", - "syscall.Ucred": "syscall", - "syscall.Umask": "syscall", - "syscall.Uname": "syscall", - "syscall.Undelete": "syscall", - "syscall.UnixCredentials": "syscall", - "syscall.UnixRights": "syscall", - "syscall.Unlink": "syscall", - "syscall.Unlinkat": "syscall", - "syscall.UnmapViewOfFile": "syscall", - "syscall.Unmount": "syscall", - "syscall.Unsetenv": "syscall", - "syscall.Unshare": "syscall", - "syscall.UserInfo10": "syscall", - "syscall.Ustat": "syscall", - "syscall.Ustat_t": "syscall", - "syscall.Utimbuf": "syscall", - "syscall.Utime": "syscall", - "syscall.Utimes": "syscall", - "syscall.UtimesNano": "syscall", - "syscall.Utsname": "syscall", - "syscall.VDISCARD": "syscall", - "syscall.VDSUSP": "syscall", - "syscall.VEOF": "syscall", - "syscall.VEOL": "syscall", - "syscall.VEOL2": "syscall", - "syscall.VERASE": "syscall", - "syscall.VERASE2": "syscall", - "syscall.VINTR": "syscall", - "syscall.VKILL": "syscall", - "syscall.VLNEXT": "syscall", - "syscall.VMIN": "syscall", - "syscall.VQUIT": "syscall", - "syscall.VREPRINT": "syscall", - "syscall.VSTART": "syscall", - "syscall.VSTATUS": "syscall", - "syscall.VSTOP": "syscall", - "syscall.VSUSP": "syscall", - "syscall.VSWTC": "syscall", - "syscall.VT0": "syscall", - "syscall.VT1": "syscall", - "syscall.VTDLY": "syscall", - "syscall.VTIME": "syscall", - "syscall.VWERASE": "syscall", - "syscall.VirtualLock": "syscall", - "syscall.VirtualUnlock": "syscall", - "syscall.WAIT_ABANDONED": "syscall", - "syscall.WAIT_FAILED": "syscall", - "syscall.WAIT_OBJECT_0": "syscall", - "syscall.WAIT_TIMEOUT": "syscall", - "syscall.WALL": "syscall", - "syscall.WALLSIG": "syscall", - "syscall.WALTSIG": "syscall", - "syscall.WCLONE": "syscall", - "syscall.WCONTINUED": "syscall", - "syscall.WCOREFLAG": "syscall", - "syscall.WEXITED": "syscall", - "syscall.WLINUXCLONE": "syscall", - "syscall.WNOHANG": "syscall", - "syscall.WNOTHREAD": "syscall", - "syscall.WNOWAIT": "syscall", - "syscall.WNOZOMBIE": "syscall", - "syscall.WOPTSCHECKED": "syscall", - "syscall.WORDSIZE": "syscall", - "syscall.WSABuf": "syscall", - "syscall.WSACleanup": "syscall", - "syscall.WSADESCRIPTION_LEN": "syscall", - "syscall.WSAData": "syscall", - "syscall.WSAEACCES": "syscall", - "syscall.WSAECONNRESET": "syscall", - "syscall.WSAEnumProtocols": "syscall", - "syscall.WSAID_CONNECTEX": "syscall", - "syscall.WSAIoctl": "syscall", - "syscall.WSAPROTOCOL_LEN": "syscall", - "syscall.WSAProtocolChain": "syscall", - "syscall.WSAProtocolInfo": "syscall", - "syscall.WSARecv": "syscall", - "syscall.WSARecvFrom": "syscall", - "syscall.WSASYS_STATUS_LEN": "syscall", - "syscall.WSASend": "syscall", - "syscall.WSASendTo": "syscall", - "syscall.WSASendto": "syscall", - "syscall.WSAStartup": "syscall", - "syscall.WSTOPPED": "syscall", - "syscall.WTRAPPED": "syscall", - "syscall.WUNTRACED": "syscall", - "syscall.Wait4": "syscall", - "syscall.WaitForSingleObject": "syscall", - "syscall.WaitStatus": "syscall", - "syscall.Win32FileAttributeData": "syscall", - "syscall.Win32finddata": "syscall", - "syscall.Write": "syscall", - "syscall.WriteConsole": "syscall", - "syscall.WriteFile": "syscall", - "syscall.X509_ASN_ENCODING": "syscall", - "syscall.XCASE": "syscall", - "syscall.XP1_CONNECTIONLESS": "syscall", - "syscall.XP1_CONNECT_DATA": "syscall", - "syscall.XP1_DISCONNECT_DATA": "syscall", - "syscall.XP1_EXPEDITED_DATA": "syscall", - "syscall.XP1_GRACEFUL_CLOSE": "syscall", - "syscall.XP1_GUARANTEED_DELIVERY": "syscall", - "syscall.XP1_GUARANTEED_ORDER": "syscall", - "syscall.XP1_IFS_HANDLES": "syscall", - "syscall.XP1_MESSAGE_ORIENTED": "syscall", - "syscall.XP1_MULTIPOINT_CONTROL_PLANE": "syscall", - "syscall.XP1_MULTIPOINT_DATA_PLANE": "syscall", - "syscall.XP1_PARTIAL_MESSAGE": "syscall", - "syscall.XP1_PSEUDO_STREAM": "syscall", - "syscall.XP1_QOS_SUPPORTED": "syscall", - "syscall.XP1_SAN_SUPPORT_SDP": "syscall", - "syscall.XP1_SUPPORT_BROADCAST": "syscall", - "syscall.XP1_SUPPORT_MULTIPOINT": "syscall", - "syscall.XP1_UNI_RECV": "syscall", - "syscall.XP1_UNI_SEND": "syscall", - "syslog.Dial": "log/syslog", - "syslog.LOG_ALERT": "log/syslog", - "syslog.LOG_AUTH": "log/syslog", - "syslog.LOG_AUTHPRIV": "log/syslog", - "syslog.LOG_CRIT": "log/syslog", - "syslog.LOG_CRON": "log/syslog", - "syslog.LOG_DAEMON": "log/syslog", - "syslog.LOG_DEBUG": "log/syslog", - "syslog.LOG_EMERG": "log/syslog", - "syslog.LOG_ERR": "log/syslog", - "syslog.LOG_FTP": "log/syslog", - "syslog.LOG_INFO": "log/syslog", - "syslog.LOG_KERN": "log/syslog", - "syslog.LOG_LOCAL0": "log/syslog", - "syslog.LOG_LOCAL1": "log/syslog", - "syslog.LOG_LOCAL2": "log/syslog", - "syslog.LOG_LOCAL3": "log/syslog", - "syslog.LOG_LOCAL4": "log/syslog", - "syslog.LOG_LOCAL5": "log/syslog", - "syslog.LOG_LOCAL6": "log/syslog", - "syslog.LOG_LOCAL7": "log/syslog", - "syslog.LOG_LPR": "log/syslog", - "syslog.LOG_MAIL": "log/syslog", - "syslog.LOG_NEWS": "log/syslog", - "syslog.LOG_NOTICE": "log/syslog", - "syslog.LOG_SYSLOG": "log/syslog", - "syslog.LOG_USER": "log/syslog", - "syslog.LOG_UUCP": "log/syslog", - "syslog.LOG_WARNING": "log/syslog", - "syslog.New": "log/syslog", - "syslog.NewLogger": "log/syslog", - "syslog.Priority": "log/syslog", - "syslog.Writer": "log/syslog", - "tabwriter.AlignRight": "text/tabwriter", - "tabwriter.Debug": "text/tabwriter", - "tabwriter.DiscardEmptyColumns": "text/tabwriter", - "tabwriter.Escape": "text/tabwriter", - "tabwriter.FilterHTML": "text/tabwriter", - "tabwriter.NewWriter": "text/tabwriter", - "tabwriter.StripEscape": "text/tabwriter", - "tabwriter.TabIndent": "text/tabwriter", - "tabwriter.Writer": "text/tabwriter", - "tar.ErrFieldTooLong": "archive/tar", - "tar.ErrHeader": "archive/tar", - "tar.ErrWriteAfterClose": "archive/tar", - "tar.ErrWriteTooLong": "archive/tar", - "tar.FileInfoHeader": "archive/tar", - "tar.Header": "archive/tar", - "tar.NewReader": "archive/tar", - "tar.NewWriter": "archive/tar", - "tar.Reader": "archive/tar", - "tar.TypeBlock": "archive/tar", - "tar.TypeChar": "archive/tar", - "tar.TypeCont": "archive/tar", - "tar.TypeDir": "archive/tar", - "tar.TypeFifo": "archive/tar", - "tar.TypeGNULongLink": "archive/tar", - "tar.TypeGNULongName": "archive/tar", - "tar.TypeGNUSparse": "archive/tar", - "tar.TypeLink": "archive/tar", - "tar.TypeReg": "archive/tar", - "tar.TypeRegA": "archive/tar", - "tar.TypeSymlink": "archive/tar", - "tar.TypeXGlobalHeader": "archive/tar", - "tar.TypeXHeader": "archive/tar", - "tar.Writer": "archive/tar", - "template.CSS": "html/template", - "template.ErrAmbigContext": "html/template", - "template.ErrBadHTML": "html/template", - "template.ErrBranchEnd": "html/template", - "template.ErrEndContext": "html/template", - "template.ErrNoSuchTemplate": "html/template", - "template.ErrOutputContext": "html/template", - "template.ErrPartialCharset": "html/template", - "template.ErrPartialEscape": "html/template", - "template.ErrRangeLoopReentry": "html/template", - "template.ErrSlashAmbig": "html/template", - "template.Error": "html/template", - "template.ErrorCode": "html/template", - // "template.FuncMap" is ambiguous - "template.HTML": "html/template", - "template.HTMLAttr": "html/template", - // "template.HTMLEscape" is ambiguous - // "template.HTMLEscapeString" is ambiguous - // "template.HTMLEscaper" is ambiguous - "template.JS": "html/template", - // "template.JSEscape" is ambiguous - // "template.JSEscapeString" is ambiguous - // "template.JSEscaper" is ambiguous - "template.JSStr": "html/template", - // "template.Must" is ambiguous - // "template.New" is ambiguous - "template.OK": "html/template", - // "template.ParseFiles" is ambiguous - // "template.ParseGlob" is ambiguous - // "template.Template" is ambiguous - "template.URL": "html/template", - // "template.URLQueryEscaper" is ambiguous - "testing.AllocsPerRun": "testing", - "testing.B": "testing", - "testing.Benchmark": "testing", - "testing.BenchmarkResult": "testing", - "testing.Cover": "testing", - "testing.CoverBlock": "testing", - "testing.Coverage": "testing", - "testing.InternalBenchmark": "testing", - "testing.InternalExample": "testing", - "testing.InternalTest": "testing", - "testing.M": "testing", - "testing.Main": "testing", - "testing.MainStart": "testing", - "testing.PB": "testing", - "testing.RegisterCover": "testing", - "testing.RunBenchmarks": "testing", - "testing.RunExamples": "testing", - "testing.RunTests": "testing", - "testing.Short": "testing", - "testing.T": "testing", - "testing.Verbose": "testing", - "textproto.CanonicalMIMEHeaderKey": "net/textproto", - "textproto.Conn": "net/textproto", - "textproto.Dial": "net/textproto", - "textproto.Error": "net/textproto", - "textproto.MIMEHeader": "net/textproto", - "textproto.NewConn": "net/textproto", - "textproto.NewReader": "net/textproto", - "textproto.NewWriter": "net/textproto", - "textproto.Pipeline": "net/textproto", - "textproto.ProtocolError": "net/textproto", - "textproto.Reader": "net/textproto", - "textproto.TrimBytes": "net/textproto", - "textproto.TrimString": "net/textproto", - "textproto.Writer": "net/textproto", - "time.ANSIC": "time", - "time.After": "time", - "time.AfterFunc": "time", - "time.April": "time", - "time.August": "time", - "time.Date": "time", - "time.December": "time", - "time.Duration": "time", - "time.February": "time", - "time.FixedZone": "time", - "time.Friday": "time", - "time.Hour": "time", - "time.January": "time", - "time.July": "time", - "time.June": "time", - "time.Kitchen": "time", - "time.LoadLocation": "time", - "time.Local": "time", - "time.Location": "time", - "time.March": "time", - "time.May": "time", - "time.Microsecond": "time", - "time.Millisecond": "time", - "time.Minute": "time", - "time.Monday": "time", - "time.Month": "time", - "time.Nanosecond": "time", - "time.NewTicker": "time", - "time.NewTimer": "time", - "time.November": "time", - "time.Now": "time", - "time.October": "time", - "time.Parse": "time", - "time.ParseDuration": "time", - "time.ParseError": "time", - "time.ParseInLocation": "time", - "time.RFC1123": "time", - "time.RFC1123Z": "time", - "time.RFC3339": "time", - "time.RFC3339Nano": "time", - "time.RFC822": "time", - "time.RFC822Z": "time", - "time.RFC850": "time", - "time.RubyDate": "time", - "time.Saturday": "time", - "time.Second": "time", - "time.September": "time", - "time.Since": "time", - "time.Sleep": "time", - "time.Stamp": "time", - "time.StampMicro": "time", - "time.StampMilli": "time", - "time.StampNano": "time", - "time.Sunday": "time", - "time.Thursday": "time", - "time.Tick": "time", - "time.Ticker": "time", - "time.Time": "time", - "time.Timer": "time", - "time.Tuesday": "time", - "time.UTC": "time", - "time.Unix": "time", - "time.UnixDate": "time", - "time.Wednesday": "time", - "time.Weekday": "time", - "tls.Certificate": "crypto/tls", - "tls.Client": "crypto/tls", - "tls.ClientAuthType": "crypto/tls", - "tls.ClientHelloInfo": "crypto/tls", - "tls.ClientSessionCache": "crypto/tls", - "tls.ClientSessionState": "crypto/tls", - "tls.Config": "crypto/tls", - "tls.Conn": "crypto/tls", - "tls.ConnectionState": "crypto/tls", - "tls.CurveID": "crypto/tls", - "tls.CurveP256": "crypto/tls", - "tls.CurveP384": "crypto/tls", - "tls.CurveP521": "crypto/tls", - "tls.Dial": "crypto/tls", - "tls.DialWithDialer": "crypto/tls", - "tls.Listen": "crypto/tls", - "tls.LoadX509KeyPair": "crypto/tls", - "tls.NewLRUClientSessionCache": "crypto/tls", - "tls.NewListener": "crypto/tls", - "tls.NoClientCert": "crypto/tls", - "tls.RequestClientCert": "crypto/tls", - "tls.RequireAndVerifyClientCert": "crypto/tls", - "tls.RequireAnyClientCert": "crypto/tls", - "tls.Server": "crypto/tls", - "tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": "crypto/tls", - "tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": "crypto/tls", - "tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": "crypto/tls", - "tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": "crypto/tls", - "tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": "crypto/tls", - "tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": "crypto/tls", - "tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": "crypto/tls", - "tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": "crypto/tls", - "tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": "crypto/tls", - "tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": "crypto/tls", - "tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA": "crypto/tls", - "tls.TLS_FALLBACK_SCSV": "crypto/tls", - "tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA": "crypto/tls", - "tls.TLS_RSA_WITH_AES_128_CBC_SHA": "crypto/tls", - "tls.TLS_RSA_WITH_AES_256_CBC_SHA": "crypto/tls", - "tls.TLS_RSA_WITH_RC4_128_SHA": "crypto/tls", - "tls.VerifyClientCertIfGiven": "crypto/tls", - "tls.VersionSSL30": "crypto/tls", - "tls.VersionTLS10": "crypto/tls", - "tls.VersionTLS11": "crypto/tls", - "tls.VersionTLS12": "crypto/tls", - "tls.X509KeyPair": "crypto/tls", - "token.ADD": "go/token", - "token.ADD_ASSIGN": "go/token", - "token.AND": "go/token", - "token.AND_ASSIGN": "go/token", - "token.AND_NOT": "go/token", - "token.AND_NOT_ASSIGN": "go/token", - "token.ARROW": "go/token", - "token.ASSIGN": "go/token", - "token.BREAK": "go/token", - "token.CASE": "go/token", - "token.CHAN": "go/token", - "token.CHAR": "go/token", - "token.COLON": "go/token", - "token.COMMA": "go/token", - "token.COMMENT": "go/token", - "token.CONST": "go/token", - "token.CONTINUE": "go/token", - "token.DEC": "go/token", - "token.DEFAULT": "go/token", - "token.DEFER": "go/token", - "token.DEFINE": "go/token", - "token.ELLIPSIS": "go/token", - "token.ELSE": "go/token", - "token.EOF": "go/token", - "token.EQL": "go/token", - "token.FALLTHROUGH": "go/token", - "token.FLOAT": "go/token", - "token.FOR": "go/token", - "token.FUNC": "go/token", - "token.File": "go/token", - "token.FileSet": "go/token", - "token.GEQ": "go/token", - "token.GO": "go/token", - "token.GOTO": "go/token", - "token.GTR": "go/token", - "token.HighestPrec": "go/token", - "token.IDENT": "go/token", - "token.IF": "go/token", - "token.ILLEGAL": "go/token", - "token.IMAG": "go/token", - "token.IMPORT": "go/token", - "token.INC": "go/token", - "token.INT": "go/token", - "token.INTERFACE": "go/token", - "token.LAND": "go/token", - "token.LBRACE": "go/token", - "token.LBRACK": "go/token", - "token.LEQ": "go/token", - "token.LOR": "go/token", - "token.LPAREN": "go/token", - "token.LSS": "go/token", - "token.Lookup": "go/token", - "token.LowestPrec": "go/token", - "token.MAP": "go/token", - "token.MUL": "go/token", - "token.MUL_ASSIGN": "go/token", - "token.NEQ": "go/token", - "token.NOT": "go/token", - "token.NewFileSet": "go/token", - "token.NoPos": "go/token", - "token.OR": "go/token", - "token.OR_ASSIGN": "go/token", - "token.PACKAGE": "go/token", - "token.PERIOD": "go/token", - "token.Pos": "go/token", - "token.Position": "go/token", - "token.QUO": "go/token", - "token.QUO_ASSIGN": "go/token", - "token.RANGE": "go/token", - "token.RBRACE": "go/token", - "token.RBRACK": "go/token", - "token.REM": "go/token", - "token.REM_ASSIGN": "go/token", - "token.RETURN": "go/token", - "token.RPAREN": "go/token", - "token.SELECT": "go/token", - "token.SEMICOLON": "go/token", - "token.SHL": "go/token", - "token.SHL_ASSIGN": "go/token", - "token.SHR": "go/token", - "token.SHR_ASSIGN": "go/token", - "token.STRING": "go/token", - "token.STRUCT": "go/token", - "token.SUB": "go/token", - "token.SUB_ASSIGN": "go/token", - "token.SWITCH": "go/token", - "token.TYPE": "go/token", - "token.Token": "go/token", - "token.UnaryPrec": "go/token", - "token.VAR": "go/token", - "token.XOR": "go/token", - "token.XOR_ASSIGN": "go/token", - "trace.Start": "runtime/trace", - "trace.Stop": "runtime/trace", - "types.Array": "go/types", - "types.AssertableTo": "go/types", - "types.AssignableTo": "go/types", - "types.Basic": "go/types", - "types.BasicInfo": "go/types", - "types.BasicKind": "go/types", - "types.Bool": "go/types", - "types.Builtin": "go/types", - "types.Byte": "go/types", - "types.Chan": "go/types", - "types.ChanDir": "go/types", - "types.Checker": "go/types", - "types.Comparable": "go/types", - "types.Complex128": "go/types", - "types.Complex64": "go/types", - "types.Config": "go/types", - "types.Const": "go/types", - "types.ConvertibleTo": "go/types", - "types.DefPredeclaredTestFuncs": "go/types", - "types.Error": "go/types", - "types.Eval": "go/types", - "types.ExprString": "go/types", - "types.FieldVal": "go/types", - "types.Float32": "go/types", - "types.Float64": "go/types", - "types.Func": "go/types", - "types.Id": "go/types", - "types.Identical": "go/types", - "types.Implements": "go/types", - "types.Importer": "go/types", - "types.Info": "go/types", - "types.Initializer": "go/types", - "types.Int": "go/types", - "types.Int16": "go/types", - "types.Int32": "go/types", - "types.Int64": "go/types", - "types.Int8": "go/types", - "types.Interface": "go/types", - "types.Invalid": "go/types", - "types.IsBoolean": "go/types", - "types.IsComplex": "go/types", - "types.IsConstType": "go/types", - "types.IsFloat": "go/types", - "types.IsInteger": "go/types", - "types.IsInterface": "go/types", - "types.IsNumeric": "go/types", - "types.IsOrdered": "go/types", - "types.IsString": "go/types", - "types.IsUnsigned": "go/types", - "types.IsUntyped": "go/types", - "types.Label": "go/types", - "types.LookupFieldOrMethod": "go/types", - "types.Map": "go/types", - "types.MethodExpr": "go/types", - "types.MethodSet": "go/types", - "types.MethodVal": "go/types", - "types.MissingMethod": "go/types", - "types.Named": "go/types", - "types.NewArray": "go/types", - "types.NewChan": "go/types", - "types.NewChecker": "go/types", - "types.NewConst": "go/types", - "types.NewField": "go/types", - "types.NewFunc": "go/types", - "types.NewInterface": "go/types", - "types.NewLabel": "go/types", - "types.NewMap": "go/types", - "types.NewMethodSet": "go/types", - "types.NewNamed": "go/types", - "types.NewPackage": "go/types", - "types.NewParam": "go/types", - "types.NewPkgName": "go/types", - "types.NewPointer": "go/types", - "types.NewScope": "go/types", - "types.NewSignature": "go/types", - "types.NewSlice": "go/types", - "types.NewStruct": "go/types", - "types.NewTuple": "go/types", - "types.NewTypeName": "go/types", - "types.NewVar": "go/types", - "types.Nil": "go/types", - "types.ObjectString": "go/types", - "types.Package": "go/types", - "types.PkgName": "go/types", - "types.Pointer": "go/types", - "types.Qualifier": "go/types", - "types.RecvOnly": "go/types", - "types.RelativeTo": "go/types", - "types.Rune": "go/types", - "types.Scope": "go/types", - "types.Selection": "go/types", - "types.SelectionKind": "go/types", - "types.SelectionString": "go/types", - "types.SendOnly": "go/types", - "types.SendRecv": "go/types", - "types.Signature": "go/types", - "types.Sizes": "go/types", - "types.Slice": "go/types", - "types.StdSizes": "go/types", - "types.String": "go/types", - "types.Struct": "go/types", - "types.Tuple": "go/types", - "types.Typ": "go/types", - "types.Type": "go/types", - "types.TypeAndValue": "go/types", - "types.TypeName": "go/types", - "types.TypeString": "go/types", - "types.Uint": "go/types", - "types.Uint16": "go/types", - "types.Uint32": "go/types", - "types.Uint64": "go/types", - "types.Uint8": "go/types", - "types.Uintptr": "go/types", - "types.Universe": "go/types", - "types.Unsafe": "go/types", - "types.UnsafePointer": "go/types", - "types.UntypedBool": "go/types", - "types.UntypedComplex": "go/types", - "types.UntypedFloat": "go/types", - "types.UntypedInt": "go/types", - "types.UntypedNil": "go/types", - "types.UntypedRune": "go/types", - "types.UntypedString": "go/types", - "types.Var": "go/types", - "types.WriteExpr": "go/types", - "types.WriteSignature": "go/types", - "types.WriteType": "go/types", - "unicode.ASCII_Hex_Digit": "unicode", - "unicode.Ahom": "unicode", - "unicode.Anatolian_Hieroglyphs": "unicode", - "unicode.Arabic": "unicode", - "unicode.Armenian": "unicode", - "unicode.Avestan": "unicode", - "unicode.AzeriCase": "unicode", - "unicode.Balinese": "unicode", - "unicode.Bamum": "unicode", - "unicode.Bassa_Vah": "unicode", - "unicode.Batak": "unicode", - "unicode.Bengali": "unicode", - "unicode.Bidi_Control": "unicode", - "unicode.Bopomofo": "unicode", - "unicode.Brahmi": "unicode", - "unicode.Braille": "unicode", - "unicode.Buginese": "unicode", - "unicode.Buhid": "unicode", - "unicode.C": "unicode", - "unicode.Canadian_Aboriginal": "unicode", - "unicode.Carian": "unicode", - "unicode.CaseRange": "unicode", - "unicode.CaseRanges": "unicode", - "unicode.Categories": "unicode", - "unicode.Caucasian_Albanian": "unicode", - "unicode.Cc": "unicode", - "unicode.Cf": "unicode", - "unicode.Chakma": "unicode", - "unicode.Cham": "unicode", - "unicode.Cherokee": "unicode", - "unicode.Co": "unicode", - "unicode.Common": "unicode", - "unicode.Coptic": "unicode", - "unicode.Cs": "unicode", - "unicode.Cuneiform": "unicode", - "unicode.Cypriot": "unicode", - "unicode.Cyrillic": "unicode", - "unicode.Dash": "unicode", - "unicode.Deprecated": "unicode", - "unicode.Deseret": "unicode", - "unicode.Devanagari": "unicode", - "unicode.Diacritic": "unicode", - "unicode.Digit": "unicode", - "unicode.Duployan": "unicode", - "unicode.Egyptian_Hieroglyphs": "unicode", - "unicode.Elbasan": "unicode", - "unicode.Ethiopic": "unicode", - "unicode.Extender": "unicode", - "unicode.FoldCategory": "unicode", - "unicode.FoldScript": "unicode", - "unicode.Georgian": "unicode", - "unicode.Glagolitic": "unicode", - "unicode.Gothic": "unicode", - "unicode.Grantha": "unicode", - "unicode.GraphicRanges": "unicode", - "unicode.Greek": "unicode", - "unicode.Gujarati": "unicode", - "unicode.Gurmukhi": "unicode", - "unicode.Han": "unicode", - "unicode.Hangul": "unicode", - "unicode.Hanunoo": "unicode", - "unicode.Hatran": "unicode", - "unicode.Hebrew": "unicode", - "unicode.Hex_Digit": "unicode", - "unicode.Hiragana": "unicode", - "unicode.Hyphen": "unicode", - "unicode.IDS_Binary_Operator": "unicode", - "unicode.IDS_Trinary_Operator": "unicode", - "unicode.Ideographic": "unicode", - "unicode.Imperial_Aramaic": "unicode", - "unicode.In": "unicode", - "unicode.Inherited": "unicode", - "unicode.Inscriptional_Pahlavi": "unicode", - "unicode.Inscriptional_Parthian": "unicode", - "unicode.Is": "unicode", - "unicode.IsControl": "unicode", - "unicode.IsDigit": "unicode", - "unicode.IsGraphic": "unicode", - "unicode.IsLetter": "unicode", - "unicode.IsLower": "unicode", - "unicode.IsMark": "unicode", - "unicode.IsNumber": "unicode", - "unicode.IsOneOf": "unicode", - "unicode.IsPrint": "unicode", - "unicode.IsPunct": "unicode", - "unicode.IsSpace": "unicode", - "unicode.IsSymbol": "unicode", - "unicode.IsTitle": "unicode", - "unicode.IsUpper": "unicode", - "unicode.Javanese": "unicode", - "unicode.Join_Control": "unicode", - "unicode.Kaithi": "unicode", - "unicode.Kannada": "unicode", - "unicode.Katakana": "unicode", - "unicode.Kayah_Li": "unicode", - "unicode.Kharoshthi": "unicode", - "unicode.Khmer": "unicode", - "unicode.Khojki": "unicode", - "unicode.Khudawadi": "unicode", - "unicode.L": "unicode", - "unicode.Lao": "unicode", - "unicode.Latin": "unicode", - "unicode.Lepcha": "unicode", - "unicode.Letter": "unicode", - "unicode.Limbu": "unicode", - "unicode.Linear_A": "unicode", - "unicode.Linear_B": "unicode", - "unicode.Lisu": "unicode", - "unicode.Ll": "unicode", - "unicode.Lm": "unicode", - "unicode.Lo": "unicode", - "unicode.Logical_Order_Exception": "unicode", - "unicode.Lower": "unicode", - "unicode.LowerCase": "unicode", - "unicode.Lt": "unicode", - "unicode.Lu": "unicode", - "unicode.Lycian": "unicode", - "unicode.Lydian": "unicode", - "unicode.M": "unicode", - "unicode.Mahajani": "unicode", - "unicode.Malayalam": "unicode", - "unicode.Mandaic": "unicode", - "unicode.Manichaean": "unicode", - "unicode.Mark": "unicode", - "unicode.MaxASCII": "unicode", - "unicode.MaxCase": "unicode", - "unicode.MaxLatin1": "unicode", - "unicode.MaxRune": "unicode", - "unicode.Mc": "unicode", - "unicode.Me": "unicode", - "unicode.Meetei_Mayek": "unicode", - "unicode.Mende_Kikakui": "unicode", - "unicode.Meroitic_Cursive": "unicode", - "unicode.Meroitic_Hieroglyphs": "unicode", - "unicode.Miao": "unicode", - "unicode.Mn": "unicode", - "unicode.Modi": "unicode", - "unicode.Mongolian": "unicode", - "unicode.Mro": "unicode", - "unicode.Multani": "unicode", - "unicode.Myanmar": "unicode", - "unicode.N": "unicode", - "unicode.Nabataean": "unicode", - "unicode.Nd": "unicode", - "unicode.New_Tai_Lue": "unicode", - "unicode.Nko": "unicode", - "unicode.Nl": "unicode", - "unicode.No": "unicode", - "unicode.Noncharacter_Code_Point": "unicode", - "unicode.Number": "unicode", - "unicode.Ogham": "unicode", - "unicode.Ol_Chiki": "unicode", - "unicode.Old_Hungarian": "unicode", - "unicode.Old_Italic": "unicode", - "unicode.Old_North_Arabian": "unicode", - "unicode.Old_Permic": "unicode", - "unicode.Old_Persian": "unicode", - "unicode.Old_South_Arabian": "unicode", - "unicode.Old_Turkic": "unicode", - "unicode.Oriya": "unicode", - "unicode.Osmanya": "unicode", - "unicode.Other": "unicode", - "unicode.Other_Alphabetic": "unicode", - "unicode.Other_Default_Ignorable_Code_Point": "unicode", - "unicode.Other_Grapheme_Extend": "unicode", - "unicode.Other_ID_Continue": "unicode", - "unicode.Other_ID_Start": "unicode", - "unicode.Other_Lowercase": "unicode", - "unicode.Other_Math": "unicode", - "unicode.Other_Uppercase": "unicode", - "unicode.P": "unicode", - "unicode.Pahawh_Hmong": "unicode", - "unicode.Palmyrene": "unicode", - "unicode.Pattern_Syntax": "unicode", - "unicode.Pattern_White_Space": "unicode", - "unicode.Pau_Cin_Hau": "unicode", - "unicode.Pc": "unicode", - "unicode.Pd": "unicode", - "unicode.Pe": "unicode", - "unicode.Pf": "unicode", - "unicode.Phags_Pa": "unicode", - "unicode.Phoenician": "unicode", - "unicode.Pi": "unicode", - "unicode.Po": "unicode", - "unicode.PrintRanges": "unicode", - "unicode.Properties": "unicode", - "unicode.Ps": "unicode", - "unicode.Psalter_Pahlavi": "unicode", - "unicode.Punct": "unicode", - "unicode.Quotation_Mark": "unicode", - "unicode.Radical": "unicode", - "unicode.Range16": "unicode", - "unicode.Range32": "unicode", - "unicode.RangeTable": "unicode", - "unicode.Rejang": "unicode", - "unicode.ReplacementChar": "unicode", - "unicode.Runic": "unicode", - "unicode.S": "unicode", - "unicode.STerm": "unicode", - "unicode.Samaritan": "unicode", - "unicode.Saurashtra": "unicode", - "unicode.Sc": "unicode", - "unicode.Scripts": "unicode", - "unicode.Sharada": "unicode", - "unicode.Shavian": "unicode", - "unicode.Siddham": "unicode", - "unicode.SignWriting": "unicode", - "unicode.SimpleFold": "unicode", - "unicode.Sinhala": "unicode", - "unicode.Sk": "unicode", - "unicode.Sm": "unicode", - "unicode.So": "unicode", - "unicode.Soft_Dotted": "unicode", - "unicode.Sora_Sompeng": "unicode", - "unicode.Space": "unicode", - "unicode.SpecialCase": "unicode", - "unicode.Sundanese": "unicode", - "unicode.Syloti_Nagri": "unicode", - "unicode.Symbol": "unicode", - "unicode.Syriac": "unicode", - "unicode.Tagalog": "unicode", - "unicode.Tagbanwa": "unicode", - "unicode.Tai_Le": "unicode", - "unicode.Tai_Tham": "unicode", - "unicode.Tai_Viet": "unicode", - "unicode.Takri": "unicode", - "unicode.Tamil": "unicode", - "unicode.Telugu": "unicode", - "unicode.Terminal_Punctuation": "unicode", - "unicode.Thaana": "unicode", - "unicode.Thai": "unicode", - "unicode.Tibetan": "unicode", - "unicode.Tifinagh": "unicode", - "unicode.Tirhuta": "unicode", - "unicode.Title": "unicode", - "unicode.TitleCase": "unicode", - "unicode.To": "unicode", - "unicode.ToLower": "unicode", - "unicode.ToTitle": "unicode", - "unicode.ToUpper": "unicode", - "unicode.TurkishCase": "unicode", - "unicode.Ugaritic": "unicode", - "unicode.Unified_Ideograph": "unicode", - "unicode.Upper": "unicode", - "unicode.UpperCase": "unicode", - "unicode.UpperLower": "unicode", - "unicode.Vai": "unicode", - "unicode.Variation_Selector": "unicode", - "unicode.Version": "unicode", - "unicode.Warang_Citi": "unicode", - "unicode.White_Space": "unicode", - "unicode.Yi": "unicode", - "unicode.Z": "unicode", - "unicode.Zl": "unicode", - "unicode.Zp": "unicode", - "unicode.Zs": "unicode", - "url.Error": "net/url", - "url.EscapeError": "net/url", - "url.Parse": "net/url", - "url.ParseQuery": "net/url", - "url.ParseRequestURI": "net/url", - "url.QueryEscape": "net/url", - "url.QueryUnescape": "net/url", - "url.URL": "net/url", - "url.User": "net/url", - "url.UserPassword": "net/url", - "url.Userinfo": "net/url", - "url.Values": "net/url", - "user.Current": "os/user", - "user.Lookup": "os/user", - "user.LookupId": "os/user", - "user.UnknownUserError": "os/user", - "user.UnknownUserIdError": "os/user", - "user.User": "os/user", - "utf16.Decode": "unicode/utf16", - "utf16.DecodeRune": "unicode/utf16", - "utf16.Encode": "unicode/utf16", - "utf16.EncodeRune": "unicode/utf16", - "utf16.IsSurrogate": "unicode/utf16", - "utf8.DecodeLastRune": "unicode/utf8", - "utf8.DecodeLastRuneInString": "unicode/utf8", - "utf8.DecodeRune": "unicode/utf8", - "utf8.DecodeRuneInString": "unicode/utf8", - "utf8.EncodeRune": "unicode/utf8", - "utf8.FullRune": "unicode/utf8", - "utf8.FullRuneInString": "unicode/utf8", - "utf8.MaxRune": "unicode/utf8", - "utf8.RuneCount": "unicode/utf8", - "utf8.RuneCountInString": "unicode/utf8", - "utf8.RuneError": "unicode/utf8", - "utf8.RuneLen": "unicode/utf8", - "utf8.RuneSelf": "unicode/utf8", - "utf8.RuneStart": "unicode/utf8", - "utf8.UTFMax": "unicode/utf8", - "utf8.Valid": "unicode/utf8", - "utf8.ValidRune": "unicode/utf8", - "utf8.ValidString": "unicode/utf8", - "x509.CANotAuthorizedForThisName": "crypto/x509", - "x509.CertPool": "crypto/x509", - "x509.Certificate": "crypto/x509", - "x509.CertificateInvalidError": "crypto/x509", - "x509.CertificateRequest": "crypto/x509", - "x509.ConstraintViolationError": "crypto/x509", - "x509.CreateCertificate": "crypto/x509", - "x509.CreateCertificateRequest": "crypto/x509", - "x509.DSA": "crypto/x509", - "x509.DSAWithSHA1": "crypto/x509", - "x509.DSAWithSHA256": "crypto/x509", - "x509.DecryptPEMBlock": "crypto/x509", - "x509.ECDSA": "crypto/x509", - "x509.ECDSAWithSHA1": "crypto/x509", - "x509.ECDSAWithSHA256": "crypto/x509", - "x509.ECDSAWithSHA384": "crypto/x509", - "x509.ECDSAWithSHA512": "crypto/x509", - "x509.EncryptPEMBlock": "crypto/x509", - "x509.ErrUnsupportedAlgorithm": "crypto/x509", - "x509.Expired": "crypto/x509", - "x509.ExtKeyUsage": "crypto/x509", - "x509.ExtKeyUsageAny": "crypto/x509", - "x509.ExtKeyUsageClientAuth": "crypto/x509", - "x509.ExtKeyUsageCodeSigning": "crypto/x509", - "x509.ExtKeyUsageEmailProtection": "crypto/x509", - "x509.ExtKeyUsageIPSECEndSystem": "crypto/x509", - "x509.ExtKeyUsageIPSECTunnel": "crypto/x509", - "x509.ExtKeyUsageIPSECUser": "crypto/x509", - "x509.ExtKeyUsageMicrosoftServerGatedCrypto": "crypto/x509", - "x509.ExtKeyUsageNetscapeServerGatedCrypto": "crypto/x509", - "x509.ExtKeyUsageOCSPSigning": "crypto/x509", - "x509.ExtKeyUsageServerAuth": "crypto/x509", - "x509.ExtKeyUsageTimeStamping": "crypto/x509", - "x509.HostnameError": "crypto/x509", - "x509.IncompatibleUsage": "crypto/x509", - "x509.IncorrectPasswordError": "crypto/x509", - "x509.InvalidReason": "crypto/x509", - "x509.IsEncryptedPEMBlock": "crypto/x509", - "x509.KeyUsage": "crypto/x509", - "x509.KeyUsageCRLSign": "crypto/x509", - "x509.KeyUsageCertSign": "crypto/x509", - "x509.KeyUsageContentCommitment": "crypto/x509", - "x509.KeyUsageDataEncipherment": "crypto/x509", - "x509.KeyUsageDecipherOnly": "crypto/x509", - "x509.KeyUsageDigitalSignature": "crypto/x509", - "x509.KeyUsageEncipherOnly": "crypto/x509", - "x509.KeyUsageKeyAgreement": "crypto/x509", - "x509.KeyUsageKeyEncipherment": "crypto/x509", - "x509.MD2WithRSA": "crypto/x509", - "x509.MD5WithRSA": "crypto/x509", - "x509.MarshalECPrivateKey": "crypto/x509", - "x509.MarshalPKCS1PrivateKey": "crypto/x509", - "x509.MarshalPKIXPublicKey": "crypto/x509", - "x509.NewCertPool": "crypto/x509", - "x509.NotAuthorizedToSign": "crypto/x509", - "x509.PEMCipher": "crypto/x509", - "x509.PEMCipher3DES": "crypto/x509", - "x509.PEMCipherAES128": "crypto/x509", - "x509.PEMCipherAES192": "crypto/x509", - "x509.PEMCipherAES256": "crypto/x509", - "x509.PEMCipherDES": "crypto/x509", - "x509.ParseCRL": "crypto/x509", - "x509.ParseCertificate": "crypto/x509", - "x509.ParseCertificateRequest": "crypto/x509", - "x509.ParseCertificates": "crypto/x509", - "x509.ParseDERCRL": "crypto/x509", - "x509.ParseECPrivateKey": "crypto/x509", - "x509.ParsePKCS1PrivateKey": "crypto/x509", - "x509.ParsePKCS8PrivateKey": "crypto/x509", - "x509.ParsePKIXPublicKey": "crypto/x509", - "x509.PublicKeyAlgorithm": "crypto/x509", - "x509.RSA": "crypto/x509", - "x509.SHA1WithRSA": "crypto/x509", - "x509.SHA256WithRSA": "crypto/x509", - "x509.SHA384WithRSA": "crypto/x509", - "x509.SHA512WithRSA": "crypto/x509", - "x509.SignatureAlgorithm": "crypto/x509", - "x509.SystemRootsError": "crypto/x509", - "x509.TooManyIntermediates": "crypto/x509", - "x509.UnhandledCriticalExtension": "crypto/x509", - "x509.UnknownAuthorityError": "crypto/x509", - "x509.UnknownPublicKeyAlgorithm": "crypto/x509", - "x509.UnknownSignatureAlgorithm": "crypto/x509", - "x509.VerifyOptions": "crypto/x509", - "xml.Attr": "encoding/xml", - "xml.CharData": "encoding/xml", - "xml.Comment": "encoding/xml", - "xml.CopyToken": "encoding/xml", - "xml.Decoder": "encoding/xml", - "xml.Directive": "encoding/xml", - "xml.Encoder": "encoding/xml", - "xml.EndElement": "encoding/xml", - "xml.Escape": "encoding/xml", - "xml.EscapeText": "encoding/xml", - "xml.HTMLAutoClose": "encoding/xml", - "xml.HTMLEntity": "encoding/xml", - "xml.Header": "encoding/xml", - "xml.Marshal": "encoding/xml", - "xml.MarshalIndent": "encoding/xml", - "xml.Marshaler": "encoding/xml", - "xml.MarshalerAttr": "encoding/xml", - "xml.Name": "encoding/xml", - "xml.NewDecoder": "encoding/xml", - "xml.NewEncoder": "encoding/xml", - "xml.ProcInst": "encoding/xml", - "xml.StartElement": "encoding/xml", - "xml.SyntaxError": "encoding/xml", - "xml.TagPathError": "encoding/xml", - "xml.Token": "encoding/xml", - "xml.Unmarshal": "encoding/xml", - "xml.UnmarshalError": "encoding/xml", - "xml.Unmarshaler": "encoding/xml", - "xml.UnmarshalerAttr": "encoding/xml", - "xml.UnsupportedTypeError": "encoding/xml", - "zip.Compressor": "archive/zip", - "zip.Decompressor": "archive/zip", - "zip.Deflate": "archive/zip", - "zip.ErrAlgorithm": "archive/zip", - "zip.ErrChecksum": "archive/zip", - "zip.ErrFormat": "archive/zip", - "zip.File": "archive/zip", - "zip.FileHeader": "archive/zip", - "zip.FileInfoHeader": "archive/zip", - "zip.NewReader": "archive/zip", - "zip.NewWriter": "archive/zip", - "zip.OpenReader": "archive/zip", - "zip.ReadCloser": "archive/zip", - "zip.Reader": "archive/zip", - "zip.RegisterCompressor": "archive/zip", - "zip.RegisterDecompressor": "archive/zip", - "zip.Store": "archive/zip", - "zip.Writer": "archive/zip", - "zlib.BestCompression": "compress/zlib", - "zlib.BestSpeed": "compress/zlib", - "zlib.DefaultCompression": "compress/zlib", - "zlib.ErrChecksum": "compress/zlib", - "zlib.ErrDictionary": "compress/zlib", - "zlib.ErrHeader": "compress/zlib", - "zlib.NewReader": "compress/zlib", - "zlib.NewReaderDict": "compress/zlib", - "zlib.NewWriter": "compress/zlib", - "zlib.NewWriterLevel": "compress/zlib", - "zlib.NewWriterLevelDict": "compress/zlib", - "zlib.NoCompression": "compress/zlib", - "zlib.Resetter": "compress/zlib", - "zlib.Writer": "compress/zlib", -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/.github/CONTRIBUTING.md b/vendor/gopkg.in/go-playground/validator.v9/.github/CONTRIBUTING.md deleted file mode 100644 index b8cf8b68153..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/.github/CONTRIBUTING.md +++ /dev/null @@ -1,9 +0,0 @@ -# Contribution Guidelines - -## Quality Standard - -To ensure the continued stability of this package tests are required to be written or already exist in order for a pull request to be merged. - -## Reporting issues - -Please open an issue or join the gitter chat [![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) for any issues, questions or possible enhancements to the package. diff --git a/vendor/gopkg.in/go-playground/validator.v9/.github/ISSUE_TEMPLATE.md b/vendor/gopkg.in/go-playground/validator.v9/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 8afb259129a..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,13 +0,0 @@ -### Package version eg. v8, v9: - - - -### Issue, Question or Enhancement: - - - -### Code sample, to showcase or reproduce: - -```go - -``` diff --git a/vendor/gopkg.in/go-playground/validator.v9/.github/PULL_REQUEST_TEMPLATE.md b/vendor/gopkg.in/go-playground/validator.v9/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 7bebde392e9..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,13 +0,0 @@ -Fixes Or Enhances # . - -**Make sure that you've checked the boxes below before you submit PR:** -- [ ] Tests exist or have been written that cover this particular change. - -Change Details: - -- -- -- - - -@go-playground/admins \ No newline at end of file diff --git a/vendor/gopkg.in/go-playground/validator.v9/README.md b/vendor/gopkg.in/go-playground/validator.v9/README.md index 51c6cb4f8b3..e7837254b00 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/README.md +++ b/vendor/gopkg.in/go-playground/validator.v9/README.md @@ -1,7 +1,7 @@ Package validator ================ [![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -![Project status](https://img.shields.io/badge/version-9.4.0-green.svg) +![Project status](https://img.shields.io/badge/version-9.9.3-green.svg) [![Build Status](https://semaphoreci.com/api/v1/joeybloggs/validator/branches/v9/badge.svg)](https://semaphoreci.com/joeybloggs/validator) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v9&service=github)](https://coveralls.io/github/go-playground/validator?branch=v9) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) @@ -13,7 +13,8 @@ Package validator implements value validations for structs and individual fields It has the following **unique** features: - Cross Field and Cross Struct validations by using validation tags or custom validators. -- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated. +- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated. +- Ability to dive into both map keys and values for validation - Handles type interface by determining it's underlying type prior to validation. - Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29) - Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs @@ -65,61 +66,69 @@ Please see http://godoc.org/gopkg.in/go-playground/validator.v9 for detailed usa Benchmarks ------ -###### Run on Dell XPS 15 i7-7700HQ 32GB Go version go1.8.3 linux/amd64 +###### Run on MacBook Pro (15-inch, 2017) Go version go1.9.2 darwin/amd64 ```go -go test -run=XXX -bench=. -benchmem=true -BenchmarkFieldSuccess-8 20000000 88.3 ns/op 0 B/op 0 allocs/op -BenchmarkFieldSuccessParallel-8 50000000 30.4 ns/op 0 B/op 0 allocs/op -BenchmarkFieldFailure-8 3000000 428 ns/op 208 B/op 4 allocs/op -BenchmarkFieldFailureParallel-8 20000000 96.0 ns/op 208 B/op 4 allocs/op -BenchmarkFieldDiveSuccess-8 2000000 695 ns/op 201 B/op 11 allocs/op -BenchmarkFieldDiveSuccessParallel-8 10000000 205 ns/op 201 B/op 11 allocs/op -BenchmarkFieldDiveFailure-8 1000000 1083 ns/op 412 B/op 16 allocs/op -BenchmarkFieldDiveFailureParallel-8 5000000 278 ns/op 413 B/op 16 allocs/op -BenchmarkFieldCustomTypeSuccess-8 10000000 229 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeSuccessParallel-8 20000000 72.4 ns/op 32 B/op 2 allocs/op -BenchmarkFieldCustomTypeFailure-8 5000000 377 ns/op 208 B/op 4 allocs/op -BenchmarkFieldCustomTypeFailureParallel-8 20000000 93.0 ns/op 208 B/op 4 allocs/op -BenchmarkFieldOrTagSuccess-8 2000000 767 ns/op 16 B/op 1 allocs/op -BenchmarkFieldOrTagSuccessParallel-8 3000000 425 ns/op 16 B/op 1 allocs/op -BenchmarkFieldOrTagFailure-8 2000000 548 ns/op 224 B/op 5 allocs/op -BenchmarkFieldOrTagFailureParallel-8 3000000 411 ns/op 224 B/op 5 allocs/op -BenchmarkStructLevelValidationSuccess-8 10000000 219 ns/op 32 B/op 2 allocs/op -BenchmarkStructLevelValidationSuccessParallel-8 20000000 69.2 ns/op 32 B/op 2 allocs/op -BenchmarkStructLevelValidationFailure-8 2000000 628 ns/op 304 B/op 8 allocs/op -BenchmarkStructLevelValidationFailureParallel-8 10000000 165 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCustomTypeSuccess-8 3000000 411 ns/op 32 B/op 2 allocs/op -BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 122 ns/op 32 B/op 2 allocs/op -BenchmarkStructSimpleCustomTypeFailure-8 1000000 1022 ns/op 424 B/op 9 allocs/op -BenchmarkStructSimpleCustomTypeFailureParallel-8 10000000 228 ns/op 440 B/op 10 allocs/op -BenchmarkStructFilteredSuccess-8 2000000 737 ns/op 288 B/op 9 allocs/op -BenchmarkStructFilteredSuccessParallel-8 10000000 192 ns/op 288 B/op 9 allocs/op -BenchmarkStructFilteredFailure-8 3000000 583 ns/op 256 B/op 7 allocs/op -BenchmarkStructFilteredFailureParallel-8 10000000 152 ns/op 256 B/op 7 allocs/op -BenchmarkStructPartialSuccess-8 2000000 731 ns/op 256 B/op 6 allocs/op -BenchmarkStructPartialSuccessParallel-8 10000000 173 ns/op 256 B/op 6 allocs/op -BenchmarkStructPartialFailure-8 1000000 1164 ns/op 480 B/op 11 allocs/op -BenchmarkStructPartialFailureParallel-8 5000000 253 ns/op 480 B/op 11 allocs/op -BenchmarkStructExceptSuccess-8 1000000 1337 ns/op 496 B/op 12 allocs/op -BenchmarkStructExceptSuccessParallel-8 10000000 153 ns/op 240 B/op 5 allocs/op -BenchmarkStructExceptFailure-8 2000000 954 ns/op 464 B/op 10 allocs/op -BenchmarkStructExceptFailureParallel-8 5000000 234 ns/op 464 B/op 10 allocs/op -BenchmarkStructSimpleCrossFieldSuccess-8 3000000 420 ns/op 72 B/op 3 allocs/op -BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 125 ns/op 72 B/op 3 allocs/op -BenchmarkStructSimpleCrossFieldFailure-8 2000000 790 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCrossFieldFailureParallel-8 10000000 205 ns/op 304 B/op 8 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 2000000 611 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 172 ns/op 80 B/op 4 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailure-8 1000000 1112 ns/op 320 B/op 9 allocs/op -BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 258 ns/op 320 B/op 9 allocs/op -BenchmarkStructSimpleSuccess-8 5000000 263 ns/op 0 B/op 0 allocs/op -BenchmarkStructSimpleSuccessParallel-8 20000000 83.1 ns/op 0 B/op 0 allocs/op -BenchmarkStructSimpleFailure-8 2000000 964 ns/op 424 B/op 9 allocs/op -BenchmarkStructSimpleFailureParallel-8 10000000 212 ns/op 424 B/op 9 allocs/op -BenchmarkStructComplexSuccess-8 1000000 1504 ns/op 128 B/op 8 allocs/op +go test -bench=. -benchmem=true +BenchmarkFieldSuccess-8 20000000 79.9 ns/op 0 B/op 0 allocs/op +BenchmarkFieldSuccessParallel-8 50000000 25.0 ns/op 0 B/op 0 allocs/op +BenchmarkFieldFailure-8 5000000 281 ns/op 208 B/op 4 allocs/op +BenchmarkFieldFailureParallel-8 20000000 97.0 ns/op 208 B/op 4 allocs/op +BenchmarkFieldArrayDiveSuccess-8 3000000 591 ns/op 201 B/op 11 allocs/op +BenchmarkFieldArrayDiveSuccessParallel-8 10000000 195 ns/op 201 B/op 11 allocs/op +BenchmarkFieldArrayDiveFailure-8 2000000 878 ns/op 412 B/op 16 allocs/op +BenchmarkFieldArrayDiveFailureParallel-8 5000000 274 ns/op 413 B/op 16 allocs/op +BenchmarkFieldMapDiveSuccess-8 1000000 1279 ns/op 432 B/op 18 allocs/op +BenchmarkFieldMapDiveSuccessParallel-8 5000000 401 ns/op 432 B/op 18 allocs/op +BenchmarkFieldMapDiveFailure-8 1000000 1060 ns/op 512 B/op 16 allocs/op +BenchmarkFieldMapDiveFailureParallel-8 5000000 334 ns/op 512 B/op 16 allocs/op +BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1462 ns/op 480 B/op 21 allocs/op +BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 463 ns/op 480 B/op 21 allocs/op +BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1414 ns/op 721 B/op 21 allocs/op +BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 446 ns/op 721 B/op 21 allocs/op +BenchmarkFieldCustomTypeSuccess-8 10000000 211 ns/op 32 B/op 2 allocs/op +BenchmarkFieldCustomTypeSuccessParallel-8 20000000 65.9 ns/op 32 B/op 2 allocs/op +BenchmarkFieldCustomTypeFailure-8 5000000 270 ns/op 208 B/op 4 allocs/op +BenchmarkFieldCustomTypeFailureParallel-8 20000000 93.3 ns/op 208 B/op 4 allocs/op +BenchmarkFieldOrTagSuccess-8 2000000 729 ns/op 16 B/op 1 allocs/op +BenchmarkFieldOrTagSuccessParallel-8 5000000 367 ns/op 16 B/op 1 allocs/op +BenchmarkFieldOrTagFailure-8 3000000 472 ns/op 224 B/op 5 allocs/op +BenchmarkFieldOrTagFailureParallel-8 5000000 373 ns/op 224 B/op 5 allocs/op +BenchmarkStructLevelValidationSuccess-8 10000000 201 ns/op 32 B/op 2 allocs/op +BenchmarkStructLevelValidationSuccessParallel-8 20000000 66.3 ns/op 32 B/op 2 allocs/op +BenchmarkStructLevelValidationFailure-8 3000000 468 ns/op 304 B/op 8 allocs/op +BenchmarkStructLevelValidationFailureParallel-8 10000000 172 ns/op 304 B/op 8 allocs/op +BenchmarkStructSimpleCustomTypeSuccess-8 5000000 376 ns/op 32 B/op 2 allocs/op +BenchmarkStructSimpleCustomTypeSuccessParallel-8 20000000 126 ns/op 32 B/op 2 allocs/op +BenchmarkStructSimpleCustomTypeFailure-8 2000000 646 ns/op 424 B/op 9 allocs/op +BenchmarkStructSimpleCustomTypeFailureParallel-8 10000000 240 ns/op 440 B/op 10 allocs/op +BenchmarkStructFilteredSuccess-8 3000000 582 ns/op 288 B/op 9 allocs/op +BenchmarkStructFilteredSuccessParallel-8 10000000 198 ns/op 288 B/op 9 allocs/op +BenchmarkStructFilteredFailure-8 3000000 447 ns/op 256 B/op 7 allocs/op +BenchmarkStructFilteredFailureParallel-8 10000000 156 ns/op 256 B/op 7 allocs/op +BenchmarkStructPartialSuccess-8 3000000 536 ns/op 256 B/op 6 allocs/op +BenchmarkStructPartialSuccessParallel-8 10000000 175 ns/op 256 B/op 6 allocs/op +BenchmarkStructPartialFailure-8 2000000 738 ns/op 480 B/op 11 allocs/op +BenchmarkStructPartialFailureParallel-8 5000000 256 ns/op 480 B/op 11 allocs/op +BenchmarkStructExceptSuccess-8 2000000 835 ns/op 496 B/op 12 allocs/op +BenchmarkStructExceptSuccessParallel-8 10000000 163 ns/op 240 B/op 5 allocs/op +BenchmarkStructExceptFailure-8 2000000 682 ns/op 464 B/op 10 allocs/op +BenchmarkStructExceptFailureParallel-8 10000000 244 ns/op 464 B/op 10 allocs/op +BenchmarkStructSimpleCrossFieldSuccess-8 5000000 392 ns/op 72 B/op 3 allocs/op +BenchmarkStructSimpleCrossFieldSuccessParallel-8 20000000 126 ns/op 72 B/op 3 allocs/op +BenchmarkStructSimpleCrossFieldFailure-8 2000000 611 ns/op 304 B/op 8 allocs/op +BenchmarkStructSimpleCrossFieldFailureParallel-8 10000000 214 ns/op 304 B/op 8 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3000000 567 ns/op 80 B/op 4 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 177 ns/op 80 B/op 4 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 807 ns/op 320 B/op 9 allocs/op +BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 268 ns/op 320 B/op 9 allocs/op +BenchmarkStructSimpleSuccess-8 5000000 256 ns/op 0 B/op 0 allocs/op +BenchmarkStructSimpleSuccessParallel-8 20000000 76.3 ns/op 0 B/op 0 allocs/op +BenchmarkStructSimpleFailure-8 2000000 625 ns/op 424 B/op 9 allocs/op +BenchmarkStructSimpleFailureParallel-8 10000000 219 ns/op 424 B/op 9 allocs/op +BenchmarkStructComplexSuccess-8 1000000 1431 ns/op 128 B/op 8 allocs/op BenchmarkStructComplexSuccessParallel-8 3000000 427 ns/op 128 B/op 8 allocs/op -BenchmarkStructComplexFailure-8 300000 7585 ns/op 3041 B/op 53 allocs/op -BenchmarkStructComplexFailureParallel-8 1000000 1387 ns/op 3041 B/op 53 allocs/op +BenchmarkStructComplexFailure-8 300000 4065 ns/op 3041 B/op 53 allocs/op +BenchmarkStructComplexFailureParallel-8 1000000 1478 ns/op 3041 B/op 53 allocs/op ``` Complementary Software @@ -128,7 +137,7 @@ Complementary Software Here is a list of software that complements using this library either pre or post validation. * [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support. -* [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags. +* [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects How to Contribute ------ diff --git a/vendor/gopkg.in/go-playground/validator.v9/_examples/custom/main.go b/vendor/gopkg.in/go-playground/validator.v9/_examples/custom/main.go deleted file mode 100644 index 724f57aa4fb..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/_examples/custom/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - "database/sql" - "database/sql/driver" - "fmt" - "reflect" - - "gopkg.in/go-playground/validator.v9" -) - -// DbBackedUser User struct -type DbBackedUser struct { - Name sql.NullString `validate:"required"` - Age sql.NullInt64 `validate:"required"` -} - -// use a single instance of Validate, it caches struct info -var validate *validator.Validate - -func main() { - - validate = validator.New() - - // register all sql.Null* types to use the ValidateValuer CustomTypeFunc - validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) - - // build object for validation - x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}} - - err := validate.Struct(x) - - if err != nil { - fmt.Printf("Err(s):\n%+v\n", err) - } -} - -// ValidateValuer implements validator.CustomTypeFunc -func ValidateValuer(field reflect.Value) interface{} { - - if valuer, ok := field.Interface().(driver.Valuer); ok { - - val, err := valuer.Value() - if err == nil { - return val - } - // handle the error how you want - } - - return nil -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/_examples/gin-upgrading-overriding/main.go b/vendor/gopkg.in/go-playground/validator.v9/_examples/gin-upgrading-overriding/main.go deleted file mode 100644 index 46fdf2adc4c..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/_examples/gin-upgrading-overriding/main.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import "github.com/gin-gonic/gin/binding" - -func main() { - - binding.Validator = new(defaultValidator) - - // regular gin logic -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/_examples/gin-upgrading-overriding/v8_to_v9.go b/vendor/gopkg.in/go-playground/validator.v9/_examples/gin-upgrading-overriding/v8_to_v9.go deleted file mode 100644 index 272b670c9cc..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/_examples/gin-upgrading-overriding/v8_to_v9.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "reflect" - "sync" - - "github.com/gin-gonic/gin/binding" - "gopkg.in/go-playground/validator.v9" -) - -type defaultValidator struct { - once sync.Once - validate *validator.Validate -} - -var _ binding.StructValidator = &defaultValidator{} - -func (v *defaultValidator) ValidateStruct(obj interface{}) error { - - if kindOfData(obj) == reflect.Struct { - - v.lazyinit() - - if err := v.validate.Struct(obj); err != nil { - return error(err) - } - } - - return nil -} - -func (v *defaultValidator) lazyinit() { - v.once.Do(func() { - v.validate = validator.New() - v.validate.SetTagName("binding") - - // add any custom validations etc. here - }) -} - -func kindOfData(data interface{}) reflect.Kind { - - value := reflect.ValueOf(data) - valueType := value.Kind() - - if valueType == reflect.Ptr { - valueType = value.Elem().Kind() - } - return valueType -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/_examples/simple/main.go b/vendor/gopkg.in/go-playground/validator.v9/_examples/simple/main.go deleted file mode 100644 index 9e3d1064861..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/_examples/simple/main.go +++ /dev/null @@ -1,101 +0,0 @@ -package main - -import ( - "fmt" - - "gopkg.in/go-playground/validator.v9" -) - -// User contains user information -type User struct { - FirstName string `validate:"required"` - LastName string `validate:"required"` - Age uint8 `validate:"gte=0,lte=130"` - Email string `validate:"required,email"` - FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla' - Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... -} - -// Address houses a users address information -type Address struct { - Street string `validate:"required"` - City string `validate:"required"` - Planet string `validate:"required"` - Phone string `validate:"required"` -} - -// use a single instance of Validate, it caches struct info -var validate *validator.Validate - -func main() { - - validate = validator.New() - - validateStruct() - validateVariable() -} - -func validateStruct() { - - address := &Address{ - Street: "Eavesdown Docks", - Planet: "Persphone", - Phone: "none", - } - - user := &User{ - FirstName: "Badger", - LastName: "Smith", - Age: 135, - Email: "Badger.Smith@gmail.com", - FavouriteColor: "#000-", - Addresses: []*Address{address}, - } - - // returns nil or ValidationErrors ( map[string]*FieldError ) - err := validate.Struct(user) - if err != nil { - - // this check is only needed when your code could produce - // an invalid value for validation such as interface with nil - // value most including myself do not usually have code like this. - if _, ok := err.(*validator.InvalidValidationError); ok { - fmt.Println(err) - return - } - - for _, err := range err.(validator.ValidationErrors) { - - fmt.Println(err.Namespace()) - fmt.Println(err.Field()) - fmt.Println(err.StructNamespace()) // can differ when a custom TagNameFunc is registered or - fmt.Println(err.StructField()) // by passing alt name to ReportError like below - fmt.Println(err.Tag()) - fmt.Println(err.ActualTag()) - fmt.Println(err.Kind()) - fmt.Println(err.Type()) - fmt.Println(err.Value()) - fmt.Println(err.Param()) - fmt.Println() - } - - // from here you can create your own error messages in whatever language you wish - return - } - - // save user to database -} - -func validateVariable() { - - myEmail := "joeybloggs.gmail.com" - - errs := validate.Var(myEmail, "required,email") - - if errs != nil { - fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag - return - } - - // email ok, move on -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/_examples/struct-level/main.go b/vendor/gopkg.in/go-playground/validator.v9/_examples/struct-level/main.go deleted file mode 100644 index 87742fc8982..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/_examples/struct-level/main.go +++ /dev/null @@ -1,109 +0,0 @@ -package main - -import ( - "fmt" - - "gopkg.in/go-playground/validator.v9" -) - -// User contains user information -type User struct { - FirstName string `json:"fname"` - LastName string `json:"lname"` - Age uint8 `validate:"gte=0,lte=130"` - Email string `validate:"required,email"` - FavouriteColor string `validate:"hexcolor|rgb|rgba"` - Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... -} - -// Address houses a users address information -type Address struct { - Street string `validate:"required"` - City string `validate:"required"` - Planet string `validate:"required"` - Phone string `validate:"required"` -} - -// use a single instance of Validate, it caches struct info -var validate *validator.Validate - -func main() { - - validate = validator.New() - - // register validation for 'User' - // NOTE: only have to register a non-pointer type for 'User', validator - // interanlly dereferences during it's type checks. - validate.RegisterStructValidation(UserStructLevelValidation, User{}) - - // build 'User' info, normally posted data etc... - address := &Address{ - Street: "Eavesdown Docks", - Planet: "Persphone", - Phone: "none", - City: "Unknown", - } - - user := &User{ - FirstName: "", - LastName: "", - Age: 45, - Email: "Badger.Smith@gmail.com", - FavouriteColor: "#000", - Addresses: []*Address{address}, - } - - // returns InvalidValidationError for bad validation input, nil or ValidationErrors ( []FieldError ) - err := validate.Struct(user) - if err != nil { - - // this check is only needed when your code could produce - // an invalid value for validation such as interface with nil - // value most including myself do not usually have code like this. - if _, ok := err.(*validator.InvalidValidationError); ok { - fmt.Println(err) - return - } - - for _, err := range err.(validator.ValidationErrors) { - - fmt.Println(err.Namespace()) - fmt.Println(err.Field()) - fmt.Println(err.StructNamespace()) // can differ when a custom TagNameFunc is registered or - fmt.Println(err.StructField()) // by passing alt name to ReportError like below - fmt.Println(err.Tag()) - fmt.Println(err.ActualTag()) - fmt.Println(err.Kind()) - fmt.Println(err.Type()) - fmt.Println(err.Value()) - fmt.Println(err.Param()) - fmt.Println() - } - - // from here you can create your own error messages in whatever language you wish - return - } - - // save user to database -} - -// UserStructLevelValidation contains custom struct level validations that don't always -// make sense at the field validation level. For Example this function validates that either -// FirstName or LastName exist; could have done that with a custom field validation but then -// would have had to add it to both fields duplicating the logic + overhead, this way it's -// only validated once. -// -// NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way -// hooks right into validator and you can combine with validation tags and still have a -// common error output format. -func UserStructLevelValidation(sl validator.StructLevel) { - - user := sl.Current().Interface().(User) - - if len(user.FirstName) == 0 && len(user.LastName) == 0 { - sl.ReportError(user.FirstName, "FirstName", "fname", "fnameorlname", "") - sl.ReportError(user.LastName, "LastName", "lname", "fnameorlname", "") - } - - // plus can to more, even with different tag than "fnameorlname" -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/_examples/translations/main.go b/vendor/gopkg.in/go-playground/validator.v9/_examples/translations/main.go deleted file mode 100644 index 0c298e431fe..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/_examples/translations/main.go +++ /dev/null @@ -1,129 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/go-playground/locales/en" - ut "github.com/go-playground/universal-translator" - "gopkg.in/go-playground/validator.v9" - en_translations "gopkg.in/go-playground/validator.v9/translations/en" -) - -// User contains user information -type User struct { - FirstName string `validate:"required"` - LastName string `validate:"required"` - Age uint8 `validate:"gte=0,lte=130"` - Email string `validate:"required,email"` - FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla' - Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage... -} - -// Address houses a users address information -type Address struct { - Street string `validate:"required"` - City string `validate:"required"` - Planet string `validate:"required"` - Phone string `validate:"required"` -} - -// use a single instance , it caches struct info -var ( - uni *ut.UniversalTranslator - validate *validator.Validate -) - -func main() { - - // NOTE: ommitting allot of error checking for brevity - - en := en.New() - uni = ut.New(en, en) - - // this is usually know or extracted from http 'Accept-Language' header - // also see uni.FindTranslator(...) - trans, _ := uni.GetTranslator("en") - - validate = validator.New() - en_translations.RegisterDefaultTranslations(validate, trans) - - translateAll(trans) - translateIndividual(trans) - translateOverride(trans) // yep you can specify your own in whatever locale you want! -} - -func translateAll(trans ut.Translator) { - - type User struct { - Username string `validate:"required"` - Tagline string `validate:"required,lt=10"` - Tagline2 string `validate:"required,gt=1"` - } - - user := User{ - Username: "Joeybloggs", - Tagline: "This tagline is way too long.", - Tagline2: "1", - } - - err := validate.Struct(user) - if err != nil { - - // translate all error at once - errs := err.(validator.ValidationErrors) - - // returns a map with key = namespace & value = translated error - // NOTICE: 2 errors are returned and you'll see something surprising - // translations are i18n aware!!!! - // eg. '10 characters' vs '1 character' - fmt.Println(errs.Translate(trans)) - } -} - -func translateIndividual(trans ut.Translator) { - - type User struct { - Username string `validate:"required"` - } - - var user User - - err := validate.Struct(user) - if err != nil { - - errs := err.(validator.ValidationErrors) - - for _, e := range errs { - // can translate each error one at a time. - fmt.Println(e.Translate(trans)) - } - } -} - -func translateOverride(trans ut.Translator) { - - validate.RegisterTranslation("required", trans, func(ut ut.Translator) error { - return ut.Add("required", "{0} must have a value!", true) // see universal-translator for details - }, func(ut ut.Translator, fe validator.FieldError) string { - t, _ := ut.T("required", fe.Field()) - - return t - }) - - type User struct { - Username string `validate:"required"` - } - - var user User - - err := validate.Struct(user) - if err != nil { - - errs := err.(validator.ValidationErrors) - - for _, e := range errs { - // can translate each error one at a time. - fmt.Println(e.Translate(trans)) - } - } -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/baked_in.go b/vendor/gopkg.in/go-playground/validator.v9/baked_in.go index 1241f35f532..66540946831 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/baked_in.go +++ b/vendor/gopkg.in/go-playground/validator.v9/baked_in.go @@ -11,10 +11,12 @@ import ( "unicode/utf8" ) -// Func accepts a FieldLevel interface for all validation needs +// Func accepts a FieldLevel interface for all validation needs. The return +// value should be true when validation succeeds. type Func func(fl FieldLevel) bool -// FuncCtx accepts a context.Context and FieldLevel interface for all validation needs +// FuncCtx accepts a context.Context and FieldLevel interface for all +// validation needs. The return value should be true when validation succeeds. type FuncCtx func(ctx context.Context, fl FieldLevel) bool // wrapFunc wraps noramal Func makes it compatible with FuncCtx @@ -30,6 +32,8 @@ func wrapFunc(fn Func) FuncCtx { var ( restrictedTags = map[string]struct{}{ diveTag: {}, + keysTag: {}, + endKeysTag: {}, structOnlyTag: {}, omitempty: {}, skipValidationTag: {}, @@ -37,6 +41,7 @@ var ( utf8Pipe: {}, noStructLevelTag: {}, requiredTag: {}, + isdefault: {}, } // BakedInAliasValidators is a default mapping of a single validation tag that @@ -51,6 +56,7 @@ var ( // or even disregard and use your own map if so desired. bakedInValidators = map[string]Func{ "required": hasValue, + "isdefault": isDefault, "len": hasLengthOf, "min": hasMinOf, "max": hasMaxOf, @@ -125,9 +131,31 @@ var ( "ip_addr": isIPAddrResolvable, "unix_addr": isUnixAddrResolvable, "mac": isMAC, + "hostname": isHostname, + "fqdn": isFQDN, + "unique": isUnique, } ) +// isUnique is the validation function for validating if each array|slice element is unique +func isUnique(fl FieldLevel) bool { + + field := fl.Field() + v := reflect.ValueOf(struct{}{}) + + switch field.Kind() { + case reflect.Slice, reflect.Array: + m := reflect.MakeMap(reflect.MapOf(fl.Field().Type().Elem(), v.Type())) + + for i := 0; i < field.Len(); i++ { + m.SetMapIndex(field.Index(i), v) + } + return field.Len() == m.Len() + default: + panic(fmt.Sprintf("Bad field type %T", field.Interface())) + } +} + // IsMAC is the validation function for validating if the field's value is a valid MAC address. func isMAC(fl FieldLevel) bool { @@ -901,6 +929,11 @@ func isAlphaUnicode(fl FieldLevel) bool { return alphaUnicodeRegex.MatchString(fl.Field().String()) } +// isDefault is the opposite of required aka hasValue +func isDefault(fl FieldLevel) bool { + return !hasValue(fl) +} + // HasValue is the validation function for validating if the current field's value is not the default static value. func hasValue(fl FieldLevel) bool { @@ -1477,3 +1510,22 @@ func isIP6Addr(fl FieldLevel) bool { return ip != nil && ip.To4() == nil } + +func isHostname(fl FieldLevel) bool { + return hostnameRegex.MatchString(fl.Field().String()) +} + +func isFQDN(fl FieldLevel) bool { + val := fl.Field().String() + + if val == "" { + return false + } + + if val[len(val)-1] == '.' { + val = val[0 : len(val)-1] + } + + return (strings.IndexAny(val, ".") > -1) && + hostnameRegex.MatchString(val) +} diff --git a/vendor/gopkg.in/go-playground/validator.v9/cache.go b/vendor/gopkg.in/go-playground/validator.v9/cache.go index f128f596b08..3906d2517fc 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/cache.go +++ b/vendor/gopkg.in/go-playground/validator.v9/cache.go @@ -13,15 +13,19 @@ type tagType uint8 const ( typeDefault tagType = iota typeOmitEmpty + typeIsDefault typeNoStructLevel typeStructOnly typeDive typeOr + typeKeys + typeEndKeys ) const ( invalidValidation = "Invalid validation tag on field '%s'" undefinedValidation = "Undefined validation function '%s' on field '%s'" + keysTagNotDefined = "'" + endKeysTag + "' tag encountered without a corresponding '" + keysTag + "' tag" ) type structCache struct { @@ -87,11 +91,14 @@ type cTag struct { aliasTag string actualAliasTag string param string - hasAlias bool typeof tagType + keys *cTag // only populated when using tag's 'keys' and 'endkeys' for map key validation + next *cTag hasTag bool + hasAlias bool + hasParam bool // true if parameter used eg. eq= where the equal sign has been set + isBlockEnd bool // indicates the current tag represents the last validation in the block fn FuncCtx - next *cTag } func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct { @@ -184,7 +191,6 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s // check map for alias and process new tags, otherwise process as usual if tagsVal, found := v.aliases[t]; found { - if i == 0 { firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) } else { @@ -196,10 +202,13 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s continue } + var prevTag tagType + if i == 0 { current = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true} firstCtag = current } else { + prevTag = current.typeof current.next = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true} current = current.next } @@ -210,6 +219,44 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s current.typeof = typeDive continue + case keysTag: + current.typeof = typeKeys + + if i == 0 || prevTag != typeDive { + panic(fmt.Sprintf("'%s' tag must be immediately preceeded by the '%s' tag", keysTag, diveTag)) + } + + current.typeof = typeKeys + + // need to pass along only keys tag + // need to increment i to skip over the keys tags + b := make([]byte, 0, 64) + + i++ + + for ; i < len(tags); i++ { + + b = append(b, tags[i]...) + b = append(b, ',') + + if tags[i] == endKeysTag { + break + } + } + + current.keys, _ = v.parseFieldTagsRecursive(string(b[:len(b)-1]), fieldName, "", false) + continue + + case endKeysTag: + current.typeof = typeEndKeys + + // if there are more in tags then there was no keysTag defined + // and an error should be thrown + if i != len(tags)-1 { + panic(keysTagNotDefined) + } + return + case omitempty: current.typeof = typeOmitEmpty continue @@ -224,6 +271,10 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s default: + if t == isdefault { + current.typeof = typeIsDefault + } + // if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C" orVals := strings.Split(t, orSeparator) @@ -242,6 +293,7 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s current.next = &cTag{aliasTag: alias, actualAliasTag: current.actualAliasTag, hasAlias: hasAlias, hasTag: true} current = current.next } + current.hasParam = len(vals) > 1 current.tag = vals[0] if len(current.tag) == 0 { @@ -260,8 +312,26 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1) } } + current.isBlockEnd = true } } - return } + +func (v *Validate) fetchCacheTag(tag string) *cTag { + // find cached tag + ctag, found := v.tagCache.Get(tag) + if !found { + v.tagCache.lock.Lock() + defer v.tagCache.lock.Unlock() + + // could have been multiple trying to access, but once first is done this ensures tag + // isn't parsed again. + ctag, found = v.tagCache.Get(tag) + if !found { + ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false) + v.tagCache.Set(tag, ctag) + } + } + return ctag +} diff --git a/vendor/gopkg.in/go-playground/validator.v9/doc.go b/vendor/gopkg.in/go-playground/validator.v9/doc.go index 7da5e591f2e..d7efa1995fd 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/doc.go +++ b/vendor/gopkg.in/go-playground/validator.v9/doc.go @@ -31,7 +31,7 @@ Custom Validation Functions Custom Validation functions can be added. Example: // Structure - func customFunc(fl FielddLevel) bool { + func customFunc(fl FieldLevel) bool { if fl.Field().String() == "invalid" { return false @@ -56,7 +56,7 @@ Cross-Field Validation can be done via the following tags: - eqcsfield - necsfield - gtcsfield - - ftecsfield + - gtecsfield - ltcsfield - ltecsfield @@ -132,7 +132,7 @@ so the above will become excludesall=0x2C. Field `validate:"excludesall=0x2C"` // GOOD! Use the UTF-8 hex representation. } -Pipe ("|") is the default separator of validation tags. If you wish to +Pipe ("|") is the 'or' validation tags deparator. If you wish to have a pipe included within the parameter i.e. excludesall=| you will need to use the UTF-8 hex representation 0x7C, which is replaced in the code as a pipe, so the above will become excludesall=0x7C @@ -193,7 +193,8 @@ Dive This tells the validator to dive into a slice, array or map and validate that level of the slice, array or map with the validation tags that follow. Multidimensional nesting is also supported, each level you wish to dive will -require another dive tag. +require another dive tag. dive has some sub-tags, 'keys' & 'endkeys', please see +the Keys & EndKeys section just below. Usage: dive @@ -211,6 +212,30 @@ Example #2 // []string will be spared validation // required will be applied to string +Keys & EndKeys + +These are to be used together directly after the dive tag and tells the validator +that anything between 'keys' and 'endkeys' applies to the keys of a map and not the +values; think of it like the 'dive' tag, but for map keys instead of values. +Multidimensional nesting is also supported, each level you wish to validate will +require another 'keys' and 'endkeys' tag. These tags are only valid for maps. + + Usage: dive,keys,othertagvalidation(s),endkeys,valuevalidationtags + +Example #1 + + map[string]string with validation tag "gt=0,dive,keys,eg=1|eq=2,endkeys,required" + // gt=0 will be applied to the map itself + // eg=1|eq=2 will be applied to the map keys + // required will be applied to map values + +Example #2 + + map[[2]string]string with validation tag "gt=0,dive,keys,dive,eq=1|eq=2,endkeys,required" + // gt=0 will be applied to the map itself + // eg=1|eq=2 will be applied to each array element in the the map keys + // required will be applied to map values + Required This validates that the value is not the data types default zero value. @@ -220,6 +245,13 @@ ensures the value is not nil. Usage: required +Is Default + +This validates that the value is the default value and is almost the +opposite of required. + + Usage: isdefault + Length For numbers, length will ensure that the value is @@ -461,6 +493,12 @@ to the top level struct. Usage: ltecsfield=InnerStructField.Field +Unique + +For arrays & slices, unique will ensure that there are no duplicates. + + Usage: unique + Alpha Only This validates that a string value contains ASCII alpha characters only @@ -794,6 +832,18 @@ Note: See Go's ParseMAC for accepted formats and types: http://golang.org/src/net/mac.go?s=866:918#L29 +Hostname + +This validates that a string value is a valid Hostname + + Usage: hostname + +Full Qualified Domain Name (FQDN) + +This validates that a string value contains a valid FQDN. + + Usage: fqdn + Alias Validators and Tags NOTE: When returning an error, the tag returned in "FieldError" will be diff --git a/vendor/gopkg.in/go-playground/validator.v9/errors.go b/vendor/gopkg.in/go-playground/validator.v9/errors.go index 820b4bdad83..85f65eff142 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/errors.go +++ b/vendor/gopkg.in/go-playground/validator.v9/errors.go @@ -101,7 +101,9 @@ type FieldError interface { // returns the namespace for the field error, with the tag // name taking precedence over the fields actual name. // - // eq. JSON name "User.fname" see ActualNamespace for comparison + // eg. JSON name "User.fname" + // + // See StructNamespace() for a version that returns actual names. // // NOTE: this field can be blank when validating a single primitive field // using validate.Field(...) as there is no way to extract it's name diff --git a/vendor/gopkg.in/go-playground/validator.v9/regexes.go b/vendor/gopkg.in/go-playground/validator.v9/regexes.go index c2d9830b59e..ec78cebc5cf 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/regexes.go +++ b/vendor/gopkg.in/go-playground/validator.v9/regexes.go @@ -30,6 +30,7 @@ const ( latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$" longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$" sSNRegexString = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` + hostnameRegexString = `^[a-zA-Z][a-zA-Z0-9\-\.]+[a-z-Az0-9]$` ) var ( @@ -60,4 +61,5 @@ var ( latitudeRegex = regexp.MustCompile(latitudeRegexString) longitudeRegex = regexp.MustCompile(longitudeRegexString) sSNRegex = regexp.MustCompile(sSNRegexString) + hostnameRegex = regexp.MustCompile(hostnameRegexString) ) diff --git a/vendor/gopkg.in/go-playground/validator.v9/struct_level.go b/vendor/gopkg.in/go-playground/validator.v9/struct_level.go index e17bc5c1b90..16c620d3d14 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/struct_level.go +++ b/vendor/gopkg.in/go-playground/validator.v9/struct_level.go @@ -52,7 +52,7 @@ type StructLevel interface { // // tag can be an existing validation tag or just something you make up // and process on the flip side it's up to you. - ReportError(field interface{}, fieldName, altName, tag, param string) + ReportError(field interface{}, fieldName, structFieldName string, tag, param string) // reports an error just by passing ValidationErrors // @@ -63,9 +63,6 @@ type StructLevel interface { // eg. pass 'User.FirstName' or 'Users[0].FirstName' depending // on the nesting. most of the time they will be blank, unless you validate // at a level lower the the current field depth - // - // tag can be an existing validation tag or just something you make up - // and process on the flip side it's up to you. ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors) } diff --git a/vendor/gopkg.in/go-playground/validator.v9/translations/en/en.go b/vendor/gopkg.in/go-playground/validator.v9/translations/en/en.go deleted file mode 100644 index a5454cc7eaf..00000000000 --- a/vendor/gopkg.in/go-playground/validator.v9/translations/en/en.go +++ /dev/null @@ -1,1306 +0,0 @@ -package en - -import ( - "fmt" - "log" - "reflect" - "strconv" - "strings" - "time" - - "github.com/go-playground/locales" - ut "github.com/go-playground/universal-translator" - "gopkg.in/go-playground/validator.v9" -) - -// RegisterDefaultTranslations registers a set of default translations -// for all built in tag's in validator; you may add your own as desired. -func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) { - - translations := []struct { - tag string - translation string - override bool - customRegisFunc validator.RegisterTranslationsFunc - customTransFunc validator.TranslationFunc - }{ - { - tag: "required", - translation: "{0} is a required field", - override: false, - }, - { - tag: "len", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("len-string", "{0} must be {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("len-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("len-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("len-number", "{0} must be equal to {1}", false); err != nil { - return - } - - if err = ut.Add("len-items", "{0} must contain {1}", false); err != nil { - return - } - if err = ut.AddCardinal("len-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("len-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - return - - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - - var digits uint64 - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err := strconv.ParseFloat(fe.Param(), 64) - if err != nil { - goto END - } - - switch fe.Kind() { - case reflect.String: - - var c string - - c, err = ut.C("len-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("len-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - c, err = ut.C("len-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("len-items", fe.Field(), c) - - default: - t, err = ut.T("len-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "min", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("min-string", "{0} must be at least {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("min-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("min-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("min-number", "{0} must be {1} or greater", false); err != nil { - return - } - - if err = ut.Add("min-items", "{0} must contain at least {1}", false); err != nil { - return - } - if err = ut.AddCardinal("min-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("min-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - return - - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - - var digits uint64 - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err := strconv.ParseFloat(fe.Param(), 64) - if err != nil { - goto END - } - - switch fe.Kind() { - case reflect.String: - - var c string - - c, err = ut.C("min-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("min-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - c, err = ut.C("min-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("min-items", fe.Field(), c) - - default: - t, err = ut.T("min-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "max", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("max-string", "{0} must be a maximum of {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("max-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("max-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("max-number", "{0} must be {1} or less", false); err != nil { - return - } - - if err = ut.Add("max-items", "{0} must contain at maximum {1}", false); err != nil { - return - } - if err = ut.AddCardinal("max-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("max-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - return - - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - - var digits uint64 - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err := strconv.ParseFloat(fe.Param(), 64) - if err != nil { - goto END - } - - switch fe.Kind() { - case reflect.String: - - var c string - - c, err = ut.C("max-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("max-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - c, err = ut.C("max-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("max-items", fe.Field(), c) - - default: - t, err = ut.T("max-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "eq", - translation: "{0} is not equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - fmt.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "ne", - translation: "{0} should not be equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - fmt.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "lt", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("lt-string", "{0} must be less than {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("lt-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("lt-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("lt-number", "{0} must be less than {1}", false); err != nil { - return - } - - if err = ut.Add("lt-items", "{0} must contain less than {1}", false); err != nil { - return - } - - if err = ut.AddCardinal("lt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("lt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("lt-datetime", "{0} must be less than the current Date & Time", false); err != nil { - return - } - - return - - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - var f64 float64 - var digits uint64 - - fn := func() (err error) { - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err = strconv.ParseFloat(fe.Param(), 64) - - return - } - - switch fe.Kind() { - case reflect.String: - - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("lt-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("lt-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("lt-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("lt-items", fe.Field(), c) - - case reflect.Struct: - if fe.Type() != reflect.TypeOf(time.Time{}) { - err = fmt.Errorf("tag '%s' cannot be used on a struct type.", fe.Tag()) - } - - t, err = ut.T("lt-datetime", fe.Field()) - - default: - err = fn() - if err != nil { - goto END - } - - t, err = ut.T("lt-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "lte", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("lte-string", "{0} must be at maximum {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("lte-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("lte-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("lte-number", "{0} must be {1} or less", false); err != nil { - return - } - - if err = ut.Add("lte-items", "{0} must contain at maximum {1}", false); err != nil { - return - } - - if err = ut.AddCardinal("lte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("lte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("lte-datetime", "{0} must be less than or equal to the current Date & Time", false); err != nil { - return - } - - return - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - var f64 float64 - var digits uint64 - - fn := func() (err error) { - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err = strconv.ParseFloat(fe.Param(), 64) - - return - } - - switch fe.Kind() { - case reflect.String: - - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("lte-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("lte-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("lte-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("lte-items", fe.Field(), c) - - case reflect.Struct: - if fe.Type() != reflect.TypeOf(time.Time{}) { - err = fmt.Errorf("tag '%s' cannot be used on a struct type.", fe.Tag()) - } - - t, err = ut.T("lte-datetime", fe.Field()) - - default: - err = fn() - if err != nil { - goto END - } - - t, err = ut.T("lte-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "gt", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("gt-string", "{0} must be greater than {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("gt-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("gt-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("gt-number", "{0} must be greater than {1}", false); err != nil { - return - } - - if err = ut.Add("gt-items", "{0} must contain more than {1}", false); err != nil { - return - } - - if err = ut.AddCardinal("gt-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("gt-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("gt-datetime", "{0} must be greater than the current Date & Time", false); err != nil { - return - } - - return - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - var f64 float64 - var digits uint64 - - fn := func() (err error) { - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err = strconv.ParseFloat(fe.Param(), 64) - - return - } - - switch fe.Kind() { - case reflect.String: - - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("gt-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("gt-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("gt-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("gt-items", fe.Field(), c) - - case reflect.Struct: - if fe.Type() != reflect.TypeOf(time.Time{}) { - err = fmt.Errorf("tag '%s' cannot be used on a struct type.", fe.Tag()) - } - - t, err = ut.T("gt-datetime", fe.Field()) - - default: - err = fn() - if err != nil { - goto END - } - - t, err = ut.T("gt-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "gte", - customRegisFunc: func(ut ut.Translator) (err error) { - - if err = ut.Add("gte-string", "{0} must be at least {1} in length", false); err != nil { - return - } - - if err = ut.AddCardinal("gte-string-character", "{0} character", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("gte-string-character", "{0} characters", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("gte-number", "{0} must be {1} or greater", false); err != nil { - return - } - - if err = ut.Add("gte-items", "{0} must contain at least {1}", false); err != nil { - return - } - - if err = ut.AddCardinal("gte-items-item", "{0} item", locales.PluralRuleOne, false); err != nil { - return - } - - if err = ut.AddCardinal("gte-items-item", "{0} items", locales.PluralRuleOther, false); err != nil { - return - } - - if err = ut.Add("gte-datetime", "{0} must be greater than or equal to the current Date & Time", false); err != nil { - return - } - - return - }, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - var err error - var t string - var f64 float64 - var digits uint64 - - fn := func() (err error) { - - if idx := strings.Index(fe.Param(), "."); idx != -1 { - digits = uint64(len(fe.Param()[idx+1:])) - } - - f64, err = strconv.ParseFloat(fe.Param(), 64) - - return - } - - switch fe.Kind() { - case reflect.String: - - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("gte-string-character", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("gte-string", fe.Field(), c) - - case reflect.Slice, reflect.Map, reflect.Array: - var c string - - err = fn() - if err != nil { - goto END - } - - c, err = ut.C("gte-items-item", f64, digits, ut.FmtNumber(f64, digits)) - if err != nil { - goto END - } - - t, err = ut.T("gte-items", fe.Field(), c) - - case reflect.Struct: - if fe.Type() != reflect.TypeOf(time.Time{}) { - err = fmt.Errorf("tag '%s' cannot be used on a struct type.", fe.Tag()) - } - - t, err = ut.T("gte-datetime", fe.Field()) - - default: - err = fn() - if err != nil { - goto END - } - - t, err = ut.T("gte-number", fe.Field(), ut.FmtNumber(f64, digits)) - } - - END: - if err != nil { - fmt.Printf("warning: error translating FieldError: %s", err) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "eqfield", - translation: "{0} must be equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "eqcsfield", - translation: "{0} must be equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "necsfield", - translation: "{0} cannot be equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "gtcsfield", - translation: "{0} must be greater than {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "gtecsfield", - translation: "{0} must be greater than or equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "ltcsfield", - translation: "{0} must be less than {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "ltecsfield", - translation: "{0} must be less than or equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "nefield", - translation: "{0} cannot be equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "gtfield", - translation: "{0} must be greater than {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "gtefield", - translation: "{0} must be greater than or equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "ltfield", - translation: "{0} must be less than {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "ltefield", - translation: "{0} must be less than or equal to {1}", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "alpha", - translation: "{0} can only contain alphabetic characters", - override: false, - }, - { - tag: "alphanum", - translation: "{0} can only contain alphanumeric characters", - override: false, - }, - { - tag: "numeric", - translation: "{0} must be a valid numeric value", - override: false, - }, - { - tag: "number", - translation: "{0} must be a valid number", - override: false, - }, - { - tag: "hexadecimal", - translation: "{0} must be a valid hexadecimal", - override: false, - }, - { - tag: "hexcolor", - translation: "{0} must be a valid HEX color", - override: false, - }, - { - tag: "rgb", - translation: "{0} must be a valid RGB color", - override: false, - }, - { - tag: "rgba", - translation: "{0} must be a valid RGBA color", - override: false, - }, - { - tag: "hsl", - translation: "{0} must be a valid HSL color", - override: false, - }, - { - tag: "hsla", - translation: "{0} must be a valid HSLA color", - override: false, - }, - { - tag: "email", - translation: "{0} must be a valid email address", - override: false, - }, - { - tag: "url", - translation: "{0} must be a valid URL", - override: false, - }, - { - tag: "uri", - translation: "{0} must be a valid URI", - override: false, - }, - { - tag: "base64", - translation: "{0} must be a valid Base64 string", - override: false, - }, - { - tag: "contains", - translation: "{0} must contain the text '{1}'", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "containsany", - translation: "{0} must contain at least one of the following characters '{1}'", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "excludes", - translation: "{0} cannot contain the text '{1}'", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "excludesall", - translation: "{0} cannot contain any of the following characters '{1}'", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "excludesrune", - translation: "{0} cannot contain the following '{1}'", - override: false, - customTransFunc: func(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field(), fe.Param()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t - }, - }, - { - tag: "isbn", - translation: "{0} must be a valid ISBN number", - override: false, - }, - { - tag: "isbn10", - translation: "{0} must be a valid ISBN-10 number", - override: false, - }, - { - tag: "isbn13", - translation: "{0} must be a valid ISBN-13 number", - override: false, - }, - { - tag: "uuid", - translation: "{0} must be a valid UUID", - override: false, - }, - { - tag: "uuid3", - translation: "{0} must be a valid version 3 UUID", - override: false, - }, - { - tag: "uuid4", - translation: "{0} must be a valid version 4 UUID", - override: false, - }, - { - tag: "uuid5", - translation: "{0} must be a valid version 5 UUID", - override: false, - }, - { - tag: "ascii", - translation: "{0} must contain only ascii characters", - override: false, - }, - { - tag: "printascii", - translation: "{0} must contain only printable ascii characters", - override: false, - }, - { - tag: "multibyte", - translation: "{0} must contain multibyte characters", - override: false, - }, - { - tag: "datauri", - translation: "{0} must contain a valid Data URI", - override: false, - }, - { - tag: "latitude", - translation: "{0} must contain valid latitude coordinates", - override: false, - }, - { - tag: "longitude", - translation: "{0} must contain a valid longitude coordinates", - override: false, - }, - { - tag: "ssn", - translation: "{0} must be a valid SSN number", - override: false, - }, - { - tag: "ipv4", - translation: "{0} must be a valid IPv4 address", - override: false, - }, - { - tag: "ipv6", - translation: "{0} must be a valid IPv6 address", - override: false, - }, - { - tag: "ip", - translation: "{0} must be a valid IP address", - override: false, - }, - { - tag: "cidr", - translation: "{0} must contain a valid CIDR notation", - override: false, - }, - { - tag: "cidrv4", - translation: "{0} must contain a valid CIDR notation for an IPv4 address", - override: false, - }, - { - tag: "cidrv6", - translation: "{0} must contain a valid CIDR notation for an IPv6 address", - override: false, - }, - { - tag: "tcp_addr", - translation: "{0} must be a valid TCP address", - override: false, - }, - { - tag: "tcp4_addr", - translation: "{0} must be a valid IPv4 TCP address", - override: false, - }, - { - tag: "tcp6_addr", - translation: "{0} must be a valid IPv6 TCP address", - override: false, - }, - { - tag: "udp_addr", - translation: "{0} must be a valid UDP address", - override: false, - }, - { - tag: "udp4_addr", - translation: "{0} must be a valid IPv4 UDP address", - override: false, - }, - { - tag: "udp6_addr", - translation: "{0} must be a valid IPv6 UDP address", - override: false, - }, - { - tag: "ip_addr", - translation: "{0} must be a resolvable IP address", - override: false, - }, - { - tag: "ip4_addr", - translation: "{0} must be a resolvable IPv4 address", - override: false, - }, - { - tag: "ip6_addr", - translation: "{0} must be a resolvable IPv6 address", - override: false, - }, - { - tag: "unix_addr", - translation: "{0} must be a resolvable UNIX address", - override: false, - }, - { - tag: "mac", - translation: "{0} must contain a valid MAC address", - override: false, - }, - { - tag: "iscolor", - translation: "{0} must be a valid color", - override: false, - }, - } - - for _, t := range translations { - - if t.customTransFunc != nil && t.customRegisFunc != nil { - - err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc) - - } else if t.customTransFunc != nil && t.customRegisFunc == nil { - - err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc) - - } else if t.customTransFunc == nil && t.customRegisFunc != nil { - - err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc) - - } else { - err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc) - } - - if err != nil { - return - } - } - - return -} - -func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc { - - return func(ut ut.Translator) (err error) { - - if err = ut.Add(tag, translation, override); err != nil { - return - } - - return - - } - -} - -func translateFunc(ut ut.Translator, fe validator.FieldError) string { - - t, err := ut.T(fe.Tag(), fe.Field()) - if err != nil { - log.Printf("warning: error translating FieldError: %#v", fe) - return fe.(error).Error() - } - - return t -} diff --git a/vendor/gopkg.in/go-playground/validator.v9/validator.go b/vendor/gopkg.in/go-playground/validator.v9/validator.go index 115dab44f9b..5fbb1660db4 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/validator.go +++ b/vendor/gopkg.in/go-playground/validator.v9/validator.go @@ -112,7 +112,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr return } - if ct.typeof == typeOmitEmpty { + if ct.typeof == typeOmitEmpty || ct.typeof == typeIsDefault { return } @@ -174,6 +174,39 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr if ct.typeof == typeStructOnly { goto CONTINUE + } else if ct.typeof == typeIsDefault { + // set Field Level fields + v.slflParent = parent + v.flField = current + v.cf = cf + v.ct = ct + + if !ct.fn(ctx, v) { + v.str1 = string(append(ns, cf.altName...)) + + if v.v.hasTagNameFunc { + v.str2 = string(append(structNs, cf.name...)) + } else { + v.str2 = v.str1 + } + + v.errs = append(v.errs, + &fieldError{ + v: v.v, + tag: ct.aliasTag, + actualTag: ct.tag, + ns: v.str1, + structNs: v.str2, + fieldLen: uint8(len(cf.altName)), + structfieldLen: uint8(len(cf.name)), + value: current.Interface(), + param: ct.param, + kind: kind, + typ: typ, + }, + ) + return + } } ct = ct.next @@ -227,6 +260,9 @@ OUTER: ct = ct.next continue + case typeEndKeys: + return + case typeDive: ct = ct.next @@ -261,7 +297,6 @@ OUTER: reusableCF.altName = string(v.misc) } - v.traverseField(ctx, parent, current.Index(i), ns, structNs, reusableCF, ct) } @@ -292,7 +327,15 @@ OUTER: reusableCF.altName = string(v.misc) } - v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct) + if ct != nil && ct.typeof == typeKeys && ct.keys != nil { + v.traverseField(ctx, parent, key, ns, structNs, reusableCF, ct.keys) + // can be nil when just keys being validated + if ct.next != nil { + v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct.next) + } + } else { + v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct) + } } default: @@ -335,14 +378,13 @@ OUTER: v.misc = append(v.misc, '|') v.misc = append(v.misc, ct.tag...) - if len(ct.param) > 0 { + if ct.hasParam { v.misc = append(v.misc, '=') v.misc = append(v.misc, ct.param...) } - if ct.next == nil || ct.next.typeof != typeOr { // ct.typeof != typeOr + if ct.isBlockEnd || ct.next == nil { // if we get here, no valid 'or' value and no more tags - v.str1 = string(append(ns, cf.altName...)) if v.v.hasTagNameFunc { @@ -404,10 +446,6 @@ OUTER: v.cf = cf v.ct = ct - // // report error interface functions need these - // v.ns = ns - // v.actualNs = structNs - if !ct.fn(ctx, v) { v.str1 = string(append(ns, cf.altName...)) @@ -435,9 +473,7 @@ OUTER: ) return - } - ct = ct.next } } diff --git a/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go b/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go index da5248103e7..f4b49a84c6a 100644 --- a/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go +++ b/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go @@ -22,8 +22,11 @@ const ( structOnlyTag = "structonly" noStructLevelTag = "nostructlevel" omitempty = "omitempty" + isdefault = "isdefault" skipValidationTag = "-" diveTag = "dive" + keysTag = "keys" + endKeysTag = "endkeys" requiredTag = "required" namespaceSeparator = "." leftBracket = "[" @@ -176,12 +179,8 @@ func (v *Validate) RegisterAlias(alias, tags string) { } // RegisterStructValidation registers a StructLevelFunc against a number of types. -// This is akin to implementing the 'Validatable' interface, but for structs for which -// you may not have access or rights to change. // -// NOTES: -// - if this and the 'Validatable' interface are implemented the Struct Level takes precedence as to enable -// a struct out of your control's validation to be overridden +// NOTE: // - this method is not thread-safe it is intended that these all be registered prior to any validation func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) { v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...) @@ -189,12 +188,8 @@ func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interfa // RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing // of contextual validation information via context.Context. -// This is akin to implementing a 'Validatable' interface, but for structs for which -// you may not have access or rights to change. // -// NOTES: -// - if this and the 'Validatable' interface are implemented the Struct Level takes precedence as to enable -// a struct out of your control's validation to be overridden +// NOTE: // - this method is not thread-safe it is intended that these all be registered prior to any validation func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) { @@ -494,9 +489,10 @@ func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields .. // var i int // validate.Var(i, "gt=1,lt=10") // -// WARNING: a struct can be passed for validation eg. time.Time is a struct or if you have a custom type and have registered -// a custom type handler, so must allow it; however unforseen validations will occur if trying to validate a struct -// that is meant to be passed to 'validate.Struct' +// WARNING: a struct can be passed for validation eg. time.Time is a struct or +// if you have a custom type and have registered a custom type handler, so must +// allow it; however unforseen validations will occur if trying to validate a +// struct that is meant to be passed to 'validate.Struct' // // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. @@ -511,9 +507,10 @@ func (v *Validate) Var(field interface{}, tag string) error { // var i int // validate.Var(i, "gt=1,lt=10") // -// WARNING: a struct can be passed for validation eg. time.Time is a struct or if you have a custom type and have registered -// a custom type handler, so must allow it; however unforseen validations will occur if trying to validate a struct -// that is meant to be passed to 'validate.Struct' +// WARNING: a struct can be passed for validation eg. time.Time is a struct or +// if you have a custom type and have registered a custom type handler, so must +// allow it; however unforseen validations will occur if trying to validate a +// struct that is meant to be passed to 'validate.Struct' // // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. @@ -523,36 +520,18 @@ func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (e return nil } - // find cached tag - ctag, ok := v.tagCache.Get(tag) - if !ok { - v.tagCache.lock.Lock() - defer v.tagCache.lock.Unlock() - - // could have been multiple trying to access, but once first is done this ensures tag - // isn't parsed again. - ctag, ok = v.tagCache.Get(tag) - if !ok { - ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false) - v.tagCache.Set(tag, ctag) - } - } - + ctag := v.fetchCacheTag(tag) val := reflect.ValueOf(field) - vd := v.pool.Get().(*validate) vd.top = val vd.isPartial = false - vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag) if len(vd.errs) > 0 { err = vd.errs vd.errs = nil } - v.pool.Put(vd) - return } @@ -562,9 +541,10 @@ func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (e // s2 := "abcd" // validate.VarWithValue(s1, s2, "eqcsfield") // returns true // -// WARNING: a struct can be passed for validation eg. time.Time is a struct or if you have a custom type and have registered -// a custom type handler, so must allow it; however unforseen validations will occur if trying to validate a struct -// that is meant to be passed to 'validate.Struct' +// WARNING: a struct can be passed for validation eg. time.Time is a struct or +// if you have a custom type and have registered a custom type handler, so must +// allow it; however unforseen validations will occur if trying to validate a +// struct that is meant to be passed to 'validate.Struct' // // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. @@ -580,9 +560,10 @@ func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string // s2 := "abcd" // validate.VarWithValue(s1, s2, "eqcsfield") // returns true // -// WARNING: a struct can be passed for validation eg. time.Time is a struct or if you have a custom type and have registered -// a custom type handler, so must allow it; however unforseen validations will occur if trying to validate a struct -// that is meant to be passed to 'validate.Struct' +// WARNING: a struct can be passed for validation eg. time.Time is a struct or +// if you have a custom type and have registered a custom type handler, so must +// allow it; however unforseen validations will occur if trying to validate a +// struct that is meant to be passed to 'validate.Struct' // // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. @@ -591,36 +572,17 @@ func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other if len(tag) == 0 || tag == skipValidationTag { return nil } - - // find cached tag - ctag, ok := v.tagCache.Get(tag) - if !ok { - v.tagCache.lock.Lock() - defer v.tagCache.lock.Unlock() - - // could have been multiple trying to access, but once first is done this ensures tag - // isn't parsed again. - ctag, ok = v.tagCache.Get(tag) - if !ok { - ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false) - v.tagCache.Set(tag, ctag) - } - } - + ctag := v.fetchCacheTag(tag) otherVal := reflect.ValueOf(other) - vd := v.pool.Get().(*validate) vd.top = otherVal vd.isPartial = false - vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag) if len(vd.errs) > 0 { err = vd.errs vd.errs = nil } - v.pool.Put(vd) - return } diff --git a/vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/.gitignore b/vendor/gopkg.in/natefinch/npipe.v2/.gitignore similarity index 100% rename from vendor/github.com/stretchr/testify/vendor/github.com/stretchr/objx/.gitignore rename to vendor/gopkg.in/natefinch/npipe.v2/.gitignore diff --git a/vendor/gopkg.in/natefinch/npipe.v2/LICENSE.txt b/vendor/gopkg.in/natefinch/npipe.v2/LICENSE.txt new file mode 100644 index 00000000000..a4a11046cc9 --- /dev/null +++ b/vendor/gopkg.in/natefinch/npipe.v2/LICENSE.txt @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2013 npipe authors + +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. \ No newline at end of file diff --git a/vendor/gopkg.in/natefinch/npipe.v2/README.md b/vendor/gopkg.in/natefinch/npipe.v2/README.md new file mode 100644 index 00000000000..420a4d16c7d --- /dev/null +++ b/vendor/gopkg.in/natefinch/npipe.v2/README.md @@ -0,0 +1,308 @@ +npipe [![Build status](https://ci.appveyor.com/api/projects/status/00vuepirsot29qwi)](https://ci.appveyor.com/project/natefinch/npipe) [![GoDoc](https://godoc.org/gopkg.in/natefinch/npipe.v2?status.svg)](https://godoc.org/gopkg.in/natefinch/npipe.v2) +===== +Package npipe provides a pure Go wrapper around Windows named pipes. + +Windows named pipe documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365780 + +Note that the code lives at https://github.com/natefinch/npipe (v2 branch) +but should be imported as gopkg.in/natefinch/npipe.v2 (the package name is +still npipe). + +npipe provides an interface based on stdlib's net package, with Dial, Listen, +and Accept functions, as well as associated implementations of net.Conn and +net.Listener. It supports rpc over the connection. + +### Notes +* Deadlines for reading/writing to the connection are only functional in Windows Vista/Server 2008 and above, due to limitations with the Windows API. + +* The pipes support byte mode only (no support for message mode) + +### Examples +The Dial function connects a client to a named pipe: + + + conn, err := npipe.Dial(`\\.\pipe\mypipename`) + if err != nil { + + } + fmt.Fprintf(conn, "Hi server!\n") + msg, err := bufio.NewReader(conn).ReadString('\n') + ... + +The Listen function creates servers: + + + ln, err := npipe.Listen(`\\.\pipe\mypipename`) + if err != nil { + // handle error + } + for { + conn, err := ln.Accept() + if err != nil { + // handle error + continue + } + go handleConnection(conn) + } + + + + + +## Variables +``` go +var ErrClosed = PipeError{"Pipe has been closed.", false} +``` +ErrClosed is the error returned by PipeListener.Accept when Close is called +on the PipeListener. + + + +## type PipeAddr +``` go +type PipeAddr string +``` +PipeAddr represents the address of a named pipe. + + + + + + + + + + + +### func (PipeAddr) Network +``` go +func (a PipeAddr) Network() string +``` +Network returns the address's network name, "pipe". + + + +### func (PipeAddr) String +``` go +func (a PipeAddr) String() string +``` +String returns the address of the pipe + + + +## type PipeConn +``` go +type PipeConn struct { + // contains filtered or unexported fields +} +``` +PipeConn is the implementation of the net.Conn interface for named pipe connections. + + + + + + + + + +### func Dial +``` go +func Dial(address string) (*PipeConn, error) +``` +Dial connects to a named pipe with the given address. If the specified pipe is not available, +it will wait indefinitely for the pipe to become available. + +The address must be of the form \\.\\pipe\ for local pipes and \\\pipe\ +for remote pipes. + +Dial will return a PipeError if you pass in a badly formatted pipe name. + +Examples: + + + // local pipe + conn, err := Dial(`\\.\pipe\mypipename`) + + // remote pipe + conn, err := Dial(`\\othercomp\pipe\mypipename`) + + +### func DialTimeout +``` go +func DialTimeout(address string, timeout time.Duration) (*PipeConn, error) +``` +DialTimeout acts like Dial, but will time out after the duration of timeout + + + + +### func (\*PipeConn) Close +``` go +func (c *PipeConn) Close() error +``` +Close closes the connection. + + + +### func (\*PipeConn) LocalAddr +``` go +func (c *PipeConn) LocalAddr() net.Addr +``` +LocalAddr returns the local network address. + + + +### func (\*PipeConn) Read +``` go +func (c *PipeConn) Read(b []byte) (int, error) +``` +Read implements the net.Conn Read method. + + + +### func (\*PipeConn) RemoteAddr +``` go +func (c *PipeConn) RemoteAddr() net.Addr +``` +RemoteAddr returns the remote network address. + + + +### func (\*PipeConn) SetDeadline +``` go +func (c *PipeConn) SetDeadline(t time.Time) error +``` +SetDeadline implements the net.Conn SetDeadline method. +Note that timeouts are only supported on Windows Vista/Server 2008 and above + + + +### func (\*PipeConn) SetReadDeadline +``` go +func (c *PipeConn) SetReadDeadline(t time.Time) error +``` +SetReadDeadline implements the net.Conn SetReadDeadline method. +Note that timeouts are only supported on Windows Vista/Server 2008 and above + + + +### func (\*PipeConn) SetWriteDeadline +``` go +func (c *PipeConn) SetWriteDeadline(t time.Time) error +``` +SetWriteDeadline implements the net.Conn SetWriteDeadline method. +Note that timeouts are only supported on Windows Vista/Server 2008 and above + + + +### func (\*PipeConn) Write +``` go +func (c *PipeConn) Write(b []byte) (int, error) +``` +Write implements the net.Conn Write method. + + + +## type PipeError +``` go +type PipeError struct { + // contains filtered or unexported fields +} +``` +PipeError is an error related to a call to a pipe + + + + + + + + + + + +### func (PipeError) Error +``` go +func (e PipeError) Error() string +``` +Error implements the error interface + + + +### func (PipeError) Temporary +``` go +func (e PipeError) Temporary() bool +``` +Temporary implements net.AddrError.Temporary() + + + +### func (PipeError) Timeout +``` go +func (e PipeError) Timeout() bool +``` +Timeout implements net.AddrError.Timeout() + + + +## type PipeListener +``` go +type PipeListener struct { + // contains filtered or unexported fields +} +``` +PipeListener is a named pipe listener. Clients should typically +use variables of type net.Listener instead of assuming named pipe. + + + + + + + + + +### func Listen +``` go +func Listen(address string) (*PipeListener, error) +``` +Listen returns a new PipeListener that will listen on a pipe with the given +address. The address must be of the form \\.\pipe\ + +Listen will return a PipeError for an incorrectly formatted pipe name. + + + + +### func (\*PipeListener) Accept +``` go +func (l *PipeListener) Accept() (net.Conn, error) +``` +Accept implements the Accept method in the net.Listener interface; it +waits for the next call and returns a generic net.Conn. + + + +### func (\*PipeListener) AcceptPipe +``` go +func (l *PipeListener) AcceptPipe() (*PipeConn, error) +``` +AcceptPipe accepts the next incoming call and returns the new connection. + + + +### func (\*PipeListener) Addr +``` go +func (l *PipeListener) Addr() net.Addr +``` +Addr returns the listener's network address, a PipeAddr. + + + +### func (\*PipeListener) Close +``` go +func (l *PipeListener) Close() error +``` +Close stops listening on the address. +Already Accepted connections are not closed. diff --git a/vendor/gopkg.in/natefinch/npipe.v2/doc.go b/vendor/gopkg.in/natefinch/npipe.v2/doc.go new file mode 100644 index 00000000000..3445773b460 --- /dev/null +++ b/vendor/gopkg.in/natefinch/npipe.v2/doc.go @@ -0,0 +1,50 @@ +// Copyright 2013 Nate Finch. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// Package npipe provides a pure Go wrapper around Windows named pipes. +// +// !! Note, this package is Windows-only. There is no code to compile on linux. +// +// Windows named pipe documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365780 +// +// Note that the code lives at https://github.com/natefinch/npipe (v2 branch) +// but should be imported as gopkg.in/natefinch/npipe.v2 (the package name is +// still npipe). +// +// npipe provides an interface based on stdlib's net package, with Dial, Listen, +// and Accept functions, as well as associated implementations of net.Conn and +// net.Listener. It supports rpc over the connection. +// +// Notes +// +// * Deadlines for reading/writing to the connection are only functional in Windows Vista/Server 2008 and above, due to limitations with the Windows API. +// +// * The pipes support byte mode only (no support for message mode) +// +// Examples +// +// The Dial function connects a client to a named pipe: +// conn, err := npipe.Dial(`\\.\pipe\mypipename`) +// if err != nil { +// +// } +// fmt.Fprintf(conn, "Hi server!\n") +// msg, err := bufio.NewReader(conn).ReadString('\n') +// ... +// +// The Listen function creates servers: +// +// ln, err := npipe.Listen(`\\.\pipe\mypipename`) +// if err != nil { +// // handle error +// } +// for { +// conn, err := ln.Accept() +// if err != nil { +// // handle error +// continue +// } +// go handleConnection(conn) +// } +package npipe diff --git a/vendor/gopkg.in/natefinch/npipe.v2/npipe_windows.go b/vendor/gopkg.in/natefinch/npipe.v2/npipe_windows.go new file mode 100755 index 00000000000..5e7cf13ee31 --- /dev/null +++ b/vendor/gopkg.in/natefinch/npipe.v2/npipe_windows.go @@ -0,0 +1,531 @@ +package npipe + +//sys createNamedPipe(name *uint16, openMode uint32, pipeMode uint32, maxInstances uint32, outBufSize uint32, inBufSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW +//sys connectNamedPipe(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) = ConnectNamedPipe +//sys disconnectNamedPipe(handle syscall.Handle) (err error) = DisconnectNamedPipe +//sys waitNamedPipe(name *uint16, timeout uint32) (err error) = WaitNamedPipeW +//sys createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateEventW +//sys getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, transferred *uint32, wait bool) (err error) = GetOverlappedResult +//sys cancelIoEx(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) = CancelIoEx + +import ( + "fmt" + "io" + "net" + "sync" + "syscall" + "time" +) + +const ( + // openMode + pipe_access_duplex = 0x3 + pipe_access_inbound = 0x1 + pipe_access_outbound = 0x2 + + // openMode write flags + file_flag_first_pipe_instance = 0x00080000 + file_flag_write_through = 0x80000000 + file_flag_overlapped = 0x40000000 + + // openMode ACL flags + write_dac = 0x00040000 + write_owner = 0x00080000 + access_system_security = 0x01000000 + + // pipeMode + pipe_type_byte = 0x0 + pipe_type_message = 0x4 + + // pipeMode read mode flags + pipe_readmode_byte = 0x0 + pipe_readmode_message = 0x2 + + // pipeMode wait mode flags + pipe_wait = 0x0 + pipe_nowait = 0x1 + + // pipeMode remote-client mode flags + pipe_accept_remote_clients = 0x0 + pipe_reject_remote_clients = 0x8 + + pipe_unlimited_instances = 255 + + nmpwait_wait_forever = 0xFFFFFFFF + + // the two not-an-errors below occur if a client connects to the pipe between + // the server's CreateNamedPipe and ConnectNamedPipe calls. + error_no_data syscall.Errno = 0xE8 + error_pipe_connected syscall.Errno = 0x217 + error_pipe_busy syscall.Errno = 0xE7 + error_sem_timeout syscall.Errno = 0x79 + + error_bad_pathname syscall.Errno = 0xA1 + error_invalid_name syscall.Errno = 0x7B + + error_io_incomplete syscall.Errno = 0x3e4 +) + +var _ net.Conn = (*PipeConn)(nil) +var _ net.Listener = (*PipeListener)(nil) + +// ErrClosed is the error returned by PipeListener.Accept when Close is called +// on the PipeListener. +var ErrClosed = PipeError{"Pipe has been closed.", false} + +// PipeError is an error related to a call to a pipe +type PipeError struct { + msg string + timeout bool +} + +// Error implements the error interface +func (e PipeError) Error() string { + return e.msg +} + +// Timeout implements net.AddrError.Timeout() +func (e PipeError) Timeout() bool { + return e.timeout +} + +// Temporary implements net.AddrError.Temporary() +func (e PipeError) Temporary() bool { + return false +} + +// Dial connects to a named pipe with the given address. If the specified pipe is not available, +// it will wait indefinitely for the pipe to become available. +// +// The address must be of the form \\.\\pipe\ for local pipes and \\\pipe\ +// for remote pipes. +// +// Dial will return a PipeError if you pass in a badly formatted pipe name. +// +// Examples: +// // local pipe +// conn, err := Dial(`\\.\pipe\mypipename`) +// +// // remote pipe +// conn, err := Dial(`\\othercomp\pipe\mypipename`) +func Dial(address string) (*PipeConn, error) { + for { + conn, err := dial(address, nmpwait_wait_forever) + if err == nil { + return conn, nil + } + if isPipeNotReady(err) { + <-time.After(100 * time.Millisecond) + continue + } + return nil, err + } +} + +// DialTimeout acts like Dial, but will time out after the duration of timeout +func DialTimeout(address string, timeout time.Duration) (*PipeConn, error) { + deadline := time.Now().Add(timeout) + + now := time.Now() + for now.Before(deadline) { + millis := uint32(deadline.Sub(now) / time.Millisecond) + conn, err := dial(address, millis) + if err == nil { + return conn, nil + } + if err == error_sem_timeout { + // This is WaitNamedPipe's timeout error, so we know we're done + return nil, PipeError{fmt.Sprintf( + "Timed out waiting for pipe '%s' to come available", address), true} + } + if isPipeNotReady(err) { + left := deadline.Sub(time.Now()) + retry := 100 * time.Millisecond + if left > retry { + <-time.After(retry) + } else { + <-time.After(left - time.Millisecond) + } + now = time.Now() + continue + } + return nil, err + } + return nil, PipeError{fmt.Sprintf( + "Timed out waiting for pipe '%s' to come available", address), true} +} + +// isPipeNotReady checks the error to see if it indicates the pipe is not ready +func isPipeNotReady(err error) bool { + // Pipe Busy means another client just grabbed the open pipe end, + // and the server hasn't made a new one yet. + // File Not Found means the server hasn't created the pipe yet. + // Neither is a fatal error. + + return err == syscall.ERROR_FILE_NOT_FOUND || err == error_pipe_busy +} + +// newOverlapped creates a structure used to track asynchronous +// I/O requests that have been issued. +func newOverlapped() (*syscall.Overlapped, error) { + event, err := createEvent(nil, true, true, nil) + if err != nil { + return nil, err + } + return &syscall.Overlapped{HEvent: event}, nil +} + +// waitForCompletion waits for an asynchronous I/O request referred to by overlapped to complete. +// This function returns the number of bytes transferred by the operation and an error code if +// applicable (nil otherwise). +func waitForCompletion(handle syscall.Handle, overlapped *syscall.Overlapped) (uint32, error) { + _, err := syscall.WaitForSingleObject(overlapped.HEvent, syscall.INFINITE) + if err != nil { + return 0, err + } + var transferred uint32 + err = getOverlappedResult(handle, overlapped, &transferred, true) + return transferred, err +} + +// dial is a helper to initiate a connection to a named pipe that has been started by a server. +// The timeout is only enforced if the pipe server has already created the pipe, otherwise +// this function will return immediately. +func dial(address string, timeout uint32) (*PipeConn, error) { + name, err := syscall.UTF16PtrFromString(string(address)) + if err != nil { + return nil, err + } + // If at least one instance of the pipe has been created, this function + // will wait timeout milliseconds for it to become available. + // It will return immediately regardless of timeout, if no instances + // of the named pipe have been created yet. + // If this returns with no error, there is a pipe available. + if err := waitNamedPipe(name, timeout); err != nil { + if err == error_bad_pathname { + // badly formatted pipe name + return nil, badAddr(address) + } + return nil, err + } + pathp, err := syscall.UTF16PtrFromString(address) + if err != nil { + return nil, err + } + handle, err := syscall.CreateFile(pathp, syscall.GENERIC_READ|syscall.GENERIC_WRITE, + uint32(syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE), nil, syscall.OPEN_EXISTING, + syscall.FILE_FLAG_OVERLAPPED, 0) + if err != nil { + return nil, err + } + return &PipeConn{handle: handle, addr: PipeAddr(address)}, nil +} + +// Listen returns a new PipeListener that will listen on a pipe with the given +// address. The address must be of the form \\.\pipe\ +// +// Listen will return a PipeError for an incorrectly formatted pipe name. +func Listen(address string) (*PipeListener, error) { + handle, err := createPipe(address, true) + if err == error_invalid_name { + return nil, badAddr(address) + } + if err != nil { + return nil, err + } + + return &PipeListener{ + addr: PipeAddr(address), + handle: handle, + }, nil +} + +// PipeListener is a named pipe listener. Clients should typically +// use variables of type net.Listener instead of assuming named pipe. +type PipeListener struct { + mu sync.Mutex + + addr PipeAddr + handle syscall.Handle + closed bool + + // acceptHandle contains the current handle waiting for + // an incoming connection or nil. + acceptHandle syscall.Handle + // acceptOverlapped is set before waiting on a connection. + // If not waiting, it is nil. + acceptOverlapped *syscall.Overlapped +} + +// Accept implements the Accept method in the net.Listener interface; it +// waits for the next call and returns a generic net.Conn. +func (l *PipeListener) Accept() (net.Conn, error) { + c, err := l.AcceptPipe() + for err == error_no_data { + // Ignore clients that connect and immediately disconnect. + c, err = l.AcceptPipe() + } + if err != nil { + return nil, err + } + return c, nil +} + +// AcceptPipe accepts the next incoming call and returns the new connection. +// It might return an error if a client connected and immediately cancelled +// the connection. +func (l *PipeListener) AcceptPipe() (*PipeConn, error) { + if l == nil { + return nil, syscall.EINVAL + } + + l.mu.Lock() + defer l.mu.Unlock() + + if l.addr == "" || l.closed { + return nil, syscall.EINVAL + } + + // the first time we call accept, the handle will have been created by the Listen + // call. This is to prevent race conditions where the client thinks the server + // isn't listening because it hasn't actually called create yet. After the first time, we'll + // have to create a new handle each time + handle := l.handle + if handle == 0 { + var err error + handle, err = createPipe(string(l.addr), false) + if err != nil { + return nil, err + } + } else { + l.handle = 0 + } + + overlapped, err := newOverlapped() + if err != nil { + return nil, err + } + defer syscall.CloseHandle(overlapped.HEvent) + err = connectNamedPipe(handle, overlapped) + if err == nil || err == error_pipe_connected { + return &PipeConn{handle: handle, addr: l.addr}, nil + } + + if err == error_io_incomplete || err == syscall.ERROR_IO_PENDING { + l.acceptOverlapped = overlapped + l.acceptHandle = handle + // unlock here so close can function correctly while we wait (we'll + // get relocked via the defer below, before the original defer + // unlock happens.) + l.mu.Unlock() + defer func() { + l.mu.Lock() + l.acceptOverlapped = nil + l.acceptHandle = 0 + // unlock is via defer above. + }() + _, err = waitForCompletion(handle, overlapped) + } + if err == syscall.ERROR_OPERATION_ABORTED { + // Return error compatible to net.Listener.Accept() in case the + // listener was closed. + return nil, ErrClosed + } + if err != nil { + return nil, err + } + return &PipeConn{handle: handle, addr: l.addr}, nil +} + +// Close stops listening on the address. +// Already Accepted connections are not closed. +func (l *PipeListener) Close() error { + l.mu.Lock() + defer l.mu.Unlock() + + if l.closed { + return nil + } + l.closed = true + if l.handle != 0 { + err := disconnectNamedPipe(l.handle) + if err != nil { + return err + } + err = syscall.CloseHandle(l.handle) + if err != nil { + return err + } + l.handle = 0 + } + if l.acceptOverlapped != nil && l.acceptHandle != 0 { + // Cancel the pending IO. This call does not block, so it is safe + // to hold onto the mutex above. + if err := cancelIoEx(l.acceptHandle, l.acceptOverlapped); err != nil { + return err + } + err := syscall.CloseHandle(l.acceptOverlapped.HEvent) + if err != nil { + return err + } + l.acceptOverlapped.HEvent = 0 + err = syscall.CloseHandle(l.acceptHandle) + if err != nil { + return err + } + l.acceptHandle = 0 + } + return nil +} + +// Addr returns the listener's network address, a PipeAddr. +func (l *PipeListener) Addr() net.Addr { return l.addr } + +// PipeConn is the implementation of the net.Conn interface for named pipe connections. +type PipeConn struct { + handle syscall.Handle + addr PipeAddr + + // these aren't actually used yet + readDeadline *time.Time + writeDeadline *time.Time +} + +type iodata struct { + n uint32 + err error +} + +// completeRequest looks at iodata to see if a request is pending. If so, it waits for it to either complete or to +// abort due to hitting the specified deadline. Deadline may be set to nil to wait forever. If no request is pending, +// the content of iodata is returned. +func (c *PipeConn) completeRequest(data iodata, deadline *time.Time, overlapped *syscall.Overlapped) (int, error) { + if data.err == error_io_incomplete || data.err == syscall.ERROR_IO_PENDING { + var timer <-chan time.Time + if deadline != nil { + if timeDiff := deadline.Sub(time.Now()); timeDiff > 0 { + timer = time.After(timeDiff) + } + } + done := make(chan iodata) + go func() { + n, err := waitForCompletion(c.handle, overlapped) + done <- iodata{n, err} + }() + select { + case data = <-done: + case <-timer: + syscall.CancelIoEx(c.handle, overlapped) + data = iodata{0, timeout(c.addr.String())} + } + } + // Windows will produce ERROR_BROKEN_PIPE upon closing + // a handle on the other end of a connection. Go RPC + // expects an io.EOF error in this case. + if data.err == syscall.ERROR_BROKEN_PIPE { + data.err = io.EOF + } + return int(data.n), data.err +} + +// Read implements the net.Conn Read method. +func (c *PipeConn) Read(b []byte) (int, error) { + // Use ReadFile() rather than Read() because the latter + // contains a workaround that eats ERROR_BROKEN_PIPE. + overlapped, err := newOverlapped() + if err != nil { + return 0, err + } + defer syscall.CloseHandle(overlapped.HEvent) + var n uint32 + err = syscall.ReadFile(c.handle, b, &n, overlapped) + return c.completeRequest(iodata{n, err}, c.readDeadline, overlapped) +} + +// Write implements the net.Conn Write method. +func (c *PipeConn) Write(b []byte) (int, error) { + overlapped, err := newOverlapped() + if err != nil { + return 0, err + } + defer syscall.CloseHandle(overlapped.HEvent) + var n uint32 + err = syscall.WriteFile(c.handle, b, &n, overlapped) + return c.completeRequest(iodata{n, err}, c.writeDeadline, overlapped) +} + +// Close closes the connection. +func (c *PipeConn) Close() error { + return syscall.CloseHandle(c.handle) +} + +// LocalAddr returns the local network address. +func (c *PipeConn) LocalAddr() net.Addr { + return c.addr +} + +// RemoteAddr returns the remote network address. +func (c *PipeConn) RemoteAddr() net.Addr { + // not sure what to do here, we don't have remote addr.... + return c.addr +} + +// SetDeadline implements the net.Conn SetDeadline method. +// Note that timeouts are only supported on Windows Vista/Server 2008 and above +func (c *PipeConn) SetDeadline(t time.Time) error { + c.SetReadDeadline(t) + c.SetWriteDeadline(t) + return nil +} + +// SetReadDeadline implements the net.Conn SetReadDeadline method. +// Note that timeouts are only supported on Windows Vista/Server 2008 and above +func (c *PipeConn) SetReadDeadline(t time.Time) error { + c.readDeadline = &t + return nil +} + +// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +// Note that timeouts are only supported on Windows Vista/Server 2008 and above +func (c *PipeConn) SetWriteDeadline(t time.Time) error { + c.writeDeadline = &t + return nil +} + +// PipeAddr represents the address of a named pipe. +type PipeAddr string + +// Network returns the address's network name, "pipe". +func (a PipeAddr) Network() string { return "pipe" } + +// String returns the address of the pipe +func (a PipeAddr) String() string { + return string(a) +} + +// createPipe is a helper function to make sure we always create pipes +// with the same arguments, since subsequent calls to create pipe need +// to use the same arguments as the first one. If first is set, fail +// if the pipe already exists. +func createPipe(address string, first bool) (syscall.Handle, error) { + n, err := syscall.UTF16PtrFromString(address) + if err != nil { + return 0, err + } + mode := uint32(pipe_access_duplex | syscall.FILE_FLAG_OVERLAPPED) + if first { + mode |= file_flag_first_pipe_instance + } + return createNamedPipe(n, + mode, + pipe_type_byte, + pipe_unlimited_instances, + 512, 512, 0, nil) +} + +func badAddr(addr string) PipeError { + return PipeError{fmt.Sprintf("Invalid pipe address '%s'.", addr), false} +} +func timeout(addr string) PipeError { + return PipeError{fmt.Sprintf("Pipe IO timed out waiting for '%s'", addr), true} +} diff --git a/vendor/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go b/vendor/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go new file mode 100644 index 00000000000..c283e6cf956 --- /dev/null +++ b/vendor/gopkg.in/natefinch/npipe.v2/znpipe_windows_386.go @@ -0,0 +1,124 @@ +// +build windows +// go build mksyscall_windows.go && ./mksyscall_windows npipe_windows.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package npipe + +import "unsafe" +import "syscall" + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe") + procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") +) + +func createNamedPipe(name *uint16, openMode uint32, pipeMode uint32, maxInstances uint32, outBufSize uint32, inBufSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(openMode), uintptr(pipeMode), uintptr(maxInstances), uintptr(outBufSize), uintptr(inBufSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func cancelIoEx(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func connectNamedPipe(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func disconnectNamedPipe(handle syscall.Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func waitNamedPipe(name *uint16, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) { + var _p0 uint32 + if manualReset { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if initialState { + _p1 = 1 + } else { + _p1 = 0 + } + r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(sa)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, transferred *uint32, wait bool) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transferred)), uintptr(_p0), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} diff --git a/vendor/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go b/vendor/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go new file mode 100644 index 00000000000..c283e6cf956 --- /dev/null +++ b/vendor/gopkg.in/natefinch/npipe.v2/znpipe_windows_amd64.go @@ -0,0 +1,124 @@ +// +build windows +// go build mksyscall_windows.go && ./mksyscall_windows npipe_windows.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package npipe + +import "unsafe" +import "syscall" + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe") + procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") +) + +func createNamedPipe(name *uint16, openMode uint32, pipeMode uint32, maxInstances uint32, outBufSize uint32, inBufSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(openMode), uintptr(pipeMode), uintptr(maxInstances), uintptr(outBufSize), uintptr(inBufSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func cancelIoEx(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func connectNamedPipe(handle syscall.Handle, overlapped *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func disconnectNamedPipe(handle syscall.Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func waitNamedPipe(name *uint16, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) { + var _p0 uint32 + if manualReset { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if initialState { + _p1 = 1 + } else { + _p1 = 0 + } + r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(sa)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getOverlappedResult(handle syscall.Handle, overlapped *syscall.Overlapped, transferred *uint32, wait bool) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transferred)), uintptr(_p0), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return +} diff --git a/vendor/gopkg.in/sourcemap.v1/.travis.yml b/vendor/gopkg.in/sourcemap.v1/.travis.yml index 814f0e51a26..229abef3694 100644 --- a/vendor/gopkg.in/sourcemap.v1/.travis.yml +++ b/vendor/gopkg.in/sourcemap.v1/.travis.yml @@ -1,10 +1,14 @@ +sudo: false language: go go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 + - 1.6 + - 1.7 + - tip + +matrix: + allow_failures: + - go: tip install: - mkdir -p $HOME/gopath/src/gopkg.in diff --git a/vendor/gopkg.in/sourcemap.v1/LICENSE b/vendor/gopkg.in/sourcemap.v1/LICENSE new file mode 100644 index 00000000000..405d20f9c66 --- /dev/null +++ b/vendor/gopkg.in/sourcemap.v1/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2016 The github.com/go-sourcemap/sourcemap Contributors. +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. + +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/gopkg.in/sourcemap.v1/Makefile b/vendor/gopkg.in/sourcemap.v1/Makefile index 08381f92873..161c4fd0fdd 100644 --- a/vendor/gopkg.in/sourcemap.v1/Makefile +++ b/vendor/gopkg.in/sourcemap.v1/Makefile @@ -1,3 +1,4 @@ all: - go test ./... -test.v -test.cpu=1,2,4 - go test ./... -test.v -test.short -test.race + go test ./... + go test ./... -short -race + go vet diff --git a/vendor/gopkg.in/sourcemap.v1/README.md b/vendor/gopkg.in/sourcemap.v1/README.md index 791938e046b..fb319d20f4d 100644 --- a/vendor/gopkg.in/sourcemap.v1/README.md +++ b/vendor/gopkg.in/sourcemap.v1/README.md @@ -1,4 +1,4 @@ -# Source Maps consumer for Golang [![Build Status](https://travis-ci.org/go-sourcemap/sourcemap.svg)](https://travis-ci.org/go-sourcemap/sourcemap) +# Source Maps consumer for Golang [![Build Status](https://travis-ci.org/go-sourcemap/sourcemap.svg?branch=v1)](https://travis-ci.org/go-sourcemap/sourcemap) ## Installation diff --git a/vendor/gopkg.in/sourcemap.v1/base64vlq/base64_vlq.go b/vendor/gopkg.in/sourcemap.v1/base64vlq/base64_vlq.go index 598b404608f..16cbfb56f09 100644 --- a/vendor/gopkg.in/sourcemap.v1/base64vlq/base64_vlq.go +++ b/vendor/gopkg.in/sourcemap.v1/base64vlq/base64_vlq.go @@ -14,22 +14,19 @@ const ( vlqContinuationBit = vlqBase ) -var ( - decodeMap [256]int -) +var decodeMap [256]byte func init() { for i := 0; i < len(encodeStd); i++ { - decodeMap[encodeStd[i]] = i + decodeMap[encodeStd[i]] = byte(i) } } func toVLQSigned(n int) int { if n < 0 { return -n<<1 + 1 - } else { - return n << 1 } + return n << 1 } func fromVLQSigned(n int) int { @@ -51,7 +48,7 @@ func NewEncoder(w io.ByteWriter) *Encoder { } } -func (enc *Encoder) Encode(n int) error { +func (enc Encoder) Encode(n int) error { n = toVLQSigned(n) for digit := vlqContinuationBit; digit&vlqContinuationBit != 0; { digit = n & vlqBaseMask @@ -59,6 +56,7 @@ func (enc *Encoder) Encode(n int) error { if n > 0 { digit |= vlqContinuationBit } + err := enc.w.WriteByte(encodeStd[digit]) if err != nil { return err @@ -77,7 +75,7 @@ func NewDecoder(r io.ByteReader) *Decoder { } } -func (dec *Decoder) Decode() (n int, err error) { +func (dec Decoder) Decode() (n int, err error) { shift := uint(0) for continuation := true; continuation; { c, err := dec.r.ReadByte() @@ -85,10 +83,9 @@ func (dec *Decoder) Decode() (n int, err error) { return 0, err } - digit := decodeMap[c] - continuation = digit&vlqContinuationBit != 0 - digit &= vlqBaseMask - n = n + digit< genCol && i > 0 { + if match.genLine > genLine || match.genCol > genCol { + if i == 0 { + return + } match = &c.mappings[i-1] } @@ -94,14 +95,14 @@ func (c *Consumer) Source(genLine, genCol int) (source, name string, line, col i source = c.absSource(c.smap.Sources[match.sourcesInd]) } if match.namesInd >= 0 { - iv := c.smap.Names[match.namesInd] - switch v := iv.(type) { + v := c.smap.Names[match.namesInd] + switch v := v.(type) { case string: name = v case float64: name = strconv.FormatFloat(v, 'f', -1, 64) default: - name = fmt.Sprint(iv) + name = fmt.Sprint(v) } } line = match.sourceLine @@ -131,182 +132,3 @@ func (c *Consumer) absSource(source string) string { return source } - -func (c *Consumer) SourceName(genLine, genCol int, genName string) (name string, ok bool) { - ind := sort.Search(len(c.mappings), func(i int) bool { - m := c.mappings[i] - if m.genLine == genLine { - return m.genCol >= genCol - } - return m.genLine >= genLine - }) - - // Mapping not found. - if ind == len(c.mappings) { - return "", false - } - - for i := ind; i >= 0; i-- { - m := c.mappings[i] - if m.namesInd == -1 { - continue - } - if c.smap.Names[m.namesInd] == "" { - - } - } - - return -} - -type fn func() (fn, error) - -type sourceMap struct { - Version int `json:"version"` - File string `json:"file"` - SourceRoot string `json:"sourceRoot"` - Sources []string `json:"sources"` - Names []interface{} `json:"names"` - Mappings string `json:"mappings"` -} - -type mapping struct { - genLine int - genCol int - sourcesInd int - sourceLine int - sourceCol int - namesInd int -} - -type mappings struct { - rd *strings.Reader - dec *base64vlq.Decoder - - genLine int - genCol int - sourcesInd int - sourceLine int - sourceCol int - namesInd int - - value mapping - values []mapping -} - -func parseMappings(s string) ([]mapping, error) { - rd := strings.NewReader(s) - m := &mappings{ - rd: rd, - dec: base64vlq.NewDecoder(rd), - - genLine: 1, - sourceLine: 1, - } - m.zeroValue() - err := m.parse() - if err != nil { - return nil, err - } - return m.values, nil -} - -func (m *mappings) parse() error { - next := m.parseGenCol - for { - c, err := m.rd.ReadByte() - if err == io.EOF { - m.pushValue() - return nil - } else if err != nil { - return err - } - - switch c { - case ',': - m.pushValue() - next = m.parseGenCol - case ';': - m.pushValue() - - m.genLine++ - m.genCol = 0 - - next = m.parseGenCol - default: - m.rd.UnreadByte() - - var err error - next, err = next() - if err != nil { - return err - } - } - } -} - -func (m *mappings) parseGenCol() (fn, error) { - n, err := m.dec.Decode() - if err != nil { - return nil, err - } - m.genCol += n - m.value.genCol = m.genCol - return m.parseSourcesInd, nil -} - -func (m *mappings) parseSourcesInd() (fn, error) { - n, err := m.dec.Decode() - if err != nil { - return nil, err - } - m.sourcesInd += n - m.value.sourcesInd = m.sourcesInd - return m.parseSourceLine, nil -} - -func (m *mappings) parseSourceLine() (fn, error) { - n, err := m.dec.Decode() - if err != nil { - return nil, err - } - m.sourceLine += n - m.value.sourceLine = m.sourceLine - return m.parseSourceCol, nil -} - -func (m *mappings) parseSourceCol() (fn, error) { - n, err := m.dec.Decode() - if err != nil { - return nil, err - } - m.sourceCol += n - m.value.sourceCol = m.sourceCol - return m.parseNamesInd, nil -} - -func (m *mappings) parseNamesInd() (fn, error) { - n, err := m.dec.Decode() - if err != nil { - return nil, err - } - m.namesInd += n - m.value.namesInd = m.namesInd - return m.parseGenCol, nil -} - -func (m *mappings) zeroValue() { - m.value = mapping{ - genLine: m.genLine, - genCol: 0, - sourcesInd: -1, - sourceLine: 0, - sourceCol: 0, - namesInd: -1, - } -} - -func (m *mappings) pushValue() { - m.values = append(m.values, m.value) - m.zeroValue() -} diff --git a/vendor/gopkg.in/sourcemap.v1/consumer_test.go b/vendor/gopkg.in/sourcemap.v1/consumer_test.go deleted file mode 100644 index 4ac660a36fa..00000000000 --- a/vendor/gopkg.in/sourcemap.v1/consumer_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package sourcemap_test - -import ( - "io/ioutil" - "net/http" - "strings" - "testing" - - "gopkg.in/sourcemap.v1" -) - -const ( - jqSourceMapURL = "http://code.jquery.com/jquery-2.0.3.min.map" -) - -var ( - jqSourceMapBytes []byte -) - -func init() { - resp, err := http.Get(jqSourceMapURL) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - panic(err) - } - jqSourceMapBytes = b -} - -type sourceMapTest struct { - genLine int - genCol int - wantedSource string - wantedName string - wantedLine int - wantedCol int -} - -func (test *sourceMapTest) assert(t *testing.T, smap *sourcemap.Consumer) { - source, name, line, col, ok := smap.Source(test.genLine, test.genCol) - if !ok { - t.Fatalf("Source not found for %d, %d", test.genLine, test.genCol) - } - if source != test.wantedSource { - t.Fatalf("got %q, wanted %q", source, test.wantedSource) - } - if name != test.wantedName { - t.Fatalf("got %q, wanted %q", name, test.wantedName) - } - if line != test.wantedLine { - t.Fatalf("got %q, wanted %q", line, test.wantedLine) - } - if col != test.wantedCol { - t.Fatalf("got %q, wanted %q", col, test.wantedCol) - } -} - -func TestSourceMap(t *testing.T) { - smap, err := sourcemap.Parse("", []byte(sourceMapJSON)) - if err != nil { - t.Fatal(err) - } - - tests := []*sourceMapTest{ - {1, 1, "/the/root/one.js", "", 1, 1}, - {1, 5, "/the/root/one.js", "", 1, 5}, - {1, 9, "/the/root/one.js", "", 1, 11}, - {1, 18, "/the/root/one.js", "bar", 1, 21}, - {1, 21, "/the/root/one.js", "", 2, 3}, - {1, 28, "/the/root/one.js", "baz", 2, 10}, - {1, 32, "/the/root/one.js", "bar", 2, 14}, - - {2, 1, "/the/root/two.js", "", 1, 1}, - {2, 5, "/the/root/two.js", "", 1, 5}, - {2, 9, "/the/root/two.js", "", 1, 11}, - {2, 18, "/the/root/two.js", "n", 1, 21}, - {2, 21, "/the/root/two.js", "", 2, 3}, - {2, 28, "/the/root/two.js", "n", 2, 10}, - - // Fuzzy match. - {1, 20, "/the/root/one.js", "bar", 1, 21}, - {1, 30, "/the/root/one.js", "baz", 2, 10}, - {2, 12, "/the/root/two.js", "", 1, 11}, - } - for _, test := range tests { - test.assert(t, smap) - } - - _, _, _, _, ok := smap.Source(3, 0) - if ok { - t.Fatal() - } -} - -func TestSourceRootURL(t *testing.T) { - jsonStr := sourceMapJSON - jsonStr = strings.Replace(jsonStr, "/the/root", "http://the/root", 1) - jsonStr = strings.Replace(jsonStr, "one.js", "../one.js", 1) - - smap, err := sourcemap.Parse("", []byte(jsonStr)) - if err != nil { - t.Fatal(err) - } - - tests := []*sourceMapTest{ - {1, 1, "http://the/one.js", "", 1, 1}, - {2, 1, "http://the/root/two.js", "", 1, 1}, - } - for _, test := range tests { - test.assert(t, smap) - } -} - -func TestEmptySourceRootURL(t *testing.T) { - jsonStr := sourceMapJSON - jsonStr = strings.Replace(jsonStr, "/the/root", "", 1) - jsonStr = strings.Replace(jsonStr, "one.js", "../one.js", 1) - - smap, err := sourcemap.Parse("http://the/root/app.min.map", []byte(jsonStr)) - if err != nil { - t.Fatal(err) - } - - tests := []*sourceMapTest{ - {1, 1, "http://the/one.js", "", 1, 1}, - {2, 1, "http://the/root/two.js", "", 1, 1}, - } - for _, test := range tests { - test.assert(t, smap) - } -} - -func TestAbsSourceURL(t *testing.T) { - jsonStr := sourceMapJSON - jsonStr = strings.Replace(jsonStr, "/the/root", "", 1) - jsonStr = strings.Replace(jsonStr, "one.js", "http://the/root/one.js", 1) - jsonStr = strings.Replace(jsonStr, "two.js", "/another/root/two.js", 1) - - testAbsSourceURL(t, "", jsonStr) - testAbsSourceURL(t, "http://path/to/map", jsonStr) -} - -func testAbsSourceURL(t *testing.T, mapURL, jsonStr string) { - smap, err := sourcemap.Parse(mapURL, []byte(jsonStr)) - if err != nil { - t.Fatal(err) - } - - tests := []*sourceMapTest{ - {1, 1, "http://the/root/one.js", "", 1, 1}, - {2, 1, "/another/root/two.js", "", 1, 1}, - } - for _, test := range tests { - test.assert(t, smap) - } -} - -func TestJQuerySourceMap(t *testing.T) { - smap, err := sourcemap.Parse(jqSourceMapURL, jqSourceMapBytes) - if err != nil { - t.Fatal(err) - } - - tests := []*sourceMapTest{ - {5, 6789, "http://code.jquery.com/jquery-2.0.3.js", "apply", 4360, 27}, - {5, 10006, "http://code.jquery.com/jquery-2.0.3.js", "apply", 4676, 8}, - {4, 553, "http://code.jquery.com/jquery-2.0.3.js", "ready", 93, 9}, - } - for _, test := range tests { - test.assert(t, smap) - } -} - -func BenchmarkParse(b *testing.B) { - for i := 0; i < b.N; i++ { - _, err := sourcemap.Parse(jqSourceMapURL, jqSourceMapBytes) - if err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkSource(b *testing.B) { - smap, err := sourcemap.Parse(jqSourceMapURL, jqSourceMapBytes) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - - for i := 0; i < b.N; i++ { - for j := 0; j < 10; j++ { - smap.Source(j, 100*j) - } - } -} - -// This is a test mapping which maps functions from two different files -// (one.js and two.js) to a minified generated source. -// -// Here is one.js: -// -// ONE.foo = function (bar) { -// return baz(bar); -// }; -// -// Here is two.js: -// -// TWO.inc = function (n) { -// return n + 1; -// }; -// -// And here is the generated code (min.js): -// -// ONE.foo=function(a){return baz(a);}; -// TWO.inc=function(a){return a+1;}; - -var genCode = `exports.testGeneratedCode = "ONE.foo=function(a){return baz(a);}; -TWO.inc=function(a){return a+1;};` - -var sourceMapJSON = `{ - "version": 3, - "file": "min.js", - "names": ["bar", "baz", "n"], - "sources": ["one.js", "two.js"], - "sourceRoot": "/the/root", - "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA" -}` diff --git a/vendor/gopkg.in/sourcemap.v1/example_test.go b/vendor/gopkg.in/sourcemap.v1/example_test.go deleted file mode 100644 index ffac4143334..00000000000 --- a/vendor/gopkg.in/sourcemap.v1/example_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package sourcemap_test - -import ( - "fmt" - "io/ioutil" - "net/http" - - "gopkg.in/sourcemap.v1" -) - -func ExampleParse() { - mapURL := "http://code.jquery.com/jquery-2.0.3.min.map" - resp, err := http.Get(mapURL) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - panic(err) - } - - smap, err := sourcemap.Parse(mapURL, b) - if err != nil { - panic(err) - } - - line, column := 5, 6789 - file, fn, line, col, ok := smap.Source(line, column) - fmt.Println(file, fn, line, col, ok) - // Output: http://code.jquery.com/jquery-2.0.3.js apply 4360 27 true -} diff --git a/vendor/gopkg.in/sourcemap.v1/sourcemap.go b/vendor/gopkg.in/sourcemap.v1/sourcemap.go new file mode 100644 index 00000000000..0e9af1a2563 --- /dev/null +++ b/vendor/gopkg.in/sourcemap.v1/sourcemap.go @@ -0,0 +1,157 @@ +package sourcemap // import "gopkg.in/sourcemap.v1" + +import ( + "io" + "strings" + + "gopkg.in/sourcemap.v1/base64vlq" +) + +type fn func(m *mappings) (fn, error) + +type sourceMap struct { + Version int `json:"version"` + File string `json:"file"` + SourceRoot string `json:"sourceRoot"` + Sources []string `json:"sources"` + Names []interface{} `json:"names"` + Mappings string `json:"mappings"` +} + +type mapping struct { + genLine int + genCol int + sourcesInd int + sourceLine int + sourceCol int + namesInd int +} + +type mappings struct { + rd *strings.Reader + dec *base64vlq.Decoder + + hasName bool + value mapping + + values []mapping +} + +func parseMappings(s string) ([]mapping, error) { + rd := strings.NewReader(s) + m := &mappings{ + rd: rd, + dec: base64vlq.NewDecoder(rd), + } + m.value.genLine = 1 + m.value.sourceLine = 1 + + err := m.parse() + if err != nil { + return nil, err + } + return m.values, nil +} + +func (m *mappings) parse() error { + next := parseGenCol + for { + c, err := m.rd.ReadByte() + if err == io.EOF { + m.pushValue() + return nil + } + if err != nil { + return err + } + + switch c { + case ',': + m.pushValue() + next = parseGenCol + case ';': + m.pushValue() + + m.value.genLine++ + m.value.genCol = 0 + + next = parseGenCol + default: + err := m.rd.UnreadByte() + if err != nil { + return err + } + + next, err = next(m) + if err != nil { + return err + } + } + } +} + +func parseGenCol(m *mappings) (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.value.genCol += n + return parseSourcesInd, nil +} + +func parseSourcesInd(m *mappings) (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.value.sourcesInd += n + return parseSourceLine, nil +} + +func parseSourceLine(m *mappings) (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.value.sourceLine += n + return parseSourceCol, nil +} + +func parseSourceCol(m *mappings) (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.value.sourceCol += n + return parseNamesInd, nil +} + +func parseNamesInd(m *mappings) (fn, error) { + n, err := m.dec.Decode() + if err != nil { + return nil, err + } + m.hasName = true + m.value.namesInd += n + return parseGenCol, nil +} + +func (m *mappings) pushValue() { + if m.value.sourceLine == 1 && m.value.sourceCol == 0 { + return + } + + if m.hasName { + m.values = append(m.values, m.value) + m.hasName = false + } else { + m.values = append(m.values, mapping{ + genLine: m.value.genLine, + genCol: m.value.genCol, + sourcesInd: m.value.sourcesInd, + sourceLine: m.value.sourceLine, + sourceCol: m.value.sourceCol, + namesInd: -1, + }) + } +} diff --git a/vendor/gopkg.in/urfave/cli.v1/.flake8 b/vendor/gopkg.in/urfave/cli.v1/.flake8 new file mode 100644 index 00000000000..6deafc26170 --- /dev/null +++ b/vendor/gopkg.in/urfave/cli.v1/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/vendor/gopkg.in/urfave/cli.v1/.travis.yml b/vendor/gopkg.in/urfave/cli.v1/.travis.yml index 273d017b46f..cf8d0980dca 100644 --- a/vendor/gopkg.in/urfave/cli.v1/.travis.yml +++ b/vendor/gopkg.in/urfave/cli.v1/.travis.yml @@ -1,40 +1,27 @@ language: go - sudo: false +dist: trusty +osx_image: xcode8.3 +go: 1.8.x + +os: +- linux +- osx cache: directories: - node_modules -go: -- 1.2.2 -- 1.3.3 -- 1.4 -- 1.5.4 -- 1.6.2 -- master - -matrix: - allow_failures: - - go: master - include: - - go: 1.6.2 - os: osx - - go: 1.1.2 - install: go get -v . - before_script: echo skipping gfmxr on $TRAVIS_GO_VERSION - script: - - ./runtests vet - - ./runtests test - before_script: -- go get github.com/urfave/gfmxr/... +- go get github.com/urfave/gfmrun/... || true +- go get golang.org/x/tools/cmd/goimports - if [ ! -f node_modules/.bin/markdown-toc ] ; then npm install markdown-toc ; fi script: +- ./runtests gen - ./runtests vet - ./runtests test -- ./runtests gfmxr +- ./runtests gfmrun - ./runtests toc diff --git a/vendor/gopkg.in/urfave/cli.v1/CHANGELOG.md b/vendor/gopkg.in/urfave/cli.v1/CHANGELOG.md index d1904fe0b96..401eae5a2cc 100644 --- a/vendor/gopkg.in/urfave/cli.v1/CHANGELOG.md +++ b/vendor/gopkg.in/urfave/cli.v1/CHANGELOG.md @@ -4,6 +4,104 @@ ## [Unreleased] +## 1.20.0 - 2017-08-10 + +### Fixed + +* `HandleExitCoder` is now correctly iterates over all errors in + a `MultiError`. The exit code is the exit code of the last error or `1` if + there are no `ExitCoder`s in the `MultiError`. +* Fixed YAML file loading on Windows (previously would fail validate the file path) +* Subcommand `Usage`, `Description`, `ArgsUsage`, `OnUsageError` correctly + propogated +* `ErrWriter` is now passed downwards through command structure to avoid the + need to redefine it +* Pass `Command` context into `OnUsageError` rather than parent context so that + all fields are avaiable +* Errors occuring in `Before` funcs are no longer double printed +* Use `UsageText` in the help templates for commands and subcommands if + defined; otherwise build the usage as before (was previously ignoring this + field) +* `IsSet` and `GlobalIsSet` now correctly return whether a flag is set if + a program calls `Set` or `GlobalSet` directly after flag parsing (would + previously only return `true` if the flag was set during parsing) + +### Changed + +* No longer exit the program on command/subcommand error if the error raised is + not an `OsExiter`. This exiting behavior was introduced in 1.19.0, but was + determined to be a regression in functionality. See [the + PR](https://github.com/urfave/cli/pull/595) for discussion. + +### Added + +* `CommandsByName` type was added to make it easy to sort `Command`s by name, + alphabetically +* `altsrc` now handles loading of string and int arrays from TOML +* Support for definition of custom help templates for `App` via + `CustomAppHelpTemplate` +* Support for arbitrary key/value fields on `App` to be used with + `CustomAppHelpTemplate` via `ExtraInfo` +* `HelpFlag`, `VersionFlag`, and `BashCompletionFlag` changed to explictly be + `cli.Flag`s allowing for the use of custom flags satisfying the `cli.Flag` + interface to be used. + + +## [1.19.1] - 2016-11-21 + +### Fixed + +- Fixes regression introduced in 1.19.0 where using an `ActionFunc` as + the `Action` for a command would cause it to error rather than calling the + function. Should not have a affected declarative cases using `func(c + *cli.Context) err)`. +- Shell completion now handles the case where the user specifies + `--generate-bash-completion` immediately after a flag that takes an argument. + Previously it call the application with `--generate-bash-completion` as the + flag value. + +## [1.19.0] - 2016-11-19 +### Added +- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`) +- A `Description` field was added to `App` for a more detailed description of + the application (similar to the existing `Description` field on `Command`) +- Flag type code generation via `go generate` +- Write to stderr and exit 1 if action returns non-nil error +- Added support for TOML to the `altsrc` loader +- `SkipArgReorder` was added to allow users to skip the argument reordering. + This is useful if you want to consider all "flags" after an argument as + arguments rather than flags (the default behavior of the stdlib `flag` + library). This is backported functionality from the [removal of the flag + reordering](https://github.com/urfave/cli/pull/398) in the unreleased version + 2 +- For formatted errors (those implementing `ErrorFormatter`), the errors will + be formatted during output. Compatible with `pkg/errors`. + +### Changed +- Raise minimum tested/supported Go version to 1.2+ + +### Fixed +- Consider empty environment variables as set (previously environment variables + with the equivalent of `""` would be skipped rather than their value used). +- Return an error if the value in a given environment variable cannot be parsed + as the flag type. Previously these errors were silently swallowed. +- Print full error when an invalid flag is specified (which includes the invalid flag) +- `App.Writer` defaults to `stdout` when `nil` +- If no action is specified on a command or app, the help is now printed instead of `panic`ing +- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized) +- Correctly show help message if `-h` is provided to a subcommand +- `context.(Global)IsSet` now respects environment variables. Previously it + would return `false` if a flag was specified in the environment rather than + as an argument +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user +- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This + fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well + as `altsrc` where Go would complain that the types didn't match + +## [1.18.1] - 2016-08-28 +### Fixed +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported) + ## [1.18.0] - 2016-06-27 ### Added - `./runtests` test runner with coverage tracking by default @@ -22,6 +120,10 @@ - No longer swallows `panic`s that occur within the `Action`s themselves when detecting the signature of the `Action` field +## [1.17.1] - 2016-08-28 +### Fixed +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user + ## [1.17.0] - 2016-05-09 ### Added - Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc` @@ -43,6 +145,10 @@ - cleanups based on [Go Report Card feedback](https://goreportcard.com/report/github.com/urfave/cli) +## [1.16.1] - 2016-08-28 +### Fixed +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user + ## [1.16.0] - 2016-05-02 ### Added - `Hidden` field on all flag struct types to omit from generated help text diff --git a/vendor/gopkg.in/urfave/cli.v1/README.md b/vendor/gopkg.in/urfave/cli.v1/README.md index ebb1d741387..2bbbd8ea972 100644 --- a/vendor/gopkg.in/urfave/cli.v1/README.md +++ b/vendor/gopkg.in/urfave/cli.v1/README.md @@ -23,15 +23,16 @@ applications in an expressive way. - [Installation](#installation) * [Supported platforms](#supported-platforms) * [Using the `v2` branch](#using-the-v2-branch) - * [Pinning to the `v1` branch](#pinning-to-the-v1-branch) + * [Pinning to the `v1` releases](#pinning-to-the-v1-releases) - [Getting Started](#getting-started) - [Examples](#examples) * [Arguments](#arguments) * [Flags](#flags) + [Placeholder Values](#placeholder-values) + [Alternate Names](#alternate-names) + + [Ordering](#ordering) + [Values from the Environment](#values-from-the-environment) - + [Values from alternate input sources (YAML and others)](#values-from-alternate-input-sources-yaml-and-others) + + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others) * [Subcommands](#subcommands) * [Subcommands categories](#subcommands-categories) * [Exit code](#exit-code) @@ -60,18 +61,16 @@ organized, and expressive! ## Installation -Make sure you have a working Go environment. Go version 1.1+ is required for -core cli, whereas use of the [`./altsrc`](./altsrc) input extensions requires Go -version 1.2+. [See the install -instructions](http://golang.org/doc/install.html). +Make sure you have a working Go environment. Go version 1.2+ is supported. [See +the install instructions for Go](http://golang.org/doc/install.html). To install cli, simply run: ``` $ go get github.com/urfave/cli ``` -Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands -can be easily used: +Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can +be easily used: ``` export PATH=$PATH:$GOPATH/bin ``` @@ -106,11 +105,11 @@ import ( ... ``` -### Pinning to the `v1` branch +### Pinning to the `v1` releases Similarly to the section above describing use of the `v2` branch, if one wants to avoid any unexpected compatibility pains once `v2` becomes `master`, then -pinning to the `v1` branch is an acceptable option, e.g.: +pinning to `v1` is an acceptable option, e.g.: ``` $ go get gopkg.in/urfave/cli.v1 @@ -124,6 +123,8 @@ import ( ... ``` +This will pull the latest tagged `v1` release (e.g. `v1.18.1` at the time of writing). + ## Getting Started One of the philosophies behind cli is that an API should be playful and full of @@ -450,6 +451,76 @@ That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error. +#### Ordering + +Flags for the application and commands are shown in the order they are defined. +However, it's possible to sort them from outside this library by using `FlagsByName` +or `CommandsByName` with `sort`. + +For example this: + + +``` go +package main + +import ( + "os" + "sort" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "Language for the greeting", + }, + cli.StringFlag{ + Name: "config, c", + Usage: "Load configuration from `FILE`", + }, + } + + app.Commands = []cli.Command{ + { + Name: "complete", + Aliases: []string{"c"}, + Usage: "complete a task on the list", + Action: func(c *cli.Context) error { + return nil + }, + }, + { + Name: "add", + Aliases: []string{"a"}, + Usage: "add a task to the list", + Action: func(c *cli.Context) error { + return nil + }, + }, + } + + sort.Sort(cli.FlagsByName(app.Flags)) + sort.Sort(cli.CommandsByName(app.Commands)) + + app.Run(os.Args) +} +``` + +Will result in help output like: + +``` +--config FILE, -c FILE Load configuration from FILE +--lang value, -l value Language for the greeting (default: "english") +``` + #### Values from the Environment You can also have the default value set from the environment via `EnvVar`. e.g. @@ -515,10 +586,14 @@ func main() { } ``` -#### Values from alternate input sources (YAML and others) +#### Values from alternate input sources (YAML, TOML, and others) There is a separate package altsrc that adds support for getting flag values -from other input sources like YAML. +from other file input sources. + +Currently supported input source formats: +* YAML +* TOML In order to get values for a flag from an alternate input source the following code would be added to wrap an existing cli.Flag like below: @@ -540,9 +615,9 @@ the yaml input source for any flags that are defined on that command. As a note the "load" flag used would also have to be defined on the command flags in order for this code snipped to work. -Currently only YAML files are supported but developers can add support for other -input sources by implementing the altsrc.InputSourceContext for their given -sources. +Currently only the aboved specified formats are supported but developers can +add support for other input sources by implementing the +altsrc.InputSourceContext for their given sources. Here is a more complete sample of a command using YAML support: @@ -845,7 +920,7 @@ func main() { ### Generated Help Text -The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked +The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked by the cli internals in order to print generated help text for the app, command, or subcommand, and break execution. @@ -885,16 +960,13 @@ SUPPORT: support@awesometown.example.com cli.AppHelpTemplate = `NAME: {{.Name}} - {{.Usage}} USAGE: - {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command -[command options]{{end}} {{if -.ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} + {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} {{if len .Authors}} -AUTHOR(S): +AUTHOR: {{range .Authors}}{{ . }}{{end}} {{end}}{{if .Commands}} COMMANDS: -{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t" -}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}} GLOBAL OPTIONS: {{range .VisibleFlags}}{{.}} {{end}}{{end}}{{if .Copyright }} @@ -950,12 +1022,12 @@ is checked by the cli internals in order to print the `App.Version` via #### Customization -The default flag may be cusomized to something other than `-v/--version` by +The default flag may be customized to something other than `-v/--version` by setting `cli.VersionFlag`, e.g.: ``` go package main @@ -974,7 +1046,7 @@ func main() { app := cli.NewApp() app.Name = "partay" - app.Version = "v19.99.0" + app.Version = "19.99.0" app.Run(os.Args) } ``` @@ -983,7 +1055,7 @@ Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e. ``` go package main @@ -1006,7 +1078,7 @@ func main() { app := cli.NewApp() app.Name = "partay" - app.Version = "v19.99.0" + app.Version = "19.99.0" app.Run(os.Args) } ``` @@ -1085,7 +1157,7 @@ func (g *genericType) String() string { func main() { app := cli.NewApp() app.Name = "kənˈtrīv" - app.Version = "v19.99.0" + app.Version = "19.99.0" app.Compiled = time.Now() app.Authors = []cli.Author{ cli.Author{ diff --git a/vendor/gopkg.in/urfave/cli.v1/app.go b/vendor/gopkg.in/urfave/cli.v1/app.go index a046c0128d7..51fc45d8781 100644 --- a/vendor/gopkg.in/urfave/cli.v1/app.go +++ b/vendor/gopkg.in/urfave/cli.v1/app.go @@ -6,9 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" - "reflect" "sort" - "strings" "time" ) @@ -19,11 +17,8 @@ var ( contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." - errNonFuncAction = NewExitError("ERROR invalid Action type. "+ - fmt.Sprintf("Must be a func of type `cli.ActionFunc`. %s", contactSysadmin)+ - fmt.Sprintf("See %s", appActionDeprecationURL), 2) - errInvalidActionSignature = NewExitError("ERROR invalid Action signature. "+ - fmt.Sprintf("Must be `cli.ActionFunc`. %s", contactSysadmin)+ + errInvalidActionType = NewExitError("ERROR invalid Action type. "+ + fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ fmt.Sprintf("See %s", appActionDeprecationURL), 2) ) @@ -42,6 +37,8 @@ type App struct { ArgsUsage string // Version of the program Version string + // Description of the program + Description string // List of commands to execute Commands []Command // List of flags to parse @@ -62,10 +59,11 @@ type App struct { // An action to execute after any subcommands are run, but after the subcommand has finished // It is run even if Action() panics After AfterFunc + // The action to execute when no subcommands are specified + // Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}` + // *Note*: support for the deprecated `Action` signature will be removed in a future version Action interface{} - // TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind - // of deprecation period has passed, maybe? // Execute this function if the proper command cannot be found CommandNotFound CommandNotFoundFunc @@ -87,6 +85,12 @@ type App struct { ErrWriter io.Writer // Other custom info Metadata map[string]interface{} + // Carries a function which returns app specific info. + ExtraInfo func() map[string]string + // CustomAppHelpTemplate the text template for app help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomAppHelpTemplate string didSetup bool } @@ -147,10 +151,6 @@ func (a *App) Setup() { } } - if a.EnableBashCompletion { - a.appendFlag(BashCompletionFlag) - } - if !a.HideVersion { a.appendFlag(VersionFlag) } @@ -160,6 +160,14 @@ func (a *App) Setup() { a.categories = a.categories.AddCommand(command.Category, command) } sort.Sort(a.categories) + + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) + } + + if a.Writer == nil { + a.Writer = os.Stdout + } } // Run is the entry point to the cli app. Parses the arguments slice and routes @@ -167,8 +175,20 @@ func (a *App) Setup() { func (a *App) Run(arguments []string) (err error) { a.Setup() + // handle the completion flag separately from the flagset since + // completion could be attempted after a flag, but before its value was put + // on the command line. this causes the flagset to interpret the completion + // flag name as the value of the flag before it which is undesirable + // note that we can only do this because the shell autocomplete function + // always appends the completion flag at the end of the command + shellComplete, arguments := checkShellCompleteFlag(a, arguments) + // parse flags - set := flagSet(a.Name, a.Flags) + set, err := flagSet(a.Name, a.Flags) + if err != nil { + return err + } + set.SetOutput(ioutil.Discard) err = set.Parse(arguments[1:]) nerr := normalizeFlags(a.Flags, set) @@ -178,6 +198,7 @@ func (a *App) Run(arguments []string) (err error) { ShowAppHelp(context) return nerr } + context.shellComplete = shellComplete if checkCompletions(context) { return nil @@ -189,7 +210,7 @@ func (a *App) Run(arguments []string) (err error) { HandleExitCoder(err) return err } - fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.") + fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) ShowAppHelp(context) return err } @@ -219,7 +240,6 @@ func (a *App) Run(arguments []string) (err error) { if a.Before != nil { beforeErr := a.Before(context) if beforeErr != nil { - fmt.Fprintf(a.Writer, "%v\n\n", beforeErr) ShowAppHelp(context) HandleExitCoder(beforeErr) err = beforeErr @@ -236,6 +256,10 @@ func (a *App) Run(arguments []string) (err error) { } } + if a.Action == nil { + a.Action = helpCommand.Action + } + // Run default Action err = HandleAction(a.Action, context) @@ -243,11 +267,12 @@ func (a *App) Run(arguments []string) (err error) { return err } -// DEPRECATED: Another entry point to the cli app, takes care of passing arguments and error handling +// RunAndExitOnError calls .Run() and exits non-zero if an error was returned +// +// Deprecated: instead you should return an error that fulfills cli.ExitCoder +// to cli.App.Run. This will cause the application to exit with the given eror +// code in the cli.ExitCoder func (a *App) RunAndExitOnError() { - fmt.Fprintf(a.errWriter(), - "DEPRECATED cli.App.RunAndExitOnError. %s See %s\n", - contactSysadmin, runAndExitOnErrorDeprecationURL) if err := a.Run(os.Args); err != nil { fmt.Fprintln(a.errWriter(), err) OsExiter(1) @@ -276,13 +301,12 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { } a.Commands = newCmds - // append flags - if a.EnableBashCompletion { - a.appendFlag(BashCompletionFlag) + // parse flags + set, err := flagSet(a.Name, a.Flags) + if err != nil { + return err } - // parse flags - set := flagSet(a.Name, a.Flags) set.SetOutput(ioutil.Discard) err = set.Parse(ctx.Args().Tail()) nerr := normalizeFlags(a.Flags, set) @@ -309,7 +333,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) { HandleExitCoder(err) return err } - fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.") + fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) ShowSubcommandHelp(context) return err } @@ -450,50 +474,24 @@ type Author struct { func (a Author) String() string { e := "" if a.Email != "" { - e = "<" + a.Email + "> " + e = " <" + a.Email + ">" } - return fmt.Sprintf("%v %v", a.Name, e) + return fmt.Sprintf("%v%v", a.Name, e) } -// HandleAction uses ✧✧✧reflection✧✧✧ to figure out if the given Action is an -// ActionFunc, a func with the legacy signature for Action, or some other -// invalid thing. If it's an ActionFunc or a func with the legacy signature for -// Action, the func is run! +// HandleAction attempts to figure out which Action signature was used. If +// it's an ActionFunc or a func with the legacy signature for Action, the func +// is run! func HandleAction(action interface{}, context *Context) (err error) { - defer func() { - if r := recover(); r != nil { - // Try to detect a known reflection error from *this scope*, rather than - // swallowing all panics that may happen when calling an Action func. - s := fmt.Sprintf("%v", r) - if strings.HasPrefix(s, "reflect: ") && strings.Contains(s, "too many input arguments") { - err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2) - } else { - panic(r) - } - } - }() - - if reflect.TypeOf(action).Kind() != reflect.Func { - return errNonFuncAction - } - - vals := reflect.ValueOf(action).Call([]reflect.Value{reflect.ValueOf(context)}) - - if len(vals) == 0 { - fmt.Fprintf(ErrWriter, - "DEPRECATED Action signature. Must be `cli.ActionFunc`. %s See %s\n", - contactSysadmin, appActionDeprecationURL) + if a, ok := action.(ActionFunc); ok { + return a(context) + } else if a, ok := action.(func(*Context) error); ok { + return a(context) + } else if a, ok := action.(func(*Context)); ok { // deprecated function signature + a(context) return nil + } else { + return errInvalidActionType } - - if len(vals) > 1 { - return errInvalidActionSignature - } - - if retErr, ok := vals[0].Interface().(error); vals[0].IsValid() && ok { - return retErr - } - - return err } diff --git a/vendor/gopkg.in/urfave/cli.v1/appveyor.yml b/vendor/gopkg.in/urfave/cli.v1/appveyor.yml index 173086e5fc5..1e1489c3651 100644 --- a/vendor/gopkg.in/urfave/cli.v1/appveyor.yml +++ b/vendor/gopkg.in/urfave/cli.v1/appveyor.yml @@ -1,25 +1,26 @@ version: "{build}" -os: Windows Server 2012 R2 +os: Windows Server 2016 + +image: Visual Studio 2017 clone_folder: c:\gopath\src\github.com\urfave\cli environment: GOPATH: C:\gopath - GOVERSION: 1.6 - PYTHON: C:\Python27-x64 - PYTHON_VERSION: 2.7.x + GOVERSION: 1.8.x + PYTHON: C:\Python36-x64 + PYTHON_VERSION: 3.6.x PYTHON_ARCH: 64 - GFMXR_DEBUG: 1 install: - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% - go version - go env -- go get github.com/urfave/gfmxr/... +- go get github.com/urfave/gfmrun/... - go get -v -t ./... build_script: - python runtests vet - python runtests test -- python runtests gfmxr +- python runtests gfmrun diff --git a/vendor/gopkg.in/urfave/cli.v1/cli.go b/vendor/gopkg.in/urfave/cli.v1/cli.go index f0440c563ff..90c07eb8ef9 100644 --- a/vendor/gopkg.in/urfave/cli.v1/cli.go +++ b/vendor/gopkg.in/urfave/cli.v1/cli.go @@ -12,8 +12,11 @@ // app.Usage = "say a greeting" // app.Action = func(c *cli.Context) error { // println("Greetings") +// return nil // } // // app.Run(os.Args) // } package cli + +//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go diff --git a/vendor/gopkg.in/urfave/cli.v1/command.go b/vendor/gopkg.in/urfave/cli.v1/command.go index 8950ccae43c..23de2944bea 100644 --- a/vendor/gopkg.in/urfave/cli.v1/command.go +++ b/vendor/gopkg.in/urfave/cli.v1/command.go @@ -46,6 +46,11 @@ type Command struct { Flags []Flag // Treat all flags as normal arguments if true SkipFlagParsing bool + // Skip argument reordering which attempts to move flags before arguments, + // but only works if all flags appear after all arguments. This behavior was + // removed n version 2 since it only works under specific conditions so we + // backport here by exposing it as an option for compatibility. + SkipArgReorder bool // Boolean to hide built-in help command HideHelp bool // Boolean to hide this command from help or completion @@ -54,6 +59,25 @@ type Command struct { // Full name of command for help, defaults to full command name, including parent commands. HelpName string commandNamePath []string + + // CustomHelpTemplate the text template for the command help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomHelpTemplate string +} + +type CommandsByName []Command + +func (c CommandsByName) Len() int { + return len(c) +} + +func (c CommandsByName) Less(i, j int) bool { + return c[i].Name < c[j].Name +} + +func (c CommandsByName) Swap(i, j int) { + c[i], c[j] = c[j], c[i] } // FullName returns the full name of the command. @@ -82,14 +106,15 @@ func (c Command) Run(ctx *Context) (err error) { ) } - if ctx.App.EnableBashCompletion { - c.Flags = append(c.Flags, BashCompletionFlag) + set, err := flagSet(c.Name, c.Flags) + if err != nil { + return err } - - set := flagSet(c.Name, c.Flags) set.SetOutput(ioutil.Discard) - if !c.SkipFlagParsing { + if c.SkipFlagParsing { + err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...)) + } else if !c.SkipArgReorder { firstFlagIndex := -1 terminatorIndex := -1 for index, arg := range ctx.Args() { @@ -122,21 +147,7 @@ func (c Command) Run(ctx *Context) (err error) { err = set.Parse(ctx.Args().Tail()) } } else { - if c.SkipFlagParsing { - err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...)) - } - } - - if err != nil { - if c.OnUsageError != nil { - err := c.OnUsageError(ctx, err, false) - HandleExitCoder(err) - return err - } - fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.") - fmt.Fprintln(ctx.App.Writer) - ShowCommandHelp(ctx, c.Name) - return err + err = set.Parse(ctx.Args().Tail()) } nerr := normalizeFlags(c.Flags, set) @@ -148,11 +159,23 @@ func (c Command) Run(ctx *Context) (err error) { } context := NewContext(ctx.App, set, ctx) - + context.Command = c if checkCommandCompletions(context, c.Name) { return nil } + if err != nil { + if c.OnUsageError != nil { + err := c.OnUsageError(context, err, false) + HandleExitCoder(err) + return err + } + fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) + fmt.Fprintln(context.App.Writer) + ShowCommandHelp(context, c.Name) + return err + } + if checkCommandHelp(context, c.Name) { return nil } @@ -174,15 +197,16 @@ func (c Command) Run(ctx *Context) (err error) { if c.Before != nil { err = c.Before(context) if err != nil { - fmt.Fprintln(ctx.App.Writer, err) - fmt.Fprintln(ctx.App.Writer) - ShowCommandHelp(ctx, c.Name) + ShowCommandHelp(context, c.Name) HandleExitCoder(err) return err } } - context.Command = c + if c.Action == nil { + c.Action = helpSubcommand.Action + } + err = HandleAction(c.Action, context) if err != nil { @@ -223,14 +247,13 @@ func (c Command) startApp(ctx *Context) error { app.HelpName = app.Name } - if c.Description != "" { - app.Usage = c.Description - } else { - app.Usage = c.Usage - } + app.Usage = c.Usage + app.Description = c.Description + app.ArgsUsage = c.ArgsUsage // set CommandNotFound app.CommandNotFound = ctx.App.CommandNotFound + app.CustomAppHelpTemplate = c.CustomHelpTemplate // set the flags and commands app.Commands = c.Subcommands @@ -243,6 +266,7 @@ func (c Command) startApp(ctx *Context) error { app.Author = ctx.App.Author app.Email = ctx.App.Email app.Writer = ctx.App.Writer + app.ErrWriter = ctx.App.ErrWriter app.categories = CommandCategories{} for _, command := range c.Subcommands { @@ -265,6 +289,7 @@ func (c Command) startApp(ctx *Context) error { } else { app.Action = helpSubcommand.Action } + app.OnUsageError = c.OnUsageError for index, cc := range app.Commands { app.Commands[index].commandNamePath = []string{c.Name, cc.Name} diff --git a/vendor/gopkg.in/urfave/cli.v1/context.go b/vendor/gopkg.in/urfave/cli.v1/context.go index 879bae5ecc5..db94191e2af 100644 --- a/vendor/gopkg.in/urfave/cli.v1/context.go +++ b/vendor/gopkg.in/urfave/cli.v1/context.go @@ -3,9 +3,9 @@ package cli import ( "errors" "flag" - "strconv" + "reflect" "strings" - "time" + "syscall" ) // Context is a type that is passed through to @@ -13,201 +13,23 @@ import ( // can be used to retrieve context-specific Args and // parsed command-line options. type Context struct { - App *App - Command Command - flagSet *flag.FlagSet - setFlags map[string]bool - globalSetFlags map[string]bool - parentContext *Context + App *App + Command Command + shellComplete bool + flagSet *flag.FlagSet + setFlags map[string]bool + parentContext *Context } // NewContext creates a new context. For use in when invoking an App or Command action. func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { - return &Context{App: app, flagSet: set, parentContext: parentCtx} -} - -// Int looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Int(name string) int { - return lookupInt(name, c.flagSet) -} - -// Int64 looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Int64(name string) int64 { - return lookupInt64(name, c.flagSet) -} - -// Uint looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Uint(name string) uint { - return lookupUint(name, c.flagSet) -} - -// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Uint64(name string) uint64 { - return lookupUint64(name, c.flagSet) -} - -// Duration looks up the value of a local time.Duration flag, returns 0 if no -// time.Duration flag exists -func (c *Context) Duration(name string) time.Duration { - return lookupDuration(name, c.flagSet) -} - -// Float64 looks up the value of a local float64 flag, returns 0 if no float64 -// flag exists -func (c *Context) Float64(name string) float64 { - return lookupFloat64(name, c.flagSet) -} - -// Bool looks up the value of a local bool flag, returns false if no bool flag exists -func (c *Context) Bool(name string) bool { - return lookupBool(name, c.flagSet) -} - -// BoolT looks up the value of a local boolT flag, returns false if no bool flag exists -func (c *Context) BoolT(name string) bool { - return lookupBoolT(name, c.flagSet) -} - -// String looks up the value of a local string flag, returns "" if no string flag exists -func (c *Context) String(name string) string { - return lookupString(name, c.flagSet) -} - -// StringSlice looks up the value of a local string slice flag, returns nil if no -// string slice flag exists -func (c *Context) StringSlice(name string) []string { - return lookupStringSlice(name, c.flagSet) -} + c := &Context{App: app, flagSet: set, parentContext: parentCtx} -// IntSlice looks up the value of a local int slice flag, returns nil if no int -// slice flag exists -func (c *Context) IntSlice(name string) []int { - return lookupIntSlice(name, c.flagSet) -} - -// Int64Slice looks up the value of a local int slice flag, returns nil if no int -// slice flag exists -func (c *Context) Int64Slice(name string) []int64 { - return lookupInt64Slice(name, c.flagSet) -} - -// Generic looks up the value of a local generic flag, returns nil if no generic -// flag exists -func (c *Context) Generic(name string) interface{} { - return lookupGeneric(name, c.flagSet) -} - -// GlobalInt looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalInt(name string) int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt(name, fs) + if parentCtx != nil { + c.shellComplete = parentCtx.shellComplete } - return 0 -} -// GlobalInt64 looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalInt64(name string) int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64(name, fs) - } - return 0 -} - -// GlobalUint looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalUint(name string) uint { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint(name, fs) - } - return 0 -} - -// GlobalUint64 looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalUint64(name string) uint64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint64(name, fs) - } - return 0 -} - -// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0) -// if no float64 flag exists -func (c *Context) GlobalFloat64(name string) float64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupFloat64(name, fs) - } - return float64(0) -} - -// GlobalDuration looks up the value of a global time.Duration flag, returns 0 -// if no time.Duration flag exists -func (c *Context) GlobalDuration(name string) time.Duration { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupDuration(name, fs) - } - return 0 -} - -// GlobalBool looks up the value of a global bool flag, returns false if no bool -// flag exists -func (c *Context) GlobalBool(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBool(name, fs) - } - return false -} - -// GlobalBoolT looks up the value of a global bool flag, returns true if no bool -// flag exists -func (c *Context) GlobalBoolT(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBoolT(name, fs) - } - return false -} - -// GlobalString looks up the value of a global string flag, returns "" if no -// string flag exists -func (c *Context) GlobalString(name string) string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupString(name, fs) - } - return "" -} - -// GlobalStringSlice looks up the value of a global string slice flag, returns -// nil if no string slice flag exists -func (c *Context) GlobalStringSlice(name string) []string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupStringSlice(name, fs) - } - return nil -} - -// GlobalIntSlice looks up the value of a global int slice flag, returns nil if -// no int slice flag exists -func (c *Context) GlobalIntSlice(name string) []int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupIntSlice(name, fs) - } - return nil -} - -// GlobalInt64Slice looks up the value of a global int slice flag, returns nil if -// no int slice flag exists -func (c *Context) GlobalInt64Slice(name string) []int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64Slice(name, fs) - } - return nil -} - -// GlobalGeneric looks up the value of a global generic flag, returns nil if no -// generic flag exists -func (c *Context) GlobalGeneric(name string) interface{} { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupGeneric(name, fs) - } - return nil + return c } // NumFlags returns the number of flags set @@ -217,11 +39,13 @@ func (c *Context) NumFlags() int { // Set sets a context flag to a value. func (c *Context) Set(name, value string) error { + c.setFlags = nil return c.flagSet.Set(name, value) } // GlobalSet sets a context flag to a value on the global flagset func (c *Context) GlobalSet(name, value string) error { + globalContext(c).setFlags = nil return globalContext(c).flagSet.Set(name, value) } @@ -229,28 +53,78 @@ func (c *Context) GlobalSet(name, value string) error { func (c *Context) IsSet(name string) bool { if c.setFlags == nil { c.setFlags = make(map[string]bool) + c.flagSet.Visit(func(f *flag.Flag) { c.setFlags[f.Name] = true }) + + c.flagSet.VisitAll(func(f *flag.Flag) { + if _, ok := c.setFlags[f.Name]; ok { + return + } + c.setFlags[f.Name] = false + }) + + // XXX hack to support IsSet for flags with EnvVar + // + // There isn't an easy way to do this with the current implementation since + // whether a flag was set via an environment variable is very difficult to + // determine here. Instead, we intend to introduce a backwards incompatible + // change in version 2 to add `IsSet` to the Flag interface to push the + // responsibility closer to where the information required to determine + // whether a flag is set by non-standard means such as environment + // variables is avaliable. + // + // See https://github.com/urfave/cli/issues/294 for additional discussion + flags := c.Command.Flags + if c.Command.Name == "" { // cannot == Command{} since it contains slice types + if c.App != nil { + flags = c.App.Flags + } + } + for _, f := range flags { + eachName(f.GetName(), func(name string) { + if isSet, ok := c.setFlags[name]; isSet || !ok { + return + } + + val := reflect.ValueOf(f) + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + + envVarValue := val.FieldByName("EnvVar") + if !envVarValue.IsValid() { + return + } + + eachName(envVarValue.String(), func(envVar string) { + envVar = strings.TrimSpace(envVar) + if _, ok := syscall.Getenv(envVar); ok { + c.setFlags[name] = true + return + } + }) + }) + } } - return c.setFlags[name] == true + + return c.setFlags[name] } // GlobalIsSet determines if the global flag was actually set func (c *Context) GlobalIsSet(name string) bool { - if c.globalSetFlags == nil { - c.globalSetFlags = make(map[string]bool) - ctx := c - if ctx.parentContext != nil { - ctx = ctx.parentContext - } - for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext { - ctx.flagSet.Visit(func(f *flag.Flag) { - c.globalSetFlags[f.Name] = true - }) + ctx := c + if ctx.parentContext != nil { + ctx = ctx.parentContext + } + + for ; ctx != nil; ctx = ctx.parentContext { + if ctx.IsSet(name) { + return true } } - return c.globalSetFlags[name] + return false } // FlagNames returns a slice of flag names used in this context. @@ -282,6 +156,11 @@ func (c *Context) Parent() *Context { return c.parentContext } +// value returns the value of the flag coressponding to `name` +func (c *Context) value(name string) interface{} { + return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +} + // Args contains apps console arguments type Args []string @@ -357,156 +236,6 @@ func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet { return nil } -func lookupInt(name string, set *flag.FlagSet) int { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return int(val) - } - - return 0 -} - -func lookupInt64(name string, set *flag.FlagSet) int64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupUint(name string, set *flag.FlagSet) uint { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return uint(val) - } - - return 0 -} - -func lookupUint64(name string, set *flag.FlagSet) uint64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupDuration(name string, set *flag.FlagSet) time.Duration { - f := set.Lookup(name) - if f != nil { - val, err := time.ParseDuration(f.Value.String()) - if err == nil { - return val - } - } - - return 0 -} - -func lookupFloat64(name string, set *flag.FlagSet) float64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseFloat(f.Value.String(), 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupString(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - return f.Value.String() - } - - return "" -} - -func lookupStringSlice(name string, set *flag.FlagSet) []string { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*StringSlice)).Value() - - } - - return nil -} - -func lookupIntSlice(name string, set *flag.FlagSet) []int { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*IntSlice)).Value() - - } - - return nil -} - -func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*Int64Slice)).Value() - - } - - return nil -} - -func lookupGeneric(name string, set *flag.FlagSet) interface{} { - f := set.Lookup(name) - if f != nil { - return f.Value - } - return nil -} - -func lookupBool(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return val - } - - return false -} - -func lookupBoolT(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return true - } - return val - } - - return false -} - func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { switch ff.Value.(type) { case *StringSlice: diff --git a/vendor/gopkg.in/urfave/cli.v1/errors.go b/vendor/gopkg.in/urfave/cli.v1/errors.go index ea551be16ac..562b2953cf2 100644 --- a/vendor/gopkg.in/urfave/cli.v1/errors.go +++ b/vendor/gopkg.in/urfave/cli.v1/errors.go @@ -24,7 +24,7 @@ func NewMultiError(err ...error) MultiError { return MultiError{Errors: err} } -// Error implents the error interface. +// Error implements the error interface. func (m MultiError) Error() string { errs := make([]string, len(m.Errors)) for i, err := range m.Errors { @@ -34,6 +34,10 @@ func (m MultiError) Error() string { return strings.Join(errs, "\n") } +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + // ExitCoder is the interface checked by `App` and `Command` for a custom exit // code type ExitCoder interface { @@ -44,11 +48,11 @@ type ExitCoder interface { // ExitError fulfills both the builtin `error` interface and `ExitCoder` type ExitError struct { exitCode int - message string + message interface{} } // NewExitError makes a new *ExitError -func NewExitError(message string, exitCode int) *ExitError { +func NewExitError(message interface{}, exitCode int) *ExitError { return &ExitError{ exitCode: exitCode, message: message, @@ -58,7 +62,7 @@ func NewExitError(message string, exitCode int) *ExitError { // Error returns the string message, fulfilling the interface required by // `error` func (ee *ExitError) Error() string { - return ee.message + return fmt.Sprintf("%v", ee.message) } // ExitCode returns the exit code, fulfilling the interface required by @@ -70,7 +74,7 @@ func (ee *ExitError) ExitCode() int { // HandleExitCoder checks if the error fulfills the ExitCoder interface, and if // so prints the error to stderr (if it is non-empty) and calls OsExiter with the // given exit code. If the given error is a MultiError, then this func is -// called on all members of the Errors slice. +// called on all members of the Errors slice and calls OsExiter with the last exit code. func HandleExitCoder(err error) { if err == nil { return @@ -78,15 +82,34 @@ func HandleExitCoder(err error) { if exitErr, ok := err.(ExitCoder); ok { if err.Error() != "" { - fmt.Fprintln(ErrWriter, err) + if _, ok := exitErr.(ErrorFormatter); ok { + fmt.Fprintf(ErrWriter, "%+v\n", err) + } else { + fmt.Fprintln(ErrWriter, err) + } } OsExiter(exitErr.ExitCode()) return } if multiErr, ok := err.(MultiError); ok { - for _, merr := range multiErr.Errors { - HandleExitCoder(merr) + code := handleMultiError(multiErr) + OsExiter(code) + return + } +} + +func handleMultiError(multiErr MultiError) int { + code := 1 + for _, merr := range multiErr.Errors { + if multiErr2, ok := merr.(MultiError); ok { + code = handleMultiError(multiErr2) + } else { + fmt.Fprintln(ErrWriter, merr) + if exitErr, ok := merr.(ExitCoder); ok { + code = exitErr.ExitCode() + } } } + return code } diff --git a/vendor/gopkg.in/urfave/cli.v1/flag-types.json b/vendor/gopkg.in/urfave/cli.v1/flag-types.json new file mode 100644 index 00000000000..1223107859a --- /dev/null +++ b/vendor/gopkg.in/urfave/cli.v1/flag-types.json @@ -0,0 +1,93 @@ +[ + { + "name": "Bool", + "type": "bool", + "value": false, + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "BoolT", + "type": "bool", + "value": false, + "doctail": " that is true by default", + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "Duration", + "type": "time.Duration", + "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", + "context_default": "0", + "parser": "time.ParseDuration(f.Value.String())" + }, + { + "name": "Float64", + "type": "float64", + "context_default": "0", + "parser": "strconv.ParseFloat(f.Value.String(), 64)" + }, + { + "name": "Generic", + "type": "Generic", + "dest": false, + "context_default": "nil", + "context_type": "interface{}" + }, + { + "name": "Int64", + "type": "int64", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" + }, + { + "name": "Int", + "type": "int", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", + "parser_cast": "int(parsed)" + }, + { + "name": "IntSlice", + "type": "*IntSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]int", + "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" + }, + { + "name": "Int64Slice", + "type": "*Int64Slice", + "dest": false, + "context_default": "nil", + "context_type": "[]int64", + "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" + }, + { + "name": "String", + "type": "string", + "context_default": "\"\"", + "parser": "f.Value.String(), error(nil)" + }, + { + "name": "StringSlice", + "type": "*StringSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]string", + "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" + }, + { + "name": "Uint64", + "type": "uint64", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" + }, + { + "name": "Uint", + "type": "uint", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", + "parser_cast": "uint(parsed)" + } +] diff --git a/vendor/gopkg.in/urfave/cli.v1/flag.go b/vendor/gopkg.in/urfave/cli.v1/flag.go index f8a28d119ef..877ff3523db 100644 --- a/vendor/gopkg.in/urfave/cli.v1/flag.go +++ b/vendor/gopkg.in/urfave/cli.v1/flag.go @@ -3,24 +3,24 @@ package cli import ( "flag" "fmt" - "os" "reflect" "runtime" "strconv" "strings" + "syscall" "time" ) const defaultPlaceholder = "value" // BashCompletionFlag enables bash-completion for all commands and subcommands -var BashCompletionFlag = BoolFlag{ +var BashCompletionFlag Flag = BoolFlag{ Name: "generate-bash-completion", Hidden: true, } // VersionFlag prints the version for the application -var VersionFlag = BoolFlag{ +var VersionFlag Flag = BoolFlag{ Name: "version, v", Usage: "print the version", } @@ -28,7 +28,7 @@ var VersionFlag = BoolFlag{ // HelpFlag prints the help for all commands and subcommands // Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand // unless HideHelp is set to true) -var HelpFlag = BoolFlag{ +var HelpFlag Flag = BoolFlag{ Name: "help, h", Usage: "show help", } @@ -37,6 +37,21 @@ var HelpFlag = BoolFlag{ // to display a flag. var FlagStringer FlagStringFunc = stringifyFlag +// FlagsByName is a slice of Flag. +type FlagsByName []Flag + +func (f FlagsByName) Len() int { + return len(f) +} + +func (f FlagsByName) Less(i, j int) bool { + return f[i].GetName() < f[j].GetName() +} + +func (f FlagsByName) Swap(i, j int) { + f[i], f[j] = f[j], f[i] +} + // Flag is a common interface related to parsing flags in cli. // For more advanced flag parsing techniques, it is recommended that // this interface be implemented. @@ -47,13 +62,29 @@ type Flag interface { GetName() string } -func flagSet(name string, flags []Flag) *flag.FlagSet { +// errorableFlag is an interface that allows us to return errors during apply +// it allows flags defined in this library to return errors in a fashion backwards compatible +// TODO remove in v2 and modify the existing Flag interface to return errors +type errorableFlag interface { + Flag + + ApplyWithError(*flag.FlagSet) error +} + +func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { set := flag.NewFlagSet(name, flag.ContinueOnError) for _, f := range flags { - f.Apply(set) + //TODO remove in v2 when errorableFlag is removed + if ef, ok := f.(errorableFlag); ok { + if err := ef.ApplyWithError(set); err != nil { + return nil, err + } + } else { + f.Apply(set) + } } - return set + return set, nil } func eachName(longName string, fn func(string)) { @@ -70,31 +101,24 @@ type Generic interface { String() string } -// GenericFlag is the flag type for types implementing Generic -type GenericFlag struct { - Name string - Value Generic - Usage string - EnvVar string - Hidden bool -} - -// String returns the string representation of the generic flag to display the -// help text to the user (uses the String() method of the generic flag to show -// the value) -func (f GenericFlag) String() string { - return FlagStringer(f) -} - // Apply takes the flagset and calls Set on the generic flag with the value // provided by the user for parsing by the flag +// Ignores parsing errors func (f GenericFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError takes the flagset and calls Set on the generic flag with the value +// provided by the user for parsing by the flag +func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error { val := f.Value if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { - val.Set(envVal) + if envVal, ok := syscall.Getenv(envVar); ok { + if err := val.Set(envVal); err != nil { + return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err) + } break } } @@ -103,14 +127,11 @@ func (f GenericFlag) Apply(set *flag.FlagSet) { eachName(f.Name, func(name string) { set.Var(f.Value, name, f.Usage) }) -} -// GetName returns the name of a flag. -func (f GenericFlag) GetName() string { - return f.Name + return nil } -// StringSlice is an opaque type for []string to satisfy flag.Value +// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter type StringSlice []string // Set appends the string value to the list of values @@ -129,31 +150,29 @@ func (f *StringSlice) Value() []string { return *f } -// StringSliceFlag is a string flag that can be specified multiple times on the -// command-line -type StringSliceFlag struct { - Name string - Value *StringSlice - Usage string - EnvVar string - Hidden bool -} - -// String returns the usage -func (f StringSliceFlag) String() string { - return FlagStringer(f) +// Get returns the slice of strings set by this flag +func (f *StringSlice) Get() interface{} { + return *f } // Apply populates the flag given the flag set and environment +// Ignores errors func (f StringSliceFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { newVal := &StringSlice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) - newVal.Set(s) + if err := newVal.Set(s); err != nil { + return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err) + } } f.Value = newVal break @@ -167,14 +186,11 @@ func (f StringSliceFlag) Apply(set *flag.FlagSet) { } set.Var(f.Value, name, f.Usage) }) -} -// GetName returns the name of a flag. -func (f StringSliceFlag) GetName() string { - return f.Name + return nil } -// IntSlice is an opaque type for []int to satisfy flag.Value +// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter type IntSlice []int // Set parses the value into an integer and appends it to the list of values @@ -197,33 +213,28 @@ func (f *IntSlice) Value() []int { return *f } -// IntSliceFlag is an int flag that can be specified multiple times on the -// command-line -type IntSliceFlag struct { - Name string - Value *IntSlice - Usage string - EnvVar string - Hidden bool -} - -// String returns the usage -func (f IntSliceFlag) String() string { - return FlagStringer(f) +// Get returns the slice of ints set by this flag +func (f *IntSlice) Get() interface{} { + return *f } // Apply populates the flag given the flag set and environment +// Ignores errors func (f IntSliceFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { newVal := &IntSlice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) - err := newVal.Set(s) - if err != nil { - fmt.Fprintf(ErrWriter, err.Error()) + if err := newVal.Set(s); err != nil { + return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err) } } f.Value = newVal @@ -238,14 +249,11 @@ func (f IntSliceFlag) Apply(set *flag.FlagSet) { } set.Var(f.Value, name, f.Usage) }) -} -// GetName returns the name of the flag. -func (f IntSliceFlag) GetName() string { - return f.Name + return nil } -// Int64Slice is an opaque type for []int to satisfy flag.Value +// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter type Int64Slice []int64 // Set parses the value into an integer and appends it to the list of values @@ -268,33 +276,28 @@ func (f *Int64Slice) Value() []int64 { return *f } -// Int64SliceFlag is an int flag that can be specified multiple times on the -// command-line -type Int64SliceFlag struct { - Name string - Value *Int64Slice - Usage string - EnvVar string - Hidden bool -} - -// String returns the usage -func (f Int64SliceFlag) String() string { - return FlagStringer(f) +// Get returns the slice of ints set by this flag +func (f *Int64Slice) Get() interface{} { + return *f } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Int64SliceFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { newVal := &Int64Slice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) - err := newVal.Set(s) - if err != nil { - fmt.Fprintf(ErrWriter, err.Error()) + if err := newVal.Set(s); err != nil { + return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err) } } f.Value = newVal @@ -309,38 +312,33 @@ func (f Int64SliceFlag) Apply(set *flag.FlagSet) { } set.Var(f.Value, name, f.Usage) }) -} - -// GetName returns the name of the flag. -func (f Int64SliceFlag) GetName() string { - return f.Name -} - -// BoolFlag is a switch that defaults to false -type BoolFlag struct { - Name string - Usage string - EnvVar string - Destination *bool - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f BoolFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f BoolFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error { val := false if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { + if envVal == "" { + val = false + break + } + envValBool, err := strconv.ParseBool(envVal) - if err == nil { - val = envValBool + if err != nil { + return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) } + + val = envValBool break } } @@ -353,40 +351,35 @@ func (f BoolFlag) Apply(set *flag.FlagSet) { } set.Bool(name, val, f.Usage) }) -} -// GetName returns the name of the flag. -func (f BoolFlag) GetName() string { - return f.Name -} - -// BoolTFlag this represents a boolean flag that is true by default, but can -// still be set to false by --some-flag=false -type BoolTFlag struct { - Name string - Usage string - EnvVar string - Destination *bool - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f BoolTFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f BoolTFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error { val := true if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { - envValBool, err := strconv.ParseBool(envVal) - if err == nil { - val = envValBool + if envVal, ok := syscall.Getenv(envVar); ok { + if envVal == "" { + val = false break } + + envValBool, err := strconv.ParseBool(envVal) + if err != nil { + return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) + } + + val = envValBool + break } } } @@ -398,34 +391,22 @@ func (f BoolTFlag) Apply(set *flag.FlagSet) { } set.Bool(name, val, f.Usage) }) -} - -// GetName returns the name of the flag. -func (f BoolTFlag) GetName() string { - return f.Name -} - -// StringFlag represents a flag that takes as string value -type StringFlag struct { - Name string - Value string - Usage string - EnvVar string - Destination *string - Hidden bool -} -// String returns the usage -func (f StringFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f StringFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f StringFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { f.Value = envVal break } @@ -439,39 +420,28 @@ func (f StringFlag) Apply(set *flag.FlagSet) { } set.String(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f StringFlag) GetName() string { - return f.Name -} - -// IntFlag is a flag that takes an integer -type IntFlag struct { - Name string - Value int - Usage string - EnvVar string - Destination *int - Hidden bool -} - -// String returns the usage -func (f IntFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f IntFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f IntFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err == nil { - f.Value = int(envValInt) - break + if err != nil { + return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) } + f.Value = int(envValInt) + break } } } @@ -483,39 +453,29 @@ func (f IntFlag) Apply(set *flag.FlagSet) { } set.Int(name, f.Value, f.Usage) }) -} - -// GetName returns the name of the flag. -func (f IntFlag) GetName() string { - return f.Name -} -// Int64Flag is a flag that takes a 64-bit integer -type Int64Flag struct { - Name string - Value int64 - Usage string - EnvVar string - Destination *int64 - Hidden bool -} - -// String returns the usage -func (f Int64Flag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Int64Flag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err == nil { - f.Value = envValInt - break + if err != nil { + return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) } + + f.Value = envValInt + break } } } @@ -527,39 +487,29 @@ func (f Int64Flag) Apply(set *flag.FlagSet) { } set.Int64(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f Int64Flag) GetName() string { - return f.Name -} - -// UintFlag is a flag that takes an unsigned integer -type UintFlag struct { - Name string - Value uint - Usage string - EnvVar string - Destination *uint - Hidden bool -} - -// String returns the usage -func (f UintFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f UintFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f UintFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err == nil { - f.Value = uint(envValInt) - break + if err != nil { + return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err) } + + f.Value = uint(envValInt) + break } } } @@ -571,39 +521,29 @@ func (f UintFlag) Apply(set *flag.FlagSet) { } set.Uint(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f UintFlag) GetName() string { - return f.Name -} - -// Uint64Flag is a flag that takes an unsigned 64-bit integer -type Uint64Flag struct { - Name string - Value uint64 - Usage string - EnvVar string - Destination *uint64 - Hidden bool -} - -// String returns the usage -func (f Uint64Flag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Uint64Flag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err == nil { - f.Value = uint64(envValInt) - break + if err != nil { + return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err) } + + f.Value = uint64(envValInt) + break } } } @@ -615,40 +555,29 @@ func (f Uint64Flag) Apply(set *flag.FlagSet) { } set.Uint64(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f Uint64Flag) GetName() string { - return f.Name -} - -// DurationFlag is a flag that takes a duration specified in Go's duration -// format: https://golang.org/pkg/time/#ParseDuration -type DurationFlag struct { - Name string - Value time.Duration - Usage string - EnvVar string - Destination *time.Duration - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f DurationFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f DurationFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValDuration, err := time.ParseDuration(envVal) - if err == nil { - f.Value = envValDuration - break + if err != nil { + return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err) } + + f.Value = envValDuration + break } } } @@ -660,38 +589,29 @@ func (f DurationFlag) Apply(set *flag.FlagSet) { } set.Duration(name, f.Value, f.Usage) }) -} - -// GetName returns the name of the flag. -func (f DurationFlag) GetName() string { - return f.Name -} -// Float64Flag is a flag that takes an float value -type Float64Flag struct { - Name string - Value float64 - Usage string - EnvVar string - Destination *float64 - Hidden bool -} - -// String returns the usage -func (f Float64Flag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Float64Flag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValFloat, err := strconv.ParseFloat(envVal, 10) - if err == nil { - f.Value = float64(envValFloat) + if err != nil { + return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err) } + + f.Value = float64(envValFloat) + break } } } @@ -703,17 +623,15 @@ func (f Float64Flag) Apply(set *flag.FlagSet) { } set.Float64(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f Float64Flag) GetName() string { - return f.Name + return nil } func visibleFlags(fl []Flag) []Flag { visible := []Flag{} for _, flag := range fl { - if !flagValue(flag).FieldByName("Hidden").Bool() { + field := flagValue(flag).FieldByName("Hidden") + if !field.IsValid() || !field.Bool() { visible = append(visible, flag) } } @@ -806,9 +724,8 @@ func stringifyFlag(f Flag) string { needsPlaceholder := false defaultValueString := "" - val := fv.FieldByName("Value") - if val.IsValid() { + if val := fv.FieldByName("Value"); val.IsValid() { needsPlaceholder = true defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface()) diff --git a/vendor/gopkg.in/urfave/cli.v1/flag_generated.go b/vendor/gopkg.in/urfave/cli.v1/flag_generated.go new file mode 100644 index 00000000000..491b61956c7 --- /dev/null +++ b/vendor/gopkg.in/urfave/cli.v1/flag_generated.go @@ -0,0 +1,627 @@ +package cli + +import ( + "flag" + "strconv" + "time" +) + +// WARNING: This file is generated! + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Destination *bool +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f BoolFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f BoolFlag) GetName() string { + return f.Name +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (c *Context) Bool(name string) bool { + return lookupBool(name, c.flagSet) +} + +// GlobalBool looks up the value of a global BoolFlag, returns +// false if not found +func (c *Context) GlobalBool(name string) bool { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupBool(name, fs) + } + return false +} + +func lookupBool(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} + +// BoolTFlag is a flag with type bool that is true by default +type BoolTFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Destination *bool +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f BoolTFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f BoolTFlag) GetName() string { + return f.Name +} + +// BoolT looks up the value of a local BoolTFlag, returns +// false if not found +func (c *Context) BoolT(name string) bool { + return lookupBoolT(name, c.flagSet) +} + +// GlobalBoolT looks up the value of a global BoolTFlag, returns +// false if not found +func (c *Context) GlobalBoolT(name string) bool { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupBoolT(name, fs) + } + return false +} + +func lookupBoolT(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} + +// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) +type DurationFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value time.Duration + Destination *time.Duration +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f DurationFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f DurationFlag) GetName() string { + return f.Name +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (c *Context) Duration(name string) time.Duration { + return lookupDuration(name, c.flagSet) +} + +// GlobalDuration looks up the value of a global DurationFlag, returns +// 0 if not found +func (c *Context) GlobalDuration(name string) time.Duration { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupDuration(name, fs) + } + return 0 +} + +func lookupDuration(name string, set *flag.FlagSet) time.Duration { + f := set.Lookup(name) + if f != nil { + parsed, err := time.ParseDuration(f.Value.String()) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value float64 + Destination *float64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Float64Flag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Float64Flag) GetName() string { + return f.Name +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (c *Context) Float64(name string) float64 { + return lookupFloat64(name, c.flagSet) +} + +// GlobalFloat64 looks up the value of a global Float64Flag, returns +// 0 if not found +func (c *Context) GlobalFloat64(name string) float64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupFloat64(name, fs) + } + return 0 +} + +func lookupFloat64(name string, set *flag.FlagSet) float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseFloat(f.Value.String(), 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value Generic +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f GenericFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f GenericFlag) GetName() string { + return f.Name +} + +// Generic looks up the value of a local GenericFlag, returns +// nil if not found +func (c *Context) Generic(name string) interface{} { + return lookupGeneric(name, c.flagSet) +} + +// GlobalGeneric looks up the value of a global GenericFlag, returns +// nil if not found +func (c *Context) GlobalGeneric(name string) interface{} { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupGeneric(name, fs) + } + return nil +} + +func lookupGeneric(name string, set *flag.FlagSet) interface{} { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value, error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value int64 + Destination *int64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Int64Flag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Int64Flag) GetName() string { + return f.Name +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (c *Context) Int64(name string) int64 { + return lookupInt64(name, c.flagSet) +} + +// GlobalInt64 looks up the value of a global Int64Flag, returns +// 0 if not found +func (c *Context) GlobalInt64(name string) int64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt64(name, fs) + } + return 0 +} + +func lookupInt64(name string, set *flag.FlagSet) int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value int + Destination *int +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f IntFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f IntFlag) GetName() string { + return f.Name +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (c *Context) Int(name string) int { + return lookupInt(name, c.flagSet) +} + +// GlobalInt looks up the value of a global IntFlag, returns +// 0 if not found +func (c *Context) GlobalInt(name string) int { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt(name, fs) + } + return 0 +} + +func lookupInt(name string, set *flag.FlagSet) int { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return int(parsed) + } + return 0 +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value *IntSlice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f IntSliceFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f IntSliceFlag) GetName() string { + return f.Name +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// nil if not found +func (c *Context) IntSlice(name string) []int { + return lookupIntSlice(name, c.flagSet) +} + +// GlobalIntSlice looks up the value of a global IntSliceFlag, returns +// nil if not found +func (c *Context) GlobalIntSlice(name string) []int { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupIntSlice(name, fs) + } + return nil +} + +func lookupIntSlice(name string, set *flag.FlagSet) []int { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*IntSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value *Int64Slice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Int64SliceFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Int64SliceFlag) GetName() string { + return f.Name +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// nil if not found +func (c *Context) Int64Slice(name string) []int64 { + return lookupInt64Slice(name, c.flagSet) +} + +// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns +// nil if not found +func (c *Context) GlobalInt64Slice(name string) []int64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt64Slice(name, fs) + } + return nil +} + +func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value string + Destination *string +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f StringFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f StringFlag) GetName() string { + return f.Name +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (c *Context) String(name string) string { + return lookupString(name, c.flagSet) +} + +// GlobalString looks up the value of a global StringFlag, returns +// "" if not found +func (c *Context) GlobalString(name string) string { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupString(name, fs) + } + return "" +} + +func lookupString(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value.String(), error(nil) + if err != nil { + return "" + } + return parsed + } + return "" +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value *StringSlice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f StringSliceFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f StringSliceFlag) GetName() string { + return f.Name +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// nil if not found +func (c *Context) StringSlice(name string) []string { + return lookupStringSlice(name, c.flagSet) +} + +// GlobalStringSlice looks up the value of a global StringSliceFlag, returns +// nil if not found +func (c *Context) GlobalStringSlice(name string) []string { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupStringSlice(name, fs) + } + return nil +} + +func lookupStringSlice(name string, set *flag.FlagSet) []string { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*StringSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value uint64 + Destination *uint64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Uint64Flag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Uint64Flag) GetName() string { + return f.Name +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (c *Context) Uint64(name string) uint64 { + return lookupUint64(name, c.flagSet) +} + +// GlobalUint64 looks up the value of a global Uint64Flag, returns +// 0 if not found +func (c *Context) GlobalUint64(name string) uint64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupUint64(name, fs) + } + return 0 +} + +func lookupUint64(name string, set *flag.FlagSet) uint64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value uint + Destination *uint +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f UintFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f UintFlag) GetName() string { + return f.Name +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (c *Context) Uint(name string) uint { + return lookupUint(name, c.flagSet) +} + +// GlobalUint looks up the value of a global UintFlag, returns +// 0 if not found +func (c *Context) GlobalUint(name string) uint { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupUint(name, fs) + } + return 0 +} + +func lookupUint(name string, set *flag.FlagSet) uint { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return uint(parsed) + } + return 0 +} diff --git a/vendor/gopkg.in/urfave/cli.v1/generate-flag-types b/vendor/gopkg.in/urfave/cli.v1/generate-flag-types new file mode 100755 index 00000000000..7147381ce37 --- /dev/null +++ b/vendor/gopkg.in/urfave/cli.v1/generate-flag-types @@ -0,0 +1,255 @@ +#!/usr/bin/env python +""" +The flag types that ship with the cli library have many things in common, and +so we can take advantage of the `go generate` command to create much of the +source code from a list of definitions. These definitions attempt to cover +the parts that vary between flag types, and should evolve as needed. + +An example of the minimum definition needed is: + + { + "name": "SomeType", + "type": "sometype", + "context_default": "nil" + } + +In this example, the code generated for the `cli` package will include a type +named `SomeTypeFlag` that is expected to wrap a value of type `sometype`. +Fetching values by name via `*cli.Context` will default to a value of `nil`. + +A more complete, albeit somewhat redundant, example showing all available +definition keys is: + + { + "name": "VeryMuchType", + "type": "*VeryMuchType", + "value": true, + "dest": false, + "doctail": " which really only wraps a []float64, oh well!", + "context_type": "[]float64", + "context_default": "nil", + "parser": "parseVeryMuchType(f.Value.String())", + "parser_cast": "[]float64(parsed)" + } + +The meaning of each field is as follows: + + name (string) - The type "name", which will be suffixed with + `Flag` when generating the type definition + for `cli` and the wrapper type for `altsrc` + type (string) - The type that the generated `Flag` type for `cli` + is expected to "contain" as its `.Value` member + value (bool) - Should the generated `cli` type have a `Value` + member? + dest (bool) - Should the generated `cli` type support a + destination pointer? + doctail (string) - Additional docs for the `cli` flag type comment + context_type (string) - The literal type used in the `*cli.Context` + reader func signature + context_default (string) - The literal value used as the default by the + `*cli.Context` reader funcs when no value is + present + parser (string) - Literal code used to parse the flag `f`, + expected to have a return signature of + (value, error) + parser_cast (string) - Literal code used to cast the `parsed` value + returned from the `parser` code +""" + +from __future__ import print_function, unicode_literals + +import argparse +import json +import os +import subprocess +import sys +import tempfile +import textwrap + + +class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter, + argparse.RawDescriptionHelpFormatter): + pass + + +def main(sysargs=sys.argv[:]): + parser = argparse.ArgumentParser( + description='Generate flag type code!', + formatter_class=_FancyFormatter) + parser.add_argument( + 'package', + type=str, default='cli', choices=_WRITEFUNCS.keys(), + help='Package for which flag types will be generated' + ) + parser.add_argument( + '-i', '--in-json', + type=argparse.FileType('r'), + default=sys.stdin, + help='Input JSON file which defines each type to be generated' + ) + parser.add_argument( + '-o', '--out-go', + type=argparse.FileType('w'), + default=sys.stdout, + help='Output file/stream to which generated source will be written' + ) + parser.epilog = __doc__ + + args = parser.parse_args(sysargs[1:]) + _generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json) + return 0 + + +def _generate_flag_types(writefunc, output_go, input_json): + types = json.load(input_json) + + tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False) + writefunc(tmp, types) + tmp.close() + + new_content = subprocess.check_output( + ['goimports', tmp.name] + ).decode('utf-8') + + print(new_content, file=output_go, end='') + output_go.flush() + os.remove(tmp.name) + + +def _set_typedef_defaults(typedef): + typedef.setdefault('doctail', '') + typedef.setdefault('context_type', typedef['type']) + typedef.setdefault('dest', True) + typedef.setdefault('value', True) + typedef.setdefault('parser', 'f.Value, error(nil)') + typedef.setdefault('parser_cast', 'parsed') + + +def _write_cli_flag_types(outfile, types): + _fwrite(outfile, """\ + package cli + + // WARNING: This file is generated! + + """) + + for typedef in types: + _set_typedef_defaults(typedef) + + _fwrite(outfile, """\ + // {name}Flag is a flag with type {type}{doctail} + type {name}Flag struct {{ + Name string + Usage string + EnvVar string + Hidden bool + """.format(**typedef)) + + if typedef['value']: + _fwrite(outfile, """\ + Value {type} + """.format(**typedef)) + + if typedef['dest']: + _fwrite(outfile, """\ + Destination *{type} + """.format(**typedef)) + + _fwrite(outfile, "\n}\n\n") + + _fwrite(outfile, """\ + // String returns a readable representation of this value + // (for usage defaults) + func (f {name}Flag) String() string {{ + return FlagStringer(f) + }} + + // GetName returns the name of the flag + func (f {name}Flag) GetName() string {{ + return f.Name + }} + + // {name} looks up the value of a local {name}Flag, returns + // {context_default} if not found + func (c *Context) {name}(name string) {context_type} {{ + return lookup{name}(name, c.flagSet) + }} + + // Global{name} looks up the value of a global {name}Flag, returns + // {context_default} if not found + func (c *Context) Global{name}(name string) {context_type} {{ + if fs := lookupGlobalFlagSet(name, c); fs != nil {{ + return lookup{name}(name, fs) + }} + return {context_default} + }} + + func lookup{name}(name string, set *flag.FlagSet) {context_type} {{ + f := set.Lookup(name) + if f != nil {{ + parsed, err := {parser} + if err != nil {{ + return {context_default} + }} + return {parser_cast} + }} + return {context_default} + }} + """.format(**typedef)) + + +def _write_altsrc_flag_types(outfile, types): + _fwrite(outfile, """\ + package altsrc + + import ( + "gopkg.in/urfave/cli.v1" + ) + + // WARNING: This file is generated! + + """) + + for typedef in types: + _set_typedef_defaults(typedef) + + _fwrite(outfile, """\ + // {name}Flag is the flag type that wraps cli.{name}Flag to allow + // for other values to be specified + type {name}Flag struct {{ + cli.{name}Flag + set *flag.FlagSet + }} + + // New{name}Flag creates a new {name}Flag + func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{ + return &{name}Flag{{{name}Flag: fl, set: nil}} + }} + + // Apply saves the flagSet for later usage calls, then calls the + // wrapped {name}Flag.Apply + func (f *{name}Flag) Apply(set *flag.FlagSet) {{ + f.set = set + f.{name}Flag.Apply(set) + }} + + // ApplyWithError saves the flagSet for later usage calls, then calls the + // wrapped {name}Flag.ApplyWithError + func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{ + f.set = set + return f.{name}Flag.ApplyWithError(set) + }} + """.format(**typedef)) + + +def _fwrite(outfile, text): + print(textwrap.dedent(text), end='', file=outfile) + + +_WRITEFUNCS = { + 'cli': _write_cli_flag_types, + 'altsrc': _write_altsrc_flag_types +} + +if __name__ == '__main__': + sys.exit(main()) diff --git a/vendor/gopkg.in/urfave/cli.v1/help.go b/vendor/gopkg.in/urfave/cli.v1/help.go index 0f4cf14cd86..57ec98d58ad 100644 --- a/vendor/gopkg.in/urfave/cli.v1/help.go +++ b/vendor/gopkg.in/urfave/cli.v1/help.go @@ -13,27 +13,31 @@ import ( // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var AppHelpTemplate = `NAME: - {{.Name}} - {{.Usage}} + {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} - {{if .Version}}{{if not .HideVersion}} + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + VERSION: - {{.Version}} - {{end}}{{end}}{{if len .Authors}} -AUTHOR(S): - {{range .Authors}}{{.}}{{end}} - {{end}}{{if .VisibleCommands}} + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}}{{if len .Authors}} + +AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} + COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{end}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}} -{{end}}{{end}}{{if .VisibleFlags}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + GLOBAL OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}}{{if .Copyright}} + {{range $index, $option := .VisibleFlags}}{{if $index}} + {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} + COPYRIGHT: - {{.Copyright}} - {{end}} + {{.Copyright}}{{end}} ` // CommandHelpTemplate is the text template for the command help topic. @@ -43,7 +47,7 @@ var CommandHelpTemplate = `NAME: {{.HelpName}} - {{.Usage}} USAGE: - {{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}} + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} @@ -60,10 +64,10 @@ OPTIONS: // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}} USAGE: - {{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{end}}{{range .VisibleCommands}} @@ -108,17 +112,42 @@ var helpSubcommand = Command{ // Prints help for the App or Command type helpPrinter func(w io.Writer, templ string, data interface{}) +// Prints help for the App or Command with custom template function. +type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{}) + // HelpPrinter is a function that writes the help output. If not set a default // is used. The function signature is: // func(w io.Writer, templ string, data interface{}) var HelpPrinter helpPrinter = printHelp +// HelpPrinterCustom is same as HelpPrinter but +// takes a custom function for template function map. +var HelpPrinterCustom helpPrinterCustom = printHelpCustom + // VersionPrinter prints the version for the App var VersionPrinter = printVersion +// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code. +func ShowAppHelpAndExit(c *Context, exitCode int) { + ShowAppHelp(c) + os.Exit(exitCode) +} + // ShowAppHelp is an action that displays the help. -func ShowAppHelp(c *Context) error { - HelpPrinter(c.App.Writer, AppHelpTemplate, c.App) +func ShowAppHelp(c *Context) (err error) { + if c.App.CustomAppHelpTemplate == "" { + HelpPrinter(c.App.Writer, AppHelpTemplate, c.App) + return + } + customAppData := func() map[string]interface{} { + if c.App.ExtraInfo == nil { + return nil + } + return map[string]interface{}{ + "ExtraInfo": c.App.ExtraInfo, + } + } + HelpPrinterCustom(c.App.Writer, c.App.CustomAppHelpTemplate, c.App, customAppData()) return nil } @@ -134,6 +163,12 @@ func DefaultAppComplete(c *Context) { } } +// ShowCommandHelpAndExit - exits with code after showing help +func ShowCommandHelpAndExit(c *Context, command string, code int) { + ShowCommandHelp(c, command) + os.Exit(code) +} + // ShowCommandHelp prints help for the given command func ShowCommandHelp(ctx *Context, command string) error { // show the subcommand help for a command with subcommands @@ -144,7 +179,11 @@ func ShowCommandHelp(ctx *Context, command string) error { for _, c := range ctx.App.Commands { if c.HasName(command) { - HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c) + if c.CustomHelpTemplate != "" { + HelpPrinterCustom(ctx.App.Writer, c.CustomHelpTemplate, c, nil) + } else { + HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c) + } return nil } } @@ -187,10 +226,15 @@ func ShowCommandCompletions(ctx *Context, command string) { } } -func printHelp(out io.Writer, templ string, data interface{}) { +func printHelpCustom(out io.Writer, templ string, data interface{}, customFunc map[string]interface{}) { funcMap := template.FuncMap{ "join": strings.Join, } + if customFunc != nil { + for key, value := range customFunc { + funcMap[key] = value + } + } w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) @@ -206,10 +250,14 @@ func printHelp(out io.Writer, templ string, data interface{}) { w.Flush() } +func printHelp(out io.Writer, templ string, data interface{}) { + printHelpCustom(out, templ, data, nil) +} + func checkVersion(c *Context) bool { found := false - if VersionFlag.Name != "" { - eachName(VersionFlag.Name, func(name string) { + if VersionFlag.GetName() != "" { + eachName(VersionFlag.GetName(), func(name string) { if c.GlobalBool(name) || c.Bool(name) { found = true } @@ -220,8 +268,8 @@ func checkVersion(c *Context) bool { func checkHelp(c *Context) bool { found := false - if HelpFlag.Name != "" { - eachName(HelpFlag.Name, func(name string) { + if HelpFlag.GetName() != "" { + eachName(HelpFlag.GetName(), func(name string) { if c.GlobalBool(name) || c.Bool(name) { found = true } @@ -240,7 +288,7 @@ func checkCommandHelp(c *Context, name string) bool { } func checkSubcommandHelp(c *Context) bool { - if c.GlobalBool("h") || c.GlobalBool("help") { + if c.Bool("h") || c.Bool("help") { ShowSubcommandHelp(c) return true } @@ -248,20 +296,43 @@ func checkSubcommandHelp(c *Context) bool { return false } +func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { + if !a.EnableBashCompletion { + return false, arguments + } + + pos := len(arguments) - 1 + lastArg := arguments[pos] + + if lastArg != "--"+BashCompletionFlag.GetName() { + return false, arguments + } + + return true, arguments[:pos] +} + func checkCompletions(c *Context) bool { - if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion { - ShowCompletions(c) - return true + if !c.shellComplete { + return false } - return false + if args := c.Args(); args.Present() { + name := args.First() + if cmd := c.App.Command(name); cmd != nil { + // let the command handle the completion + return false + } + } + + ShowCompletions(c) + return true } func checkCommandCompletions(c *Context, name string) bool { - if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { - ShowCommandCompletions(c, name) - return true + if !c.shellComplete { + return false } - return false + ShowCommandCompletions(c, name) + return true } diff --git a/vendor/gopkg.in/urfave/cli.v1/runtests b/vendor/gopkg.in/urfave/cli.v1/runtests index 0a7b483e317..ee22bdeed55 100755 --- a/vendor/gopkg.in/urfave/cli.v1/runtests +++ b/vendor/gopkg.in/urfave/cli.v1/runtests @@ -18,8 +18,9 @@ def main(sysargs=sys.argv[:]): targets = { 'vet': _vet, 'test': _test, - 'gfmxr': _gfmxr, + 'gfmrun': _gfmrun, 'toc': _toc, + 'gen': _gen, } parser = argparse.ArgumentParser() @@ -34,7 +35,7 @@ def main(sysargs=sys.argv[:]): def _test(): if check_output('go version'.split()).split()[2] < 'go1.2': - _run('go test -v .'.split()) + _run('go test -v .') return coverprofiles = [] @@ -51,29 +52,45 @@ def _test(): ]) combined_name = _combine_coverprofiles(coverprofiles) - _run('go tool cover -func={}'.format(combined_name).split()) + _run('go tool cover -func={}'.format(combined_name)) os.remove(combined_name) -def _gfmxr(): - _run(['gfmxr', '-c', str(_gfmxr_count()), '-s', 'README.md']) +def _gfmrun(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.3': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + _run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md']) def _vet(): - _run('go vet ./...'.split()) + _run('go vet ./...') def _toc(): - _run(['node_modules/.bin/markdown-toc', '-i', 'README.md']) - _run(['git', 'diff', '--quiet']) + _run('node_modules/.bin/markdown-toc -i README.md') + _run('git diff --exit-code') + + +def _gen(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.5': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + + _run('go generate ./...') + _run('git diff --exit-code') def _run(command): + if hasattr(command, 'split'): + command = command.split() print('runtests: {}'.format(' '.join(command)), file=sys.stderr) check_call(command) -def _gfmxr_count(): +def _gfmrun_count(): with open('README.md') as infile: lines = infile.read().splitlines() return len(filter(_is_go_runnable, lines))

    HTML5
    -

    the-input-byte-stream-001
    Result summary & related tests
    Detailed results for this test
    Link to spec

    -
    Assumptions:
    • The default encoding for the browser you are testing is not set to ISO 8859-15.
    • -
    • The test is read from a server that supports HTTP.
    -