Merge branch 'master' into f-disable-tls
This commit is contained in:
commit
6cdb8aeb4f
|
@ -3,7 +3,7 @@ sudo: false
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.5.1
|
- 1.5.2
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
|
|
79
CHANGELOG.md
79
CHANGELOG.md
|
@ -1,4 +1,52 @@
|
||||||
## 0.4.0 (Unreleased)
|
## 0.5.0 (Unreleased)
|
||||||
|
|
||||||
|
DEPRECATIONS/BREAKING CHANGES:
|
||||||
|
* S3 physical backend: Environment variables are now preferred over
|
||||||
|
configuration values. This makes it behave similar to the rest of Vault,
|
||||||
|
which, in increasing order of preference, uses values from the configuration
|
||||||
|
file, environment variables, and CLI flags. [GH-871]
|
||||||
|
|
||||||
|
FEATURES:
|
||||||
|
|
||||||
|
* **Split Data/High Availability Physical Backends**: You can now configure
|
||||||
|
two separate physical backends: one to be used for High Availability
|
||||||
|
coordination and another to be used for encrypted data storage. See the
|
||||||
|
[configuration
|
||||||
|
documentation](https://vaultproject.io/docs/config/index.html) for details.
|
||||||
|
[GH-395]
|
||||||
|
|
||||||
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
* cli: Output secrets sorted by key name [GH-830]
|
||||||
|
* cli: Support YAML as an output format [GH-832]
|
||||||
|
* cli: Show an error if the output format is incorrect, rather than falling
|
||||||
|
back to an empty table [GH-849]
|
||||||
|
* cli: Allow setting the `advertise_addr` for HA via the
|
||||||
|
`VAULT_ADVERTISE_ADDR` environment variable [GH-581]
|
||||||
|
* helper/certutil: Add ability to parse PKCS#8 bundles [GH-829]
|
||||||
|
* logical/pki: Assign ExtKeyUsageAny to CA certs generated/signed with the
|
||||||
|
backend; this fixes the non-spec validation logic used in the Windows Crypto
|
||||||
|
API and Go's verification functions [GH-846]
|
||||||
|
* physical/etcd: Support basic auth [GH-859]
|
||||||
|
|
||||||
|
BUG FIXES:
|
||||||
|
* api: Correct the HTTP verb used in the LookupSelf method [GH-887]
|
||||||
|
* core: When running in standalone mode, don't advertise that we are active
|
||||||
|
until post-unseal setup completes [GH-872]
|
||||||
|
* core: Update go-cleanhttp dependency to ensure idle connections aren't
|
||||||
|
leaked [GH-867]
|
||||||
|
* physical: Use square brackets when setting an IPv6-based advertise address
|
||||||
|
as the auto-detected advertise address [GH-883]
|
||||||
|
* physical/s3: Use an initialized client when using IAM roles to fix a
|
||||||
|
regression introduced against newer versions of the AWS Go SDK [GH-836]
|
||||||
|
|
||||||
|
MISC:
|
||||||
|
|
||||||
|
* Add `vault-java` to libraries [GH-851]
|
||||||
|
* Various minor documentation fixes and improvements [GH-839] [GH-854]
|
||||||
|
[GH-861] [GH-876]
|
||||||
|
|
||||||
|
## 0.4.0 (December 10, 2015)
|
||||||
|
|
||||||
DEPRECATIONS/BREAKING CHANGES:
|
DEPRECATIONS/BREAKING CHANGES:
|
||||||
|
|
||||||
|
@ -11,9 +59,25 @@ DEPRECATIONS/BREAKING CHANGES:
|
||||||
* As noted below in the FEATURES section, if your Vault installation contains
|
* As noted below in the FEATURES section, if your Vault installation contains
|
||||||
a policy called `default`, new tokens created will inherit this policy
|
a policy called `default`, new tokens created will inherit this policy
|
||||||
automatically.
|
automatically.
|
||||||
|
* In the PKI backend there have been a few minor breaking changes:
|
||||||
|
* The token display name is no longer a valid option for providing a base
|
||||||
|
domain for issuance. Since this name is prepended with the name of the
|
||||||
|
authentication backend that issued it, it provided a faulty use-case at best
|
||||||
|
and a confusing experience at worst. We hope to figure out a better
|
||||||
|
per-token value in a future release.
|
||||||
|
* The `allowed_base_domain` parameter has been changed to `allowed_domains`,
|
||||||
|
which accepts a comma-separated list of domains. This allows issuing
|
||||||
|
certificates with DNS subjects across multiple domains. If you had a
|
||||||
|
configured `allowed_base_domain` parameter, it will be migrated
|
||||||
|
automatically when the role is read (either via a normal read, or via
|
||||||
|
issuing a certificate).
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
|
|
||||||
|
* **Significantly Enhanced PKI Backend**: The `pki` backend can now generate
|
||||||
|
and sign root CA certificates and intermediate CA CSRs. It can also now sign
|
||||||
|
submitted client CSRs, as well as a significant number of other
|
||||||
|
enhancements. See the updated documentation for the full API. [GH-666]
|
||||||
* **CRL Checking for Certificate Authentication**: The `cert` backend now
|
* **CRL Checking for Certificate Authentication**: The `cert` backend now
|
||||||
supports pushing CRLs into the mount and using the contained serial numbers
|
supports pushing CRLs into the mount and using the contained serial numbers
|
||||||
for revocation checking. See the documentation for the `cert` backend for
|
for revocation checking. See the documentation for the `cert` backend for
|
||||||
|
@ -58,9 +122,12 @@ IMPROVEMENTS:
|
||||||
* logical: Responses now contain a "warnings" key containing a list of
|
* logical: Responses now contain a "warnings" key containing a list of
|
||||||
warnings returned from the server. These are conditions that did not require
|
warnings returned from the server. These are conditions that did not require
|
||||||
failing an operation, but of which the client should be aware. [GH-676]
|
failing an operation, but of which the client should be aware. [GH-676]
|
||||||
* physical/consul: Consul now uses a connection pool to limit the number of
|
* physical/(consul,etcd): Consul and etcd now use a connection pool to limit
|
||||||
outstanding operations, improving behavior when a lot of operations must
|
the number of outstanding operations, improving behavior when a lot of
|
||||||
happen at once [GH-677]
|
operations must happen at once [GH-677] [GH-780]
|
||||||
|
* physical/consul: The `datacenter` parameter was removed; It could not be
|
||||||
|
effective unless the Vault node (or the Consul node it was connecting to)
|
||||||
|
was in the datacenter specified, in which case it wasn't needed [GH-816]
|
||||||
* physical/etcd: Support TLS-encrypted connections and use a connection pool
|
* physical/etcd: Support TLS-encrypted connections and use a connection pool
|
||||||
to limit the number of outstanding operations [GH-780]
|
to limit the number of outstanding operations [GH-780]
|
||||||
* physical/s3: The S3 endpoint can now be configured, allowing using
|
* physical/s3: The S3 endpoint can now be configured, allowing using
|
||||||
|
@ -94,13 +161,15 @@ generate them, leading to client errors.
|
||||||
* secret/generic: Validate given duration at write time, not just read time;
|
* secret/generic: Validate given duration at write time, not just read time;
|
||||||
if stored durations are not parseable, return a warning and the default
|
if stored durations are not parseable, return a warning and the default
|
||||||
duration rather than an error [GH-718]
|
duration rather than an error [GH-718]
|
||||||
|
* secret/generic: Return 400 instead of 500 when `generic` backend is written
|
||||||
|
to with no data fields [GH-825]
|
||||||
* secret/postgresql: Revoke permissions before dropping a user or revocation
|
* secret/postgresql: Revoke permissions before dropping a user or revocation
|
||||||
may fail [GH-699]
|
may fail [GH-699]
|
||||||
|
|
||||||
MISC:
|
MISC:
|
||||||
|
|
||||||
* Various documentation fixes and improvements [GH-685] [GH-688] [GH-697]
|
* Various documentation fixes and improvements [GH-685] [GH-688] [GH-697]
|
||||||
[GH-710] [GH-715]
|
[GH-710] [GH-715] [GH-831]
|
||||||
|
|
||||||
## 0.3.1 (October 6, 2015)
|
## 0.3.1 (October 6, 2015)
|
||||||
|
|
||||||
|
|
131
Godeps/Godeps.json
generated
131
Godeps/Godeps.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/vault",
|
"ImportPath": "github.com/hashicorp/vault",
|
||||||
"GoVersion": "go1.5.1",
|
"GoVersion": "go1.5.2",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
|
@ -13,85 +13,90 @@
|
||||||
"ImportPath": "github.com/armon/go-radix",
|
"ImportPath": "github.com/armon/go-radix",
|
||||||
"Rev": "fbd82e84e2b13651f3abc5ffd26b65ba71bc8f93"
|
"Rev": "fbd82e84e2b13651f3abc5ffd26b65ba71bc8f93"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/asaskevich/govalidator",
|
||||||
|
"Comment": "v2-37-gedd46cd",
|
||||||
|
"Rev": "edd46cdac249b001c7b7d88c6d43993ea875e8d8"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/restxml",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/iam",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/iam",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
"ImportPath": "github.com/aws/aws-sdk-go/service/s3",
|
||||||
"Comment": "v0.10.4-18-gce51895",
|
"Comment": "v1.0.4",
|
||||||
"Rev": "ce51895e994693d65ab997ae48032bf13a9290b7"
|
"Rev": "999b1591218c36d5050d1ba7266eba956e65965f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/client",
|
"ImportPath": "github.com/coreos/etcd/client",
|
||||||
"Comment": "v2.3.0-alpha.0-64-gc4672ce",
|
"Comment": "v2.3.0-alpha.0-117-g858857d",
|
||||||
"Rev": "c4672ced3e0a0dc2232af3194d00d869516866f1"
|
"Rev": "858857d7013af3142310aa2cef9a29d6a2edb736"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
"ImportPath": "github.com/coreos/etcd/pkg/pathutil",
|
||||||
"Comment": "v2.3.0-alpha.0-64-gc4672ce",
|
"Comment": "v2.3.0-alpha.0-117-g858857d",
|
||||||
"Rev": "c4672ced3e0a0dc2232af3194d00d869516866f1"
|
"Rev": "858857d7013af3142310aa2cef9a29d6a2edb736"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
"ImportPath": "github.com/coreos/etcd/pkg/transport",
|
||||||
"Comment": "v2.3.0-alpha.0-64-gc4672ce",
|
"Comment": "v2.3.0-alpha.0-117-g858857d",
|
||||||
"Rev": "c4672ced3e0a0dc2232af3194d00d869516866f1"
|
"Rev": "858857d7013af3142310aa2cef9a29d6a2edb736"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
"ImportPath": "github.com/coreos/etcd/pkg/types",
|
||||||
"Comment": "v2.3.0-alpha.0-64-gc4672ce",
|
"Comment": "v2.3.0-alpha.0-117-g858857d",
|
||||||
"Rev": "c4672ced3e0a0dc2232af3194d00d869516866f1"
|
"Rev": "858857d7013af3142310aa2cef9a29d6a2edb736"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/duosecurity/duo_api_golang",
|
"ImportPath": "github.com/duosecurity/duo_api_golang",
|
||||||
|
@ -99,17 +104,21 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/fatih/structs",
|
"ImportPath": "github.com/fatih/structs",
|
||||||
"Rev": "c701457aaa1ff6709d5e35fccb5c129448e0a37b"
|
"Rev": "9a7733345ff091c5457cb963f498a79ecd0bdbaa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/ghodss/yaml",
|
||||||
|
"Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/go-ini/ini",
|
"ImportPath": "github.com/go-ini/ini",
|
||||||
"Comment": "v0-48-g060d7da",
|
"Comment": "v0-56-g03e0e7d",
|
||||||
"Rev": "060d7da055ba6ec5ea7a31f116332fe5efa04ce0"
|
"Rev": "03e0e7d51a13a91c765d8d0161246bc14a38001a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/go-ldap/ldap",
|
"ImportPath": "github.com/go-ldap/ldap",
|
||||||
"Comment": "v2.1-8-ge983ad5",
|
"Comment": "v2.2",
|
||||||
"Rev": "e983ad52b3ab99bd12fc7cad94e31509a0a010cc"
|
"Rev": "e9a325d64989e2844be629682cb085d2c58eef8d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/go-sql-driver/mysql",
|
"ImportPath": "github.com/go-sql-driver/mysql",
|
||||||
|
@ -118,8 +127,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gocql/gocql",
|
"ImportPath": "github.com/gocql/gocql",
|
||||||
"Comment": "1st_gen_framing-361-gf8da9df",
|
"Comment": "1st_gen_framing-383-g87cc185",
|
||||||
"Rev": "f8da9dfadd52ef498900e0050ee6578e0f58e8ce"
|
"Rev": "87cc1854b57c7a4d8f4ae1d0cc358ed6ecb0f8c3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/golang/snappy",
|
"ImportPath": "github.com/golang/snappy",
|
||||||
|
@ -127,7 +136,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/go-github/github",
|
"ImportPath": "github.com/google/go-github/github",
|
||||||
"Rev": "6eb49d4ba5175412dcbb29b0031ebf02ab85a48d"
|
"Rev": "47f2593dad1971eec2f0a0971aa007fef5edbc50"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/go-querystring/query",
|
"ImportPath": "github.com/google/go-querystring/query",
|
||||||
|
@ -139,8 +148,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/consul/api",
|
"ImportPath": "github.com/hashicorp/consul/api",
|
||||||
"Comment": "v0.6.0-rc2-1-g402a366",
|
"Comment": "v0.6.0-rc2-21-g86f20a3",
|
||||||
"Rev": "402a3666769ea796d3b5b779ae343bb8c59abc50"
|
"Rev": "86f20a32e5afe1fbcd98129239cdea4bf8b0d5ba"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/errwrap",
|
"ImportPath": "github.com/hashicorp/errwrap",
|
||||||
|
@ -148,7 +157,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/go-cleanhttp",
|
"ImportPath": "github.com/hashicorp/go-cleanhttp",
|
||||||
"Rev": "5df5ddc69534f1a4697289f1dca2193fbb40213f"
|
"Rev": "ce617e79981a8fff618bb643d155133a8f38db96"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/go-multierror",
|
"ImportPath": "github.com/hashicorp/go-multierror",
|
||||||
|
@ -158,9 +167,13 @@
|
||||||
"ImportPath": "github.com/hashicorp/go-syslog",
|
"ImportPath": "github.com/hashicorp/go-syslog",
|
||||||
"Rev": "42a2b573b664dbf281bd48c3cc12c086b17a39ba"
|
"Rev": "42a2b573b664dbf281bd48c3cc12c086b17a39ba"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/hashicorp/go-uuid",
|
||||||
|
"Rev": "2d537aea09f39d27f9aa33092154c51ebe277486"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/golang-lru",
|
"ImportPath": "github.com/hashicorp/golang-lru",
|
||||||
"Rev": "a6091bb5d00e2e9c4a16a0e739e306f8a3071a3c"
|
"Rev": "b361c4c189a958f7d0ad435952611c140751afe2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/hcl",
|
"ImportPath": "github.com/hashicorp/hcl",
|
||||||
|
@ -175,10 +188,6 @@
|
||||||
"Comment": "v0.6.4-145-ga72c045",
|
"Comment": "v0.6.4-145-ga72c045",
|
||||||
"Rev": "a72c0453da2ba628a013e98bf323a76be4aa1443"
|
"Rev": "a72c0453da2ba628a013e98bf323a76be4aa1443"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ImportPath": "github.com/hashicorp/uuid",
|
|
||||||
"Rev": "2951e8b9707a040acdb49145ed9f36a088f3532e"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/jmespath/go-jmespath",
|
"ImportPath": "github.com/jmespath/go-jmespath",
|
||||||
"Comment": "0.2.2",
|
"Comment": "0.2.2",
|
||||||
|
@ -186,12 +195,12 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/kardianos/osext",
|
"ImportPath": "github.com/kardianos/osext",
|
||||||
"Rev": "345163ffe35aa66560a4cd7dddf00f3ae21c9fda"
|
"Rev": "10da29423eb9a6269092eebdc2be32209612d9d2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/lib/pq",
|
"ImportPath": "github.com/lib/pq",
|
||||||
"Comment": "go1.0-cutoff-61-g83c4f41",
|
"Comment": "go1.0-cutoff-63-g11fc39a",
|
||||||
"Rev": "83c4f410d0aed80a0f44bac6a576a7f2435791f3"
|
"Rev": "11fc39a580a008f1f39bb3d11d984fb34ed778d9"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/mitchellh/cli",
|
"ImportPath": "github.com/mitchellh/cli",
|
||||||
|
@ -228,31 +237,31 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||||
"Rev": "346896d57731cb5670b36c6178fc5519f3225980"
|
"Rev": "7b85b097bf7527677d54d3220065e966a0e3b613"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/blowfish",
|
"ImportPath": "golang.org/x/crypto/blowfish",
|
||||||
"Rev": "346896d57731cb5670b36c6178fc5519f3225980"
|
"Rev": "7b85b097bf7527677d54d3220065e966a0e3b613"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/cast5",
|
"ImportPath": "golang.org/x/crypto/cast5",
|
||||||
"Rev": "346896d57731cb5670b36c6178fc5519f3225980"
|
"Rev": "7b85b097bf7527677d54d3220065e966a0e3b613"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/curve25519",
|
"ImportPath": "golang.org/x/crypto/curve25519",
|
||||||
"Rev": "346896d57731cb5670b36c6178fc5519f3225980"
|
"Rev": "7b85b097bf7527677d54d3220065e966a0e3b613"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/openpgp",
|
"ImportPath": "golang.org/x/crypto/openpgp",
|
||||||
"Rev": "346896d57731cb5670b36c6178fc5519f3225980"
|
"Rev": "7b85b097bf7527677d54d3220065e966a0e3b613"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/ssh",
|
"ImportPath": "golang.org/x/crypto/ssh",
|
||||||
"Rev": "346896d57731cb5670b36c6178fc5519f3225980"
|
"Rev": "7b85b097bf7527677d54d3220065e966a0e3b613"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context",
|
"ImportPath": "golang.org/x/net/context",
|
||||||
"Rev": "1d9fd3b8333e891c0e7353e1adcfe8a612573033"
|
"Rev": "195180cfebf7362bd243a52477697895128c8777"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/oauth2",
|
"ImportPath": "golang.org/x/oauth2",
|
||||||
|
@ -266,6 +275,10 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "gopkg.in/inf.v0",
|
"ImportPath": "gopkg.in/inf.v0",
|
||||||
"Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
|
"Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "gopkg.in/yaml.v2",
|
||||||
|
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
10
Godeps/_workspace/src/github.com/asaskevich/govalidator/.travis.yml
generated
vendored
Normal file
10
Godeps/_workspace/src/github.com/asaskevich/govalidator/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.1
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
- bwatas@gmail.com
|
21
Godeps/_workspace/src/github.com/asaskevich/govalidator/LICENSE
generated
vendored
Normal file
21
Godeps/_workspace/src/github.com/asaskevich/govalidator/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Alex Saskevich
|
||||||
|
|
||||||
|
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.
|
281
Godeps/_workspace/src/github.com/asaskevich/govalidator/README.md
generated
vendored
Normal file
281
Godeps/_workspace/src/github.com/asaskevich/govalidator/README.md
generated
vendored
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
govalidator
|
||||||
|
===========
|
||||||
|
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![GoDoc](https://godoc.org/github.com/asaskevich/govalidator?status.png)](https://godoc.org/github.com/asaskevich/govalidator) [![Coverage Status](https://img.shields.io/coveralls/asaskevich/govalidator.svg)](https://coveralls.io/r/asaskevich/govalidator?branch=master) [![views](https://sourcegraph.com/api/repos/github.com/asaskevich/govalidator/.counters/views.png)](https://sourcegraph.com/github.com/asaskevich/govalidator)
|
||||||
|
[![wercker status](https://app.wercker.com/status/1ec990b09ea86c910d5f08b0e02c6043/s "wercker status")](https://app.wercker.com/project/bykey/1ec990b09ea86c910d5f08b0e02c6043)
|
||||||
|
[![Build Status](https://travis-ci.org/asaskevich/govalidator.svg?branch=master)](https://travis-ci.org/asaskevich/govalidator)
|
||||||
|
|
||||||
|
A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js).
|
||||||
|
|
||||||
|
#### Installation
|
||||||
|
Make sure that Go is installed on your computer.
|
||||||
|
Type the following command in your terminal:
|
||||||
|
|
||||||
|
go get github.com/asaskevich/govalidator
|
||||||
|
|
||||||
|
After it the package is ready to use.
|
||||||
|
|
||||||
|
#### Import package in your project
|
||||||
|
Add following line in your `*.go` file:
|
||||||
|
```go
|
||||||
|
import "github.com/asaskevich/govalidator"
|
||||||
|
```
|
||||||
|
If you unhappy to use long `govalidator`, you can do something like this:
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
valid "github.com/asaskevich/govalidator"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### List of functions:
|
||||||
|
```go
|
||||||
|
func Abs(value float64) float64
|
||||||
|
func BlackList(str, chars string) string
|
||||||
|
func ByteLength(str string, params ...string) bool
|
||||||
|
func StringLength(str string, params ...string) bool
|
||||||
|
func CamelCaseToUnderscore(str string) string
|
||||||
|
func Contains(str, substring string) bool
|
||||||
|
func Count(array []interface{}, iterator ConditionIterator) int
|
||||||
|
func Each(array []interface{}, iterator Iterator)
|
||||||
|
func ErrorByField(e error, field string) string
|
||||||
|
func Filter(array []interface{}, iterator ConditionIterator) []interface{}
|
||||||
|
func Find(array []interface{}, iterator ConditionIterator) interface{}
|
||||||
|
func GetLine(s string, index int) (string, error)
|
||||||
|
func GetLines(s string) []string
|
||||||
|
func InRange(value, left, right float64) bool
|
||||||
|
func IsASCII(str string) bool
|
||||||
|
func IsAlpha(str string) bool
|
||||||
|
func IsAlphanumeric(str string) bool
|
||||||
|
func IsBase64(str string) bool
|
||||||
|
func IsByteLength(str string, min, max int) bool
|
||||||
|
func IsCreditCard(str string) bool
|
||||||
|
func IsDataURI(str string) bool
|
||||||
|
func IsDivisibleBy(str, num string) bool
|
||||||
|
func IsEmail(str string) bool
|
||||||
|
func IsFilePath(str string) (bool, int)
|
||||||
|
func IsFloat(str string) bool
|
||||||
|
func IsFullWidth(str string) bool
|
||||||
|
func IsHalfWidth(str string) bool
|
||||||
|
func IsHexadecimal(str string) bool
|
||||||
|
func IsHexcolor(str string) bool
|
||||||
|
func IsIP(str string) bool
|
||||||
|
func IsIPv4(str string) bool
|
||||||
|
func IsIPv6(str string) bool
|
||||||
|
func IsISBN(str string, version int) bool
|
||||||
|
func IsISBN10(str string) bool
|
||||||
|
func IsISBN13(str string) bool
|
||||||
|
func IsISO3166Alpha2(str string) bool
|
||||||
|
func IsISO3166Alpha3(str string) bool
|
||||||
|
func IsInt(str string) bool
|
||||||
|
func IsJSON(str string) bool
|
||||||
|
func IsLatitude(str string) bool
|
||||||
|
func IsLongitude(str string) bool
|
||||||
|
func IsLowerCase(str string) bool
|
||||||
|
func IsMAC(str string) bool
|
||||||
|
func IsMongoID(str string) bool
|
||||||
|
func IsMultibyte(str string) bool
|
||||||
|
func IsNatural(value float64) bool
|
||||||
|
func IsNegative(value float64) bool
|
||||||
|
func IsNonNegative(value float64) bool
|
||||||
|
func IsNonPositive(value float64) bool
|
||||||
|
func IsNull(str string) bool
|
||||||
|
func IsNumeric(str string) bool
|
||||||
|
func IsPositive(value float64) bool
|
||||||
|
func IsPrintableASCII(str string) bool
|
||||||
|
func IsRGBcolor(str string) bool
|
||||||
|
func IsRequestURI(rawurl string) bool
|
||||||
|
func IsRequestURL(rawurl string) bool
|
||||||
|
func IsSSN(str string) bool
|
||||||
|
func IsURL(str string) bool
|
||||||
|
func IsUTFDigit(str string) bool
|
||||||
|
func IsUTFLetter(str string) bool
|
||||||
|
func IsUTFLetterNumeric(str string) bool
|
||||||
|
func IsUTFNumeric(str string) bool
|
||||||
|
func IsUUID(str string) bool
|
||||||
|
func IsUUIDv3(str string) bool
|
||||||
|
func IsUUIDv4(str string) bool
|
||||||
|
func IsUUIDv5(str string) bool
|
||||||
|
func IsUpperCase(str string) bool
|
||||||
|
func IsVariableWidth(str string) bool
|
||||||
|
func IsWhole(value float64) bool
|
||||||
|
func LeftTrim(str, chars string) string
|
||||||
|
func Map(array []interface{}, iterator ResultIterator) []interface{}
|
||||||
|
func Matches(str, pattern string) bool
|
||||||
|
func NormalizeEmail(str string) (string, error)
|
||||||
|
func RemoveTags(s string) string
|
||||||
|
func ReplacePattern(str, pattern, replace string) string
|
||||||
|
func Reverse(s string) string
|
||||||
|
func RightTrim(str, chars string) string
|
||||||
|
func SafeFileName(str string) string
|
||||||
|
func Sign(value float64) float64
|
||||||
|
func StripLow(str string, keepNewLines bool) string
|
||||||
|
func ToBoolean(str string) (bool, error)
|
||||||
|
func ToFloat(str string) (float64, error)
|
||||||
|
func ToInt(str string) (int64, error)
|
||||||
|
func ToJSON(obj interface{}) (string, error)
|
||||||
|
func ToString(obj interface{}) string
|
||||||
|
func Trim(str, chars string) string
|
||||||
|
func Truncate(str string, length int, ending string) string
|
||||||
|
func UnderscoreToCamelCase(s string) string
|
||||||
|
func ValidateStruct(s interface{}) (bool, error)
|
||||||
|
func WhiteList(str, chars string) string
|
||||||
|
type ConditionIterator
|
||||||
|
type Error
|
||||||
|
func (e Error) Error() string
|
||||||
|
type Errors
|
||||||
|
func (es Errors) Error() string
|
||||||
|
type ISO3166Entry
|
||||||
|
type Iterator
|
||||||
|
type ParamValidator
|
||||||
|
type ResultIterator
|
||||||
|
type UnsupportedTypeError
|
||||||
|
func (e *UnsupportedTypeError) Error() string
|
||||||
|
type Validator
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
###### IsURL
|
||||||
|
```go
|
||||||
|
println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
|
||||||
|
```
|
||||||
|
###### ToString
|
||||||
|
```go
|
||||||
|
type User struct {
|
||||||
|
FirstName string
|
||||||
|
LastName string
|
||||||
|
}
|
||||||
|
|
||||||
|
str, _ := govalidator.ToString(&User{"John", "Juan"})
|
||||||
|
println(str)
|
||||||
|
```
|
||||||
|
###### Each, Map, Filter, Count for slices
|
||||||
|
Each iterates over the slice/array and calls Iterator for every item
|
||||||
|
```go
|
||||||
|
data := []interface{}{1, 2, 3, 4, 5}
|
||||||
|
var fn govalidator.Iterator = func(value interface{}, index int) {
|
||||||
|
println(value.(int))
|
||||||
|
}
|
||||||
|
govalidator.Each(data, fn)
|
||||||
|
```
|
||||||
|
```go
|
||||||
|
data := []interface{}{1, 2, 3, 4, 5}
|
||||||
|
var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
|
||||||
|
return value.(int) * 3
|
||||||
|
}
|
||||||
|
_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
|
||||||
|
```
|
||||||
|
```go
|
||||||
|
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||||
|
var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
|
||||||
|
return value.(int)%2 == 0
|
||||||
|
}
|
||||||
|
_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
|
||||||
|
_ = govalidator.Count(data, fn) // result = 5
|
||||||
|
```
|
||||||
|
###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2)
|
||||||
|
If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this:
|
||||||
|
```go
|
||||||
|
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
|
||||||
|
return str == "duck"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
Here is a list of available validators for struct fields (validator - used function):
|
||||||
|
```go
|
||||||
|
"alpha": IsAlpha,
|
||||||
|
"alphanum": IsAlphanumeric,
|
||||||
|
"ascii": IsASCII,
|
||||||
|
"base64": IsBase64,
|
||||||
|
"creditcard": IsCreditCard,
|
||||||
|
"datauri": IsDataURI,
|
||||||
|
"email": IsEmail,
|
||||||
|
"float": IsFloat,
|
||||||
|
"fullwidth": IsFullWidth,
|
||||||
|
"halfwidth": IsHalfWidth,
|
||||||
|
"hexadecimal": IsHexadecimal,
|
||||||
|
"hexcolor": IsHexcolor,
|
||||||
|
"int": IsInt,
|
||||||
|
"ip": IsIP,
|
||||||
|
"ipv4": IsIPv4,
|
||||||
|
"ipv6": IsIPv6,
|
||||||
|
"isbn10": IsISBN10,
|
||||||
|
"isbn13": IsISBN13,
|
||||||
|
"json": IsJSON,
|
||||||
|
"latitude": IsLatitude,
|
||||||
|
"longitude": IsLongitude,
|
||||||
|
"lowercase": IsLowerCase,
|
||||||
|
"mac": IsMAC,
|
||||||
|
"multibyte": IsMultibyte,
|
||||||
|
"null": IsNull,
|
||||||
|
"numeric": IsNumeric,
|
||||||
|
"printableascii": IsPrintableASCII,
|
||||||
|
"requri": IsRequestURI,
|
||||||
|
"requrl": IsRequestURL,
|
||||||
|
"rgbcolor": IsRGBcolor,
|
||||||
|
"ssn": IsSSN
|
||||||
|
"uppercase": IsUpperCase,
|
||||||
|
"url": IsURL,
|
||||||
|
"utfdigit": IsUTFDigit,
|
||||||
|
"utfletter": IsUTFLetter,
|
||||||
|
"utfletternum": IsUTFLetterNumeric,
|
||||||
|
"utfnumeric": IsUTFNumeric,
|
||||||
|
"uuid": IsUUID,
|
||||||
|
"uuidv3": IsUUIDv3,
|
||||||
|
"uuidv4": IsUUIDv4,
|
||||||
|
"uuidv5": IsUUIDv5,
|
||||||
|
"variablewidth": IsVariableWidth,
|
||||||
|
```
|
||||||
|
Validators with parameters
|
||||||
|
|
||||||
|
```go
|
||||||
|
"length(min|max)": ByteLength,
|
||||||
|
```
|
||||||
|
|
||||||
|
And here is small example of usage:
|
||||||
|
```go
|
||||||
|
type Post struct {
|
||||||
|
Title string `valid:"alphanum,required"`
|
||||||
|
Message string `valid:"duck,ascii"`
|
||||||
|
AuthorIP string `valid:"ipv4"`
|
||||||
|
Date string `valid:"-"`
|
||||||
|
}
|
||||||
|
post := &Post{
|
||||||
|
Title: "My Example Post",
|
||||||
|
Message: "duck",
|
||||||
|
AuthorIP: "123.234.54.3",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add your own struct validation tags
|
||||||
|
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
|
||||||
|
return str == "duck"
|
||||||
|
})
|
||||||
|
|
||||||
|
result, err := govalidator.ValidateStruct(post)
|
||||||
|
if err != nil {
|
||||||
|
println("error: " + err.Error())
|
||||||
|
}
|
||||||
|
println(result)
|
||||||
|
```
|
||||||
|
###### WhiteList
|
||||||
|
```go
|
||||||
|
// Remove all characters from string ignoring characters between "a" and "z"
|
||||||
|
println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Notes
|
||||||
|
Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator).
|
||||||
|
Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
|
||||||
|
|
||||||
|
#### Support
|
||||||
|
If you do have a contribution for the package feel free to put up a Pull Request or open Issue.
|
||||||
|
|
||||||
|
#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
|
||||||
|
* [Attila Oláh](https://github.com/attilaolah)
|
||||||
|
* [Daniel Korner](https://github.com/Dadie)
|
||||||
|
* [Steven Wilkin](https://github.com/stevenwilkin)
|
||||||
|
* [Deiwin Sarjas](https://github.com/deiwin)
|
||||||
|
* [Noah Shibley](https://github.com/slugmobile)
|
||||||
|
* [Nathan Davies](https://github.com/nathj07)
|
||||||
|
* [Matt Sanford](https://github.com/mzsanford)
|
||||||
|
* [Simon ccl1115](https://github.com/ccl1115)
|
||||||
|
|
||||||
|
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/asaskevich/govalidator/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
||||||
|
|
58
Godeps/_workspace/src/github.com/asaskevich/govalidator/arrays.go
generated
vendored
Normal file
58
Godeps/_workspace/src/github.com/asaskevich/govalidator/arrays.go
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
// Iterator is the function that accepts element of slice/array and its index
|
||||||
|
type Iterator func(interface{}, int)
|
||||||
|
|
||||||
|
// ResultIterator is the function that accepts element of slice/array and its index and returns any result
|
||||||
|
type ResultIterator func(interface{}, int) interface{}
|
||||||
|
|
||||||
|
// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean
|
||||||
|
type ConditionIterator func(interface{}, int) bool
|
||||||
|
|
||||||
|
// Each iterates over the slice and apply Iterator to every item
|
||||||
|
func Each(array []interface{}, iterator Iterator) {
|
||||||
|
for index, data := range array {
|
||||||
|
iterator(data, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result.
|
||||||
|
func Map(array []interface{}, iterator ResultIterator) []interface{} {
|
||||||
|
var result []interface{} = make([]interface{}, len(array))
|
||||||
|
for index, data := range array {
|
||||||
|
result[index] = iterator(data, index)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise.
|
||||||
|
func Find(array []interface{}, iterator ConditionIterator) interface{} {
|
||||||
|
for index, data := range array {
|
||||||
|
if iterator(data, index) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice.
|
||||||
|
func Filter(array []interface{}, iterator ConditionIterator) []interface{} {
|
||||||
|
var result []interface{} = make([]interface{}, 0)
|
||||||
|
for index, data := range array {
|
||||||
|
if iterator(data, index) {
|
||||||
|
result = append(result, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator.
|
||||||
|
func Count(array []interface{}, iterator ConditionIterator) int {
|
||||||
|
count := 0
|
||||||
|
for index, data := range array {
|
||||||
|
if iterator(data, index) {
|
||||||
|
count = count + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
49
Godeps/_workspace/src/github.com/asaskevich/govalidator/converter.go
generated
vendored
Normal file
49
Godeps/_workspace/src/github.com/asaskevich/govalidator/converter.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToString convert the input to a string.
|
||||||
|
func ToString(obj interface{}) string {
|
||||||
|
res := fmt.Sprintf("%v", obj)
|
||||||
|
return string(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON convert the input to a valid JSON string
|
||||||
|
func ToJSON(obj interface{}) (string, error) {
|
||||||
|
res, err := json.Marshal(obj)
|
||||||
|
if err != nil {
|
||||||
|
res = []byte("")
|
||||||
|
}
|
||||||
|
return string(res), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToFloat convert the input string to a float, or 0.0 if the input is not a float.
|
||||||
|
func ToFloat(str string) (float64, error) {
|
||||||
|
res, err := strconv.ParseFloat(str, 64)
|
||||||
|
if err != nil {
|
||||||
|
res = 0.0
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToInt convert the input string to an integer, or 0 if the input is not an integer.
|
||||||
|
func ToInt(str string) (int64, error) {
|
||||||
|
res, err := strconv.ParseInt(str, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
res = 0
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToBoolean convert the input string to a boolean.
|
||||||
|
func ToBoolean(str string) (bool, error) {
|
||||||
|
res, err := strconv.ParseBool(str)
|
||||||
|
if err != nil {
|
||||||
|
res = false
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
24
Godeps/_workspace/src/github.com/asaskevich/govalidator/error.go
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/asaskevich/govalidator/error.go
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
type Errors []error
|
||||||
|
|
||||||
|
func (es Errors) Errors() []error {
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es Errors) Error() string {
|
||||||
|
var err string
|
||||||
|
for _, e := range es {
|
||||||
|
err += e.Error() + ";"
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Name string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Error) Error() string {
|
||||||
|
return e.Name + ": " + e.Err.Error()
|
||||||
|
}
|
57
Godeps/_workspace/src/github.com/asaskevich/govalidator/numerics.go
generated
vendored
Normal file
57
Godeps/_workspace/src/github.com/asaskevich/govalidator/numerics.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// Abs returns absolute value of number
|
||||||
|
func Abs(value float64) float64 {
|
||||||
|
return value * Sign(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise
|
||||||
|
func Sign(value float64) float64 {
|
||||||
|
if value > 0 {
|
||||||
|
return 1
|
||||||
|
} else if value < 0 {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNegative returns true if value < 0
|
||||||
|
func IsNegative(value float64) bool {
|
||||||
|
return value < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPositive returns true if value > 0
|
||||||
|
func IsPositive(value float64) bool {
|
||||||
|
return value > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNonNegative returns true if value >= 0
|
||||||
|
func IsNonNegative(value float64) bool {
|
||||||
|
return value >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNonPositive returns true if value <= 0
|
||||||
|
func IsNonPositive(value float64) bool {
|
||||||
|
return value <= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// InRange returns true if value lies between left and right border
|
||||||
|
func InRange(value, left, right float64) bool {
|
||||||
|
if left > right {
|
||||||
|
left, right = right, left
|
||||||
|
}
|
||||||
|
return value >= left && value <= right
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsWhole returns true if value is whole number
|
||||||
|
func IsWhole(value float64) bool {
|
||||||
|
return Abs(math.Remainder(value, 1)) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNatural returns true if value is natural number (positive and whole)
|
||||||
|
func IsNatural(value float64) bool {
|
||||||
|
return IsWhole(value) && IsPositive(value)
|
||||||
|
}
|
79
Godeps/_workspace/src/github.com/asaskevich/govalidator/patterns.go
generated
vendored
Normal file
79
Godeps/_workspace/src/github.com/asaskevich/govalidator/patterns.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
// Basic regular expressions for validating strings
|
||||||
|
const (
|
||||||
|
Email string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
|
||||||
|
CreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$"
|
||||||
|
ISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$"
|
||||||
|
ISBN13 string = "^(?:[0-9]{13})$"
|
||||||
|
UUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||||
|
UUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
||||||
|
UUID5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
|
||||||
|
UUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||||
|
Alpha string = "^[a-zA-Z]+$"
|
||||||
|
Alphanumeric string = "^[a-zA-Z0-9]+$"
|
||||||
|
Numeric string = "^[-+]?[0-9]+$"
|
||||||
|
Int string = "^(?:[-+]?(?:0|[1-9][0-9]*))$"
|
||||||
|
Float string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$"
|
||||||
|
Hexadecimal string = "^[0-9a-fA-F]+$"
|
||||||
|
Hexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
|
||||||
|
RGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
|
||||||
|
ASCII string = "^[\x00-\x7F]+$"
|
||||||
|
Multibyte string = "[^\x00-\x7F]"
|
||||||
|
FullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
|
||||||
|
HalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
|
||||||
|
Base64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
|
||||||
|
PrintableASCII string = "^[\x20-\x7E]+$"
|
||||||
|
DataURI string = "^data:.+\\/(.+);base64$"
|
||||||
|
Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
||||||
|
Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
||||||
|
URL string = `^((ftp|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`
|
||||||
|
SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
|
||||||
|
WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
|
||||||
|
UnixPath string = `^((?:\/[a-zA-Z0-9\.\:]+(?:_[a-zA-Z0-9\:\.]+)*(?:\-[\:a-zA-Z0-9\.]+)*)+\/?)$`
|
||||||
|
tagName string = "valid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Used by IsFilePath func
|
||||||
|
const (
|
||||||
|
// Unknown is unresolved OS type
|
||||||
|
Unknown = iota
|
||||||
|
// Win is Windows type
|
||||||
|
Win
|
||||||
|
// Unix is *nix OS types
|
||||||
|
Unix
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rxEmail = regexp.MustCompile(Email)
|
||||||
|
rxCreditCard = regexp.MustCompile(CreditCard)
|
||||||
|
rxISBN10 = regexp.MustCompile(ISBN10)
|
||||||
|
rxISBN13 = regexp.MustCompile(ISBN13)
|
||||||
|
rxUUID3 = regexp.MustCompile(UUID3)
|
||||||
|
rxUUID4 = regexp.MustCompile(UUID4)
|
||||||
|
rxUUID5 = regexp.MustCompile(UUID5)
|
||||||
|
rxUUID = regexp.MustCompile(UUID)
|
||||||
|
rxAlpha = regexp.MustCompile(Alpha)
|
||||||
|
rxAlphanumeric = regexp.MustCompile(Alphanumeric)
|
||||||
|
rxNumeric = regexp.MustCompile(Numeric)
|
||||||
|
rxInt = regexp.MustCompile(Int)
|
||||||
|
rxFloat = regexp.MustCompile(Float)
|
||||||
|
rxHexadecimal = regexp.MustCompile(Hexadecimal)
|
||||||
|
rxHexcolor = regexp.MustCompile(Hexcolor)
|
||||||
|
rxRGBcolor = regexp.MustCompile(RGBcolor)
|
||||||
|
rxASCII = regexp.MustCompile(ASCII)
|
||||||
|
rxPrintableASCII = regexp.MustCompile(PrintableASCII)
|
||||||
|
rxMultibyte = regexp.MustCompile(Multibyte)
|
||||||
|
rxFullWidth = regexp.MustCompile(FullWidth)
|
||||||
|
rxHalfWidth = regexp.MustCompile(HalfWidth)
|
||||||
|
rxBase64 = regexp.MustCompile(Base64)
|
||||||
|
rxDataURI = regexp.MustCompile(DataURI)
|
||||||
|
rxLatitude = regexp.MustCompile(Latitude)
|
||||||
|
rxLongitude = regexp.MustCompile(Longitude)
|
||||||
|
rxURL = regexp.MustCompile(URL)
|
||||||
|
rxSSN = regexp.MustCompile(SSN)
|
||||||
|
rxWinPath = regexp.MustCompile(WinPath)
|
||||||
|
rxUnixPath = regexp.MustCompile(UnixPath)
|
||||||
|
)
|
349
Godeps/_workspace/src/github.com/asaskevich/govalidator/types.go
generated
vendored
Normal file
349
Godeps/_workspace/src/github.com/asaskevich/govalidator/types.go
generated
vendored
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Validator is a wrapper for a validator function that returns bool and accepts string.
|
||||||
|
type Validator func(str string) bool
|
||||||
|
|
||||||
|
// CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type.
|
||||||
|
type CustomTypeValidator func(i interface{}) bool
|
||||||
|
|
||||||
|
// ParamValidator is a wrapper for validator functions that accepts additional parameters.
|
||||||
|
type ParamValidator func(str string, params ...string) bool
|
||||||
|
type tagOptions []string
|
||||||
|
|
||||||
|
// UnsupportedTypeError is a wrapper for reflect.Type
|
||||||
|
type UnsupportedTypeError struct {
|
||||||
|
Type reflect.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
|
||||||
|
// It implements the methods to sort by string.
|
||||||
|
type stringValues []reflect.Value
|
||||||
|
|
||||||
|
// ParamTagMap is a map of functions accept variants parameters
|
||||||
|
var ParamTagMap = map[string]ParamValidator{
|
||||||
|
"length": ByteLength,
|
||||||
|
"stringlength": StringLength,
|
||||||
|
}
|
||||||
|
|
||||||
|
var ParamTagRegexMap = map[string]*regexp.Regexp{
|
||||||
|
"length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"),
|
||||||
|
"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function.
|
||||||
|
// Use this to validate compound or custom types that need to be handled as a whole, e.g.
|
||||||
|
// `type UUID [16]byte` (this would be handled as an array of bytes).
|
||||||
|
var CustomTypeTagMap = map[string]CustomTypeValidator{}
|
||||||
|
|
||||||
|
// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
|
||||||
|
var TagMap = map[string]Validator{
|
||||||
|
"email": IsEmail,
|
||||||
|
"url": IsURL,
|
||||||
|
"requrl": IsRequestURL,
|
||||||
|
"requri": IsRequestURI,
|
||||||
|
"alpha": IsAlpha,
|
||||||
|
"utfletter": IsUTFLetter,
|
||||||
|
"alphanum": IsAlphanumeric,
|
||||||
|
"utfletternum": IsUTFLetterNumeric,
|
||||||
|
"numeric": IsNumeric,
|
||||||
|
"utfnumeric": IsUTFNumeric,
|
||||||
|
"utfdigit": IsUTFDigit,
|
||||||
|
"hexadecimal": IsHexadecimal,
|
||||||
|
"hexcolor": IsHexcolor,
|
||||||
|
"rgbcolor": IsRGBcolor,
|
||||||
|
"lowercase": IsLowerCase,
|
||||||
|
"uppercase": IsUpperCase,
|
||||||
|
"int": IsInt,
|
||||||
|
"float": IsFloat,
|
||||||
|
"null": IsNull,
|
||||||
|
"uuid": IsUUID,
|
||||||
|
"uuidv3": IsUUIDv3,
|
||||||
|
"uuidv4": IsUUIDv4,
|
||||||
|
"uuidv5": IsUUIDv5,
|
||||||
|
"creditcard": IsCreditCard,
|
||||||
|
"isbn10": IsISBN10,
|
||||||
|
"isbn13": IsISBN13,
|
||||||
|
"json": IsJSON,
|
||||||
|
"multibyte": IsMultibyte,
|
||||||
|
"ascii": IsASCII,
|
||||||
|
"printableascii": IsPrintableASCII,
|
||||||
|
"fullwidth": IsFullWidth,
|
||||||
|
"halfwidth": IsHalfWidth,
|
||||||
|
"variablewidth": IsVariableWidth,
|
||||||
|
"base64": IsBase64,
|
||||||
|
"datauri": IsDataURI,
|
||||||
|
"ip": IsIP,
|
||||||
|
"ipv4": IsIPv4,
|
||||||
|
"ipv6": IsIPv6,
|
||||||
|
"mac": IsMAC,
|
||||||
|
"latitude": IsLatitude,
|
||||||
|
"longitude": IsLongitude,
|
||||||
|
"ssn": IsSSN,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISO3166Entry stores country codes
|
||||||
|
type ISO3166Entry struct {
|
||||||
|
EnglishShortName string
|
||||||
|
FrenchShortName string
|
||||||
|
Alpha2Code string
|
||||||
|
Alpha3Code string
|
||||||
|
Numeric string
|
||||||
|
}
|
||||||
|
|
||||||
|
//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes"
|
||||||
|
var ISO3166List = []ISO3166Entry{
|
||||||
|
{"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"},
|
||||||
|
{"Albania", "Albanie (l')", "AL", "ALB", "008"},
|
||||||
|
{"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"},
|
||||||
|
{"Algeria", "Algérie (l')", "DZ", "DZA", "012"},
|
||||||
|
{"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"},
|
||||||
|
{"Andorra", "Andorre (l')", "AD", "AND", "020"},
|
||||||
|
{"Angola", "Angola (l')", "AO", "AGO", "024"},
|
||||||
|
{"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"},
|
||||||
|
{"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"},
|
||||||
|
{"Argentina", "Argentine (l')", "AR", "ARG", "032"},
|
||||||
|
{"Australia", "Australie (l')", "AU", "AUS", "036"},
|
||||||
|
{"Austria", "Autriche (l')", "AT", "AUT", "040"},
|
||||||
|
{"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"},
|
||||||
|
{"Bahrain", "Bahreïn", "BH", "BHR", "048"},
|
||||||
|
{"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"},
|
||||||
|
{"Armenia", "Arménie (l')", "AM", "ARM", "051"},
|
||||||
|
{"Barbados", "Barbade (la)", "BB", "BRB", "052"},
|
||||||
|
{"Belgium", "Belgique (la)", "BE", "BEL", "056"},
|
||||||
|
{"Bermuda", "Bermudes (les)", "BM", "BMU", "060"},
|
||||||
|
{"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"},
|
||||||
|
{"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"},
|
||||||
|
{"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"},
|
||||||
|
{"Botswana", "Botswana (le)", "BW", "BWA", "072"},
|
||||||
|
{"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"},
|
||||||
|
{"Brazil", "Brésil (le)", "BR", "BRA", "076"},
|
||||||
|
{"Belize", "Belize (le)", "BZ", "BLZ", "084"},
|
||||||
|
{"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"},
|
||||||
|
{"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"},
|
||||||
|
{"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"},
|
||||||
|
{"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"},
|
||||||
|
{"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"},
|
||||||
|
{"Myanmar", "Myanmar (le)", "MM", "MMR", "104"},
|
||||||
|
{"Burundi", "Burundi (le)", "BI", "BDI", "108"},
|
||||||
|
{"Belarus", "Bélarus (le)", "BY", "BLR", "112"},
|
||||||
|
{"Cambodia", "Cambodge (le)", "KH", "KHM", "116"},
|
||||||
|
{"Cameroon", "Cameroun (le)", "CM", "CMR", "120"},
|
||||||
|
{"Canada", "Canada (le)", "CA", "CAN", "124"},
|
||||||
|
{"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"},
|
||||||
|
{"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"},
|
||||||
|
{"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"},
|
||||||
|
{"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"},
|
||||||
|
{"Chad", "Tchad (le)", "TD", "TCD", "148"},
|
||||||
|
{"Chile", "Chili (le)", "CL", "CHL", "152"},
|
||||||
|
{"China", "Chine (la)", "CN", "CHN", "156"},
|
||||||
|
{"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"},
|
||||||
|
{"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"},
|
||||||
|
{"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"},
|
||||||
|
{"Colombia", "Colombie (la)", "CO", "COL", "170"},
|
||||||
|
{"Comoros (the)", "Comores (les)", "KM", "COM", "174"},
|
||||||
|
{"Mayotte", "Mayotte", "YT", "MYT", "175"},
|
||||||
|
{"Congo (the)", "Congo (le)", "CG", "COG", "178"},
|
||||||
|
{"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"},
|
||||||
|
{"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"},
|
||||||
|
{"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"},
|
||||||
|
{"Croatia", "Croatie (la)", "HR", "HRV", "191"},
|
||||||
|
{"Cuba", "Cuba", "CU", "CUB", "192"},
|
||||||
|
{"Cyprus", "Chypre", "CY", "CYP", "196"},
|
||||||
|
{"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"},
|
||||||
|
{"Benin", "Bénin (le)", "BJ", "BEN", "204"},
|
||||||
|
{"Denmark", "Danemark (le)", "DK", "DNK", "208"},
|
||||||
|
{"Dominica", "Dominique (la)", "DM", "DMA", "212"},
|
||||||
|
{"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"},
|
||||||
|
{"Ecuador", "Équateur (l')", "EC", "ECU", "218"},
|
||||||
|
{"El Salvador", "El Salvador", "SV", "SLV", "222"},
|
||||||
|
{"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"},
|
||||||
|
{"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"},
|
||||||
|
{"Eritrea", "Érythrée (l')", "ER", "ERI", "232"},
|
||||||
|
{"Estonia", "Estonie (l')", "EE", "EST", "233"},
|
||||||
|
{"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"},
|
||||||
|
{"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"},
|
||||||
|
{"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"},
|
||||||
|
{"Fiji", "Fidji (les)", "FJ", "FJI", "242"},
|
||||||
|
{"Finland", "Finlande (la)", "FI", "FIN", "246"},
|
||||||
|
{"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"},
|
||||||
|
{"France", "France (la)", "FR", "FRA", "250"},
|
||||||
|
{"French Guiana", "Guyane française (la )", "GF", "GUF", "254"},
|
||||||
|
{"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"},
|
||||||
|
{"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"},
|
||||||
|
{"Djibouti", "Djibouti", "DJ", "DJI", "262"},
|
||||||
|
{"Gabon", "Gabon (le)", "GA", "GAB", "266"},
|
||||||
|
{"Georgia", "Géorgie (la)", "GE", "GEO", "268"},
|
||||||
|
{"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"},
|
||||||
|
{"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"},
|
||||||
|
{"Germany", "Allemagne (l')", "DE", "DEU", "276"},
|
||||||
|
{"Ghana", "Ghana (le)", "GH", "GHA", "288"},
|
||||||
|
{"Gibraltar", "Gibraltar", "GI", "GIB", "292"},
|
||||||
|
{"Kiribati", "Kiribati", "KI", "KIR", "296"},
|
||||||
|
{"Greece", "Grèce (la)", "GR", "GRC", "300"},
|
||||||
|
{"Greenland", "Groenland (le)", "GL", "GRL", "304"},
|
||||||
|
{"Grenada", "Grenade (la)", "GD", "GRD", "308"},
|
||||||
|
{"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"},
|
||||||
|
{"Guam", "Guam", "GU", "GUM", "316"},
|
||||||
|
{"Guatemala", "Guatemala (le)", "GT", "GTM", "320"},
|
||||||
|
{"Guinea", "Guinée (la)", "GN", "GIN", "324"},
|
||||||
|
{"Guyana", "Guyana (le)", "GY", "GUY", "328"},
|
||||||
|
{"Haiti", "Haïti", "HT", "HTI", "332"},
|
||||||
|
{"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"},
|
||||||
|
{"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"},
|
||||||
|
{"Honduras", "Honduras (le)", "HN", "HND", "340"},
|
||||||
|
{"Hong Kong", "Hong Kong", "HK", "HKG", "344"},
|
||||||
|
{"Hungary", "Hongrie (la)", "HU", "HUN", "348"},
|
||||||
|
{"Iceland", "Islande (l')", "IS", "ISL", "352"},
|
||||||
|
{"India", "Inde (l')", "IN", "IND", "356"},
|
||||||
|
{"Indonesia", "Indonésie (l')", "ID", "IDN", "360"},
|
||||||
|
{"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"},
|
||||||
|
{"Iraq", "Iraq (l')", "IQ", "IRQ", "368"},
|
||||||
|
{"Ireland", "Irlande (l')", "IE", "IRL", "372"},
|
||||||
|
{"Israel", "Israël", "IL", "ISR", "376"},
|
||||||
|
{"Italy", "Italie (l')", "IT", "ITA", "380"},
|
||||||
|
{"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"},
|
||||||
|
{"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"},
|
||||||
|
{"Japan", "Japon (le)", "JP", "JPN", "392"},
|
||||||
|
{"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"},
|
||||||
|
{"Jordan", "Jordanie (la)", "JO", "JOR", "400"},
|
||||||
|
{"Kenya", "Kenya (le)", "KE", "KEN", "404"},
|
||||||
|
{"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"},
|
||||||
|
{"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"},
|
||||||
|
{"Kuwait", "Koweït (le)", "KW", "KWT", "414"},
|
||||||
|
{"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"},
|
||||||
|
{"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"},
|
||||||
|
{"Lebanon", "Liban (le)", "LB", "LBN", "422"},
|
||||||
|
{"Lesotho", "Lesotho (le)", "LS", "LSO", "426"},
|
||||||
|
{"Latvia", "Lettonie (la)", "LV", "LVA", "428"},
|
||||||
|
{"Liberia", "Libéria (le)", "LR", "LBR", "430"},
|
||||||
|
{"Libya", "Libye (la)", "LY", "LBY", "434"},
|
||||||
|
{"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"},
|
||||||
|
{"Lithuania", "Lituanie (la)", "LT", "LTU", "440"},
|
||||||
|
{"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"},
|
||||||
|
{"Macao", "Macao", "MO", "MAC", "446"},
|
||||||
|
{"Madagascar", "Madagascar", "MG", "MDG", "450"},
|
||||||
|
{"Malawi", "Malawi (le)", "MW", "MWI", "454"},
|
||||||
|
{"Malaysia", "Malaisie (la)", "MY", "MYS", "458"},
|
||||||
|
{"Maldives", "Maldives (les)", "MV", "MDV", "462"},
|
||||||
|
{"Mali", "Mali (le)", "ML", "MLI", "466"},
|
||||||
|
{"Malta", "Malte", "MT", "MLT", "470"},
|
||||||
|
{"Martinique", "Martinique (la)", "MQ", "MTQ", "474"},
|
||||||
|
{"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"},
|
||||||
|
{"Mauritius", "Maurice", "MU", "MUS", "480"},
|
||||||
|
{"Mexico", "Mexique (le)", "MX", "MEX", "484"},
|
||||||
|
{"Monaco", "Monaco", "MC", "MCO", "492"},
|
||||||
|
{"Mongolia", "Mongolie (la)", "MN", "MNG", "496"},
|
||||||
|
{"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"},
|
||||||
|
{"Montenegro", "Monténégro (le)", "ME", "MNE", "499"},
|
||||||
|
{"Montserrat", "Montserrat", "MS", "MSR", "500"},
|
||||||
|
{"Morocco", "Maroc (le)", "MA", "MAR", "504"},
|
||||||
|
{"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"},
|
||||||
|
{"Oman", "Oman", "OM", "OMN", "512"},
|
||||||
|
{"Namibia", "Namibie (la)", "NA", "NAM", "516"},
|
||||||
|
{"Nauru", "Nauru", "NR", "NRU", "520"},
|
||||||
|
{"Nepal", "Népal (le)", "NP", "NPL", "524"},
|
||||||
|
{"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"},
|
||||||
|
{"Curaçao", "Curaçao", "CW", "CUW", "531"},
|
||||||
|
{"Aruba", "Aruba", "AW", "ABW", "533"},
|
||||||
|
{"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"},
|
||||||
|
{"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"},
|
||||||
|
{"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"},
|
||||||
|
{"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"},
|
||||||
|
{"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"},
|
||||||
|
{"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"},
|
||||||
|
{"Niger (the)", "Niger (le)", "NE", "NER", "562"},
|
||||||
|
{"Nigeria", "Nigéria (le)", "NG", "NGA", "566"},
|
||||||
|
{"Niue", "Niue", "NU", "NIU", "570"},
|
||||||
|
{"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"},
|
||||||
|
{"Norway", "Norvège (la)", "NO", "NOR", "578"},
|
||||||
|
{"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"},
|
||||||
|
{"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"},
|
||||||
|
{"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"},
|
||||||
|
{"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"},
|
||||||
|
{"Palau", "Palaos (les)", "PW", "PLW", "585"},
|
||||||
|
{"Pakistan", "Pakistan (le)", "PK", "PAK", "586"},
|
||||||
|
{"Panama", "Panama (le)", "PA", "PAN", "591"},
|
||||||
|
{"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"},
|
||||||
|
{"Paraguay", "Paraguay (le)", "PY", "PRY", "600"},
|
||||||
|
{"Peru", "Pérou (le)", "PE", "PER", "604"},
|
||||||
|
{"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"},
|
||||||
|
{"Pitcairn", "Pitcairn", "PN", "PCN", "612"},
|
||||||
|
{"Poland", "Pologne (la)", "PL", "POL", "616"},
|
||||||
|
{"Portugal", "Portugal (le)", "PT", "PRT", "620"},
|
||||||
|
{"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"},
|
||||||
|
{"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"},
|
||||||
|
{"Puerto Rico", "Porto Rico", "PR", "PRI", "630"},
|
||||||
|
{"Qatar", "Qatar (le)", "QA", "QAT", "634"},
|
||||||
|
{"Réunion", "Réunion (La)", "RE", "REU", "638"},
|
||||||
|
{"Romania", "Roumanie (la)", "RO", "ROU", "642"},
|
||||||
|
{"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"},
|
||||||
|
{"Rwanda", "Rwanda (le)", "RW", "RWA", "646"},
|
||||||
|
{"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"},
|
||||||
|
{"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"},
|
||||||
|
{"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"},
|
||||||
|
{"Anguilla", "Anguilla", "AI", "AIA", "660"},
|
||||||
|
{"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"},
|
||||||
|
{"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"},
|
||||||
|
{"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"},
|
||||||
|
{"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"},
|
||||||
|
{"San Marino", "Saint-Marin", "SM", "SMR", "674"},
|
||||||
|
{"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"},
|
||||||
|
{"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"},
|
||||||
|
{"Senegal", "Sénégal (le)", "SN", "SEN", "686"},
|
||||||
|
{"Serbia", "Serbie (la)", "RS", "SRB", "688"},
|
||||||
|
{"Seychelles", "Seychelles (les)", "SC", "SYC", "690"},
|
||||||
|
{"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"},
|
||||||
|
{"Singapore", "Singapour", "SG", "SGP", "702"},
|
||||||
|
{"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"},
|
||||||
|
{"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"},
|
||||||
|
{"Slovenia", "Slovénie (la)", "SI", "SVN", "705"},
|
||||||
|
{"Somalia", "Somalie (la)", "SO", "SOM", "706"},
|
||||||
|
{"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"},
|
||||||
|
{"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"},
|
||||||
|
{"Spain", "Espagne (l')", "ES", "ESP", "724"},
|
||||||
|
{"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"},
|
||||||
|
{"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"},
|
||||||
|
{"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"},
|
||||||
|
{"Suriname", "Suriname (le)", "SR", "SUR", "740"},
|
||||||
|
{"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"},
|
||||||
|
{"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"},
|
||||||
|
{"Sweden", "Suède (la)", "SE", "SWE", "752"},
|
||||||
|
{"Switzerland", "Suisse (la)", "CH", "CHE", "756"},
|
||||||
|
{"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"},
|
||||||
|
{"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"},
|
||||||
|
{"Thailand", "Thaïlande (la)", "TH", "THA", "764"},
|
||||||
|
{"Togo", "Togo (le)", "TG", "TGO", "768"},
|
||||||
|
{"Tokelau", "Tokelau (les)", "TK", "TKL", "772"},
|
||||||
|
{"Tonga", "Tonga (les)", "TO", "TON", "776"},
|
||||||
|
{"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"},
|
||||||
|
{"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"},
|
||||||
|
{"Tunisia", "Tunisie (la)", "TN", "TUN", "788"},
|
||||||
|
{"Turkey", "Turquie (la)", "TR", "TUR", "792"},
|
||||||
|
{"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"},
|
||||||
|
{"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"},
|
||||||
|
{"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"},
|
||||||
|
{"Uganda", "Ouganda (l')", "UG", "UGA", "800"},
|
||||||
|
{"Ukraine", "Ukraine (l')", "UA", "UKR", "804"},
|
||||||
|
{"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'ex‑République yougoslave de)", "MK", "MKD", "807"},
|
||||||
|
{"Egypt", "Égypte (l')", "EG", "EGY", "818"},
|
||||||
|
{"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"},
|
||||||
|
{"Guernsey", "Guernesey", "GG", "GGY", "831"},
|
||||||
|
{"Jersey", "Jersey", "JE", "JEY", "832"},
|
||||||
|
{"Isle of Man", "Île de Man", "IM", "IMN", "833"},
|
||||||
|
{"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"},
|
||||||
|
{"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"},
|
||||||
|
{"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"},
|
||||||
|
{"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"},
|
||||||
|
{"Uruguay", "Uruguay (l')", "UY", "URY", "858"},
|
||||||
|
{"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"},
|
||||||
|
{"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"},
|
||||||
|
{"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"},
|
||||||
|
{"Samoa", "Samoa (le)", "WS", "WSM", "882"},
|
||||||
|
{"Yemen", "Yémen (le)", "YE", "YEM", "887"},
|
||||||
|
{"Zambia", "Zambie (la)", "ZM", "ZMB", "894"},
|
||||||
|
}
|
214
Godeps/_workspace/src/github.com/asaskevich/govalidator/utils.go
generated
vendored
Normal file
214
Godeps/_workspace/src/github.com/asaskevich/govalidator/utils.go
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"html"
|
||||||
|
"path"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Contains check if the string contains the substring.
|
||||||
|
func Contains(str, substring string) bool {
|
||||||
|
return strings.Contains(str, substring)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches check if string matches the pattern (pattern is regular expression)
|
||||||
|
// In case of error return false
|
||||||
|
func Matches(str, pattern string) bool {
|
||||||
|
match, _ := regexp.MatchString(pattern, str)
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftTrim trim characters from the left-side of the input.
|
||||||
|
// If second argument is empty, it's will be remove leading spaces.
|
||||||
|
func LeftTrim(str, chars string) string {
|
||||||
|
pattern := ""
|
||||||
|
if chars == "" {
|
||||||
|
pattern = "^\\s+"
|
||||||
|
} else {
|
||||||
|
pattern = "^[" + chars + "]+"
|
||||||
|
}
|
||||||
|
r, _ := regexp.Compile(pattern)
|
||||||
|
return string(r.ReplaceAll([]byte(str), []byte("")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RightTrim trim characters from the right-side of the input.
|
||||||
|
// If second argument is empty, it's will be remove spaces.
|
||||||
|
func RightTrim(str, chars string) string {
|
||||||
|
pattern := ""
|
||||||
|
if chars == "" {
|
||||||
|
pattern = "\\s+$"
|
||||||
|
} else {
|
||||||
|
pattern = "[" + chars + "]+$"
|
||||||
|
}
|
||||||
|
r, _ := regexp.Compile(pattern)
|
||||||
|
return string(r.ReplaceAll([]byte(str), []byte("")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim trim characters from both sides of the input.
|
||||||
|
// If second argument is empty, it's will be remove spaces.
|
||||||
|
func Trim(str, chars string) string {
|
||||||
|
return LeftTrim(RightTrim(str, chars), chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhiteList remove characters that do not appear in the whitelist.
|
||||||
|
func WhiteList(str, chars string) string {
|
||||||
|
pattern := "[^" + chars + "]+"
|
||||||
|
r, _ := regexp.Compile(pattern)
|
||||||
|
return string(r.ReplaceAll([]byte(str), []byte("")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlackList remove characters that appear in the blacklist.
|
||||||
|
func BlackList(str, chars string) string {
|
||||||
|
pattern := "[" + chars + "]+"
|
||||||
|
r, _ := regexp.Compile(pattern)
|
||||||
|
return string(r.ReplaceAll([]byte(str), []byte("")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StripLow remove characters with a numerical value < 32 and 127, mostly control characters.
|
||||||
|
// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
|
||||||
|
func StripLow(str string, keepNewLines bool) string {
|
||||||
|
chars := ""
|
||||||
|
if keepNewLines {
|
||||||
|
chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
|
||||||
|
} else {
|
||||||
|
chars = "\x00-\x1F\x7F"
|
||||||
|
}
|
||||||
|
return BlackList(str, chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplacePattern replace regular expression pattern in string
|
||||||
|
func ReplacePattern(str, pattern, replace string) string {
|
||||||
|
r, _ := regexp.Compile(pattern)
|
||||||
|
return string(r.ReplaceAll([]byte(str), []byte(replace)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape replace <, >, & and " with HTML entities.
|
||||||
|
var Escape = html.EscapeString
|
||||||
|
|
||||||
|
func addSegment(inrune, segment []rune) []rune {
|
||||||
|
if len(segment) == 0 {
|
||||||
|
return inrune
|
||||||
|
}
|
||||||
|
if len(inrune) != 0 {
|
||||||
|
inrune = append(inrune, '_')
|
||||||
|
}
|
||||||
|
inrune = append(inrune, segment...)
|
||||||
|
return inrune
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnderscoreToCamelCase converts from underscore separated form to camel case form.
|
||||||
|
// Ex.: my_func => MyFunc
|
||||||
|
func UnderscoreToCamelCase(s string) string {
|
||||||
|
return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CamelCaseToUnderscore converts from camel case form to underscore separated form.
|
||||||
|
// Ex.: MyFunc => my_func
|
||||||
|
func CamelCaseToUnderscore(str string) string {
|
||||||
|
var output []rune
|
||||||
|
var segment []rune
|
||||||
|
for _, r := range str {
|
||||||
|
if !unicode.IsLower(r) {
|
||||||
|
output = addSegment(output, segment)
|
||||||
|
segment = nil
|
||||||
|
}
|
||||||
|
segment = append(segment, unicode.ToLower(r))
|
||||||
|
}
|
||||||
|
output = addSegment(output, segment)
|
||||||
|
return string(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse return reversed string
|
||||||
|
func Reverse(s string) string {
|
||||||
|
r := []rune(s)
|
||||||
|
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
r[i], r[j] = r[j], r[i]
|
||||||
|
}
|
||||||
|
return string(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLines split string by "\n" and return array of lines
|
||||||
|
func GetLines(s string) []string {
|
||||||
|
return strings.Split(s, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLine return specified line of multiline string
|
||||||
|
func GetLine(s string, index int) (string, error) {
|
||||||
|
lines := GetLines(s)
|
||||||
|
if index < 0 || index >= len(lines) {
|
||||||
|
return "", errors.New("line index out of bounds")
|
||||||
|
}
|
||||||
|
return lines[index], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTags remove all tags from HTML string
|
||||||
|
func RemoveTags(s string) string {
|
||||||
|
return ReplacePattern(s, "<[^>]*>", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeFileName return safe string that can be used in file names
|
||||||
|
func SafeFileName(str string) string {
|
||||||
|
name := strings.ToLower(str)
|
||||||
|
name = path.Clean(path.Base(name))
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
separators, err := regexp.Compile(`[ &_=+:]`)
|
||||||
|
if err == nil {
|
||||||
|
name = separators.ReplaceAllString(name, "-")
|
||||||
|
}
|
||||||
|
legal, err := regexp.Compile(`[^[:alnum:]-.]`)
|
||||||
|
if err == nil {
|
||||||
|
name = legal.ReplaceAllString(name, "")
|
||||||
|
}
|
||||||
|
for strings.Contains(name, "--") {
|
||||||
|
name = strings.Replace(name, "--", "-", -1)
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeEmail canonicalize an email address.
|
||||||
|
// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
|
||||||
|
// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
|
||||||
|
// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
|
||||||
|
// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
|
||||||
|
// normalized to @gmail.com.
|
||||||
|
func NormalizeEmail(str string) (string, error) {
|
||||||
|
if !IsEmail(str) {
|
||||||
|
return "", fmt.Errorf("%s is not an email", str)
|
||||||
|
}
|
||||||
|
parts := strings.Split(str, "@")
|
||||||
|
parts[0] = strings.ToLower(parts[0])
|
||||||
|
parts[1] = strings.ToLower(parts[1])
|
||||||
|
if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
|
||||||
|
parts[1] = "gmail.com"
|
||||||
|
parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
|
||||||
|
}
|
||||||
|
return strings.Join(parts, "@"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will truncate a string closest length without breaking words.
|
||||||
|
func Truncate(str string, length int, ending string) string {
|
||||||
|
var aftstr, befstr string
|
||||||
|
if len(str) > length {
|
||||||
|
words := strings.Fields(str)
|
||||||
|
before, present := 0, 0
|
||||||
|
for i := range words {
|
||||||
|
befstr = aftstr
|
||||||
|
before = present
|
||||||
|
aftstr = aftstr + words[i] + " "
|
||||||
|
present = len(aftstr)
|
||||||
|
if present > length && i != 0 {
|
||||||
|
if (length - before) < (present - length) {
|
||||||
|
return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
|
||||||
|
} else {
|
||||||
|
return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
854
Godeps/_workspace/src/github.com/asaskevich/govalidator/validator.go
generated
vendored
Normal file
854
Godeps/_workspace/src/github.com/asaskevich/govalidator/validator.go
generated
vendored
Normal file
|
@ -0,0 +1,854 @@
|
||||||
|
// Package govalidator is package of validators and sanitizers for strings, structs and collections.
|
||||||
|
package govalidator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fieldsRequiredByDefault bool
|
||||||
|
|
||||||
|
// SetFieldsRequiredByDefault causes validation to fail when struct fields
|
||||||
|
// do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`).
|
||||||
|
// This struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
|
||||||
|
// type exampleStruct struct {
|
||||||
|
// Name string ``
|
||||||
|
// Email string `valid:"email"`
|
||||||
|
// This, however, will only fail when Email is empty or an invalid email address:
|
||||||
|
// type exampleStruct2 struct {
|
||||||
|
// Name string `valid:"-"`
|
||||||
|
// Email string `valid:"email"`
|
||||||
|
// Lastly, this will only fail when Email is an invalid email address but not when it's empty:
|
||||||
|
// type exampleStruct2 struct {
|
||||||
|
// Name string `valid:"-"`
|
||||||
|
// Email string `valid:"email,optional"`
|
||||||
|
func SetFieldsRequiredByDefault(value bool) {
|
||||||
|
fieldsRequiredByDefault = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmail check if the string is an email.
|
||||||
|
func IsEmail(str string) bool {
|
||||||
|
// TODO uppercase letters are not supported
|
||||||
|
return rxEmail.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsURL check if the string is an URL.
|
||||||
|
func IsURL(str string) bool {
|
||||||
|
if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
u, err := url.Parse(str)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(u.Host, ".") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return rxURL.MatchString(str)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRequestURL check if the string rawurl, assuming
|
||||||
|
// it was recieved in an HTTP request, is a valid
|
||||||
|
// URL confirm to RFC 3986
|
||||||
|
func IsRequestURL(rawurl string) bool {
|
||||||
|
url, err := url.ParseRequestURI(rawurl)
|
||||||
|
if err != nil {
|
||||||
|
return false //Couldn't even parse the rawurl
|
||||||
|
}
|
||||||
|
if len(url.Scheme) == 0 {
|
||||||
|
return false //No Scheme found
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRequestURI check if the string rawurl, assuming
|
||||||
|
// it was recieved in an HTTP request, is an
|
||||||
|
// absolute URI or an absolute path.
|
||||||
|
func IsRequestURI(rawurl string) bool {
|
||||||
|
_, err := url.ParseRequestURI(rawurl)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAlpha check if the string contains only letters (a-zA-Z). Empty string is valid.
|
||||||
|
func IsAlpha(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxAlpha.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
//IsUTFLetter check if the string contains only unicode letter characters.
|
||||||
|
//Similar to IsAlpha but for all languages. Empty string is valid.
|
||||||
|
func IsUTFLetter(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range str {
|
||||||
|
if !unicode.IsLetter(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAlphanumeric check if the string contains only letters and numbers. Empty string is valid.
|
||||||
|
func IsAlphanumeric(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxAlphanumeric.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUTFLetterNumeric check if the string contains only unicode letters and numbers. Empty string is valid.
|
||||||
|
func IsUTFLetterNumeric(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, c := range str {
|
||||||
|
if !unicode.IsLetter(c) && !unicode.IsNumber(c) { //letters && numbers are ok
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNumeric check if the string contains only numbers. Empty string is valid.
|
||||||
|
func IsNumeric(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxNumeric.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUTFNumeric check if the string contains only unicode numbers of any kind.
|
||||||
|
// Numbers can be 0-9 but also Fractions ¾,Roman Ⅸ and Hangzhou 〩. Empty string is valid.
|
||||||
|
func IsUTFNumeric(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.IndexAny(str, "+-") > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(str) > 1 {
|
||||||
|
str = strings.TrimPrefix(str, "-")
|
||||||
|
str = strings.TrimPrefix(str, "+")
|
||||||
|
}
|
||||||
|
for _, c := range str {
|
||||||
|
if unicode.IsNumber(c) == false { //numbers && minus sign are ok
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUTFDigit check if the string contains only unicode radix-10 decimal digits. Empty string is valid.
|
||||||
|
func IsUTFDigit(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.IndexAny(str, "+-") > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(str) > 1 {
|
||||||
|
str = strings.TrimPrefix(str, "-")
|
||||||
|
str = strings.TrimPrefix(str, "+")
|
||||||
|
}
|
||||||
|
for _, c := range str {
|
||||||
|
if !unicode.IsDigit(c) { //digits && minus sign are ok
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHexadecimal check if the string is a hexadecimal number.
|
||||||
|
func IsHexadecimal(str string) bool {
|
||||||
|
return rxHexadecimal.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHexcolor check if the string is a hexadecimal color.
|
||||||
|
func IsHexcolor(str string) bool {
|
||||||
|
return rxHexcolor.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRGBcolor check if the string is a valid RGB color in form rgb(RRR, GGG, BBB).
|
||||||
|
func IsRGBcolor(str string) bool {
|
||||||
|
return rxRGBcolor.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLowerCase check if the string is lowercase. Empty string is valid.
|
||||||
|
func IsLowerCase(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return str == strings.ToLower(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUpperCase check if the string is uppercase. Empty string is valid.
|
||||||
|
func IsUpperCase(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return str == strings.ToUpper(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInt check if the string is an integer. Empty string is valid.
|
||||||
|
func IsInt(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxInt.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFloat check if the string is a float.
|
||||||
|
func IsFloat(str string) bool {
|
||||||
|
return str != "" && rxFloat.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDivisibleBy check if the string is a number that's divisible by another.
|
||||||
|
// If second argument is not valid integer or zero, it's return false.
|
||||||
|
// Otherwise, if first argument is not valid integer or zero, it's return true (Invalid string converts to zero).
|
||||||
|
func IsDivisibleBy(str, num string) bool {
|
||||||
|
f, _ := ToFloat(str)
|
||||||
|
p := int64(f)
|
||||||
|
q, _ := ToInt(num)
|
||||||
|
if q == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return (p == 0) || (p%q == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNull check if the string is null.
|
||||||
|
func IsNull(str string) bool {
|
||||||
|
return len(str) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsByteLength check if the string's length (in bytes) falls in a range.
|
||||||
|
func IsByteLength(str string, min, max int) bool {
|
||||||
|
return len(str) >= min && len(str) <= max
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUUIDv3 check if the string is a UUID version 3.
|
||||||
|
func IsUUIDv3(str string) bool {
|
||||||
|
return rxUUID3.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUUIDv4 check if the string is a UUID version 4.
|
||||||
|
func IsUUIDv4(str string) bool {
|
||||||
|
return rxUUID4.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUUIDv5 check if the string is a UUID version 5.
|
||||||
|
func IsUUIDv5(str string) bool {
|
||||||
|
return rxUUID5.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUUID check if the string is a UUID (version 3, 4 or 5).
|
||||||
|
func IsUUID(str string) bool {
|
||||||
|
return rxUUID.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCreditCard check if the string is a credit card.
|
||||||
|
func IsCreditCard(str string) bool {
|
||||||
|
r, _ := regexp.Compile("[^0-9]+")
|
||||||
|
sanitized := r.ReplaceAll([]byte(str), []byte(""))
|
||||||
|
if !rxCreditCard.MatchString(string(sanitized)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var sum int64
|
||||||
|
var digit string
|
||||||
|
var tmpNum int64
|
||||||
|
var shouldDouble bool
|
||||||
|
for i := len(sanitized) - 1; i >= 0; i-- {
|
||||||
|
digit = string(sanitized[i:(i + 1)])
|
||||||
|
tmpNum, _ = ToInt(digit)
|
||||||
|
if shouldDouble {
|
||||||
|
tmpNum *= 2
|
||||||
|
if tmpNum >= 10 {
|
||||||
|
sum += ((tmpNum % 10) + 1)
|
||||||
|
} else {
|
||||||
|
sum += tmpNum
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sum += tmpNum
|
||||||
|
}
|
||||||
|
shouldDouble = !shouldDouble
|
||||||
|
}
|
||||||
|
|
||||||
|
if sum%10 == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsISBN10 check if the string is an ISBN version 10.
|
||||||
|
func IsISBN10(str string) bool {
|
||||||
|
return IsISBN(str, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsISBN13 check if the string is an ISBN version 13.
|
||||||
|
func IsISBN13(str string) bool {
|
||||||
|
return IsISBN(str, 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsISBN check if the string is an ISBN (version 10 or 13).
|
||||||
|
// If version value is not equal to 10 or 13, it will be check both variants.
|
||||||
|
func IsISBN(str string, version int) bool {
|
||||||
|
r, _ := regexp.Compile("[\\s-]+")
|
||||||
|
sanitized := r.ReplaceAll([]byte(str), []byte(""))
|
||||||
|
var checksum int32
|
||||||
|
var i int32
|
||||||
|
if version == 10 {
|
||||||
|
if !rxISBN10.MatchString(string(sanitized)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i = 0; i < 9; i++ {
|
||||||
|
checksum += (i + 1) * int32(sanitized[i]-'0')
|
||||||
|
}
|
||||||
|
if sanitized[9] == 'X' {
|
||||||
|
checksum += 10 * 10
|
||||||
|
} else {
|
||||||
|
checksum += 10 * int32(sanitized[9]-'0')
|
||||||
|
}
|
||||||
|
if checksum%11 == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} else if version == 13 {
|
||||||
|
if !rxISBN13.MatchString(string(sanitized)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
factor := []int32{1, 3}
|
||||||
|
for i = 0; i < 12; i++ {
|
||||||
|
checksum += factor[i%2] * int32(sanitized[i]-'0')
|
||||||
|
}
|
||||||
|
if (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return IsISBN(str, 10) || IsISBN(str, 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsJSON check if the string is valid JSON (note: uses json.Unmarshal).
|
||||||
|
func IsJSON(str string) bool {
|
||||||
|
var js json.RawMessage
|
||||||
|
return json.Unmarshal([]byte(str), &js) == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMultibyte check if the string contains one or more multibyte chars. Empty string is valid.
|
||||||
|
func IsMultibyte(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxMultibyte.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsASCII check if the string contains ASCII chars only. Empty string is valid.
|
||||||
|
func IsASCII(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxASCII.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPrintableASCII check if the string contains printable ASCII chars only. Empty string is valid.
|
||||||
|
func IsPrintableASCII(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxPrintableASCII.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFullWidth check if the string contains any full-width chars. Empty string is valid.
|
||||||
|
func IsFullWidth(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxFullWidth.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsHalfWidth check if the string contains any half-width chars. Empty string is valid.
|
||||||
|
func IsHalfWidth(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxHalfWidth.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsVariableWidth check if the string contains a mixture of full and half-width chars. Empty string is valid.
|
||||||
|
func IsVariableWidth(str string) bool {
|
||||||
|
if IsNull(str) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsBase64 check if a string is base64 encoded.
|
||||||
|
func IsBase64(str string) bool {
|
||||||
|
return rxBase64.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFilePath check is a string is Win or Unix file path and returns it's type.
|
||||||
|
func IsFilePath(str string) (bool, int) {
|
||||||
|
if rxWinPath.MatchString(str) {
|
||||||
|
//check windows path limit see:
|
||||||
|
// http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
|
||||||
|
if len(str[3:]) > 32767 {
|
||||||
|
return false, Win
|
||||||
|
}
|
||||||
|
return true, Win
|
||||||
|
} else if rxUnixPath.MatchString(str) {
|
||||||
|
return true, Unix
|
||||||
|
}
|
||||||
|
return false, Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDataURI checks if a string is base64 encoded data URI such as an image
|
||||||
|
func IsDataURI(str string) bool {
|
||||||
|
dataURI := strings.Split(str, ",")
|
||||||
|
if !rxDataURI.MatchString(dataURI[0]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return IsBase64(dataURI[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsISO3166Alpha2 checks if a string is valid two-letter country code
|
||||||
|
func IsISO3166Alpha2(str string) bool {
|
||||||
|
for _, entry := range ISO3166List {
|
||||||
|
if str == entry.Alpha2Code {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsISO3166Alpha3 checks if a string is valid three-letter country code
|
||||||
|
func IsISO3166Alpha3(str string) bool {
|
||||||
|
for _, entry := range ISO3166List {
|
||||||
|
if str == entry.Alpha3Code {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIP checks if a string is either IP version 4 or 6.
|
||||||
|
func IsIP(str string) bool {
|
||||||
|
return net.ParseIP(str) != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIPv4 check if the string is an IP version 4.
|
||||||
|
func IsIPv4(str string) bool {
|
||||||
|
ip := net.ParseIP(str)
|
||||||
|
return ip != nil && ip.To4() != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsIPv6 check if the string is an IP version 6.
|
||||||
|
func IsIPv6(str string) bool {
|
||||||
|
ip := net.ParseIP(str)
|
||||||
|
return ip != nil && ip.To4() == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMAC check if a string is valid MAC address.
|
||||||
|
// Possible MAC formats:
|
||||||
|
// 01:23:45:67:89:ab
|
||||||
|
// 01:23:45:67:89:ab:cd:ef
|
||||||
|
// 01-23-45-67-89-ab
|
||||||
|
// 01-23-45-67-89-ab-cd-ef
|
||||||
|
// 0123.4567.89ab
|
||||||
|
// 0123.4567.89ab.cdef
|
||||||
|
func IsMAC(str string) bool {
|
||||||
|
_, err := net.ParseMAC(str)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMongoID check if the string is a valid hex-encoded representation of a MongoDB ObjectId.
|
||||||
|
func IsMongoID(str string) bool {
|
||||||
|
return rxHexadecimal.MatchString(str) && (len(str) == 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLatitude check if a string is valid latitude.
|
||||||
|
func IsLatitude(str string) bool {
|
||||||
|
return rxLatitude.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsLongitude check if a string is valid longitude.
|
||||||
|
func IsLongitude(str string) bool {
|
||||||
|
return rxLongitude.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateStruct use tags for fields
|
||||||
|
func ValidateStruct(s interface{}) (bool, error) {
|
||||||
|
if s == nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
result := true
|
||||||
|
var err error
|
||||||
|
val := reflect.ValueOf(s)
|
||||||
|
if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
// we only accept structs
|
||||||
|
if val.Kind() != reflect.Struct {
|
||||||
|
return false, fmt.Errorf("function only accepts structs; got %s", val.Kind())
|
||||||
|
}
|
||||||
|
var errs Errors
|
||||||
|
for i := 0; i < val.NumField(); i++ {
|
||||||
|
valueField := val.Field(i)
|
||||||
|
typeField := val.Type().Field(i)
|
||||||
|
if typeField.PkgPath != "" {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
resultField, err := typeCheck(valueField, typeField)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
result = result && resultField
|
||||||
|
}
|
||||||
|
if len(errs) > 0 {
|
||||||
|
err = errs
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseTag splits a struct field's tag into its
|
||||||
|
// comma-separated options.
|
||||||
|
func parseTag(tag string) tagOptions {
|
||||||
|
split := strings.SplitN(tag, ",", -1)
|
||||||
|
return tagOptions(split)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidTag(s string) bool {
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
switch {
|
||||||
|
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
|
||||||
|
// Backslash and quote chars are reserved, but
|
||||||
|
// otherwise any punctuation chars are allowed
|
||||||
|
// in a tag name.
|
||||||
|
default:
|
||||||
|
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSSN will validate the given string as a U.S. Social Security Number
|
||||||
|
func IsSSN(str string) bool {
|
||||||
|
if str == "" || len(str) != 11 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return rxSSN.MatchString(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByteLength check string's length
|
||||||
|
func ByteLength(str string, params ...string) bool {
|
||||||
|
if len(params) == 2 {
|
||||||
|
min, _ := ToInt(params[0])
|
||||||
|
max, _ := ToInt(params[1])
|
||||||
|
return len(str) >= int(min) && len(str) <= int(max)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringLength check string's length (including multi byte strings)
|
||||||
|
func StringLength(str string, params ...string) bool {
|
||||||
|
|
||||||
|
if len(params) == 2 {
|
||||||
|
strLength := utf8.RuneCountInString(str)
|
||||||
|
min, _ := ToInt(params[0])
|
||||||
|
max, _ := ToInt(params[1])
|
||||||
|
return strLength >= int(min) && strLength <= int(max)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains returns whether checks that a comma-separated list of options
|
||||||
|
// contains a particular substr flag. substr must be surrounded by a
|
||||||
|
// string boundary or commas.
|
||||||
|
func (opts tagOptions) contains(optionName string) bool {
|
||||||
|
for i := range opts {
|
||||||
|
tagOpt := opts[i]
|
||||||
|
if tagOpt == optionName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRequired(v reflect.Value, t reflect.StructField, options tagOptions) (bool, error) {
|
||||||
|
if options.contains("required") {
|
||||||
|
err := fmt.Errorf("non zero value required")
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
} else if fieldsRequiredByDefault && !options.contains("optional") {
|
||||||
|
err := fmt.Errorf("All fields are required to at least have one validation defined")
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
}
|
||||||
|
// not required and empty is valid
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func typeCheck(v reflect.Value, t reflect.StructField) (bool, error) {
|
||||||
|
if !v.IsValid() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tag := t.Tag.Get(tagName)
|
||||||
|
|
||||||
|
// Check if the field should be ignored
|
||||||
|
switch tag {
|
||||||
|
case "":
|
||||||
|
if !fieldsRequiredByDefault {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
err := fmt.Errorf("All fields are required to at least have one validation defined")
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
case "-":
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
options := parseTag(tag)
|
||||||
|
for i := range options {
|
||||||
|
tagOpt := options[i]
|
||||||
|
if ok := isValidTag(tagOpt); !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if validatefunc, ok := CustomTypeTagMap[tagOpt]; ok {
|
||||||
|
options = append(options[:i], options[i+1:]...) // we found our custom validator, so remove it from the options
|
||||||
|
if result := validatefunc(v.Interface()); !result {
|
||||||
|
return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), tagOpt)}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isEmptyValue(v) {
|
||||||
|
// an empty value is not validated, check only required
|
||||||
|
return checkRequired(v, t, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Bool,
|
||||||
|
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
|
||||||
|
reflect.Float32, reflect.Float64,
|
||||||
|
reflect.String:
|
||||||
|
// for each tag option check the map of validator functions
|
||||||
|
for i := range options {
|
||||||
|
tagOpt := options[i]
|
||||||
|
negate := false
|
||||||
|
// Check wether the tag looks like '!something' or 'something'
|
||||||
|
if len(tagOpt) > 0 && tagOpt[0] == '!' {
|
||||||
|
tagOpt = string(tagOpt[1:])
|
||||||
|
negate = true
|
||||||
|
}
|
||||||
|
if ok := isValidTag(tagOpt); !ok {
|
||||||
|
err := fmt.Errorf("Unkown Validator %s", tagOpt)
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for param validators
|
||||||
|
for key, value := range ParamTagRegexMap {
|
||||||
|
ps := value.FindStringSubmatch(tagOpt)
|
||||||
|
if len(ps) > 0 {
|
||||||
|
if validatefunc, ok := ParamTagMap[key]; ok {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
field := fmt.Sprint(v) // make value into string, then validate with regex
|
||||||
|
if result := validatefunc(field, ps[1:]...); !result && !negate || result && negate {
|
||||||
|
var err error
|
||||||
|
if !negate {
|
||||||
|
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
|
||||||
|
}
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
//Not Yet Supported Types (Fail here!)
|
||||||
|
err := fmt.Errorf("Validator %s doesn't support kind %s", tagOpt, v.Kind())
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if validatefunc, ok := TagMap[tagOpt]; ok {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
field := fmt.Sprint(v) // make value into string, then validate with regex
|
||||||
|
if result := validatefunc(field); !result && !negate || result && negate {
|
||||||
|
var err error
|
||||||
|
if !negate {
|
||||||
|
err = fmt.Errorf("%s does not validate as %s", field, tagOpt)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("%s does validate as %s", field, tagOpt)
|
||||||
|
}
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
//Not Yet Supported Types (Fail here!)
|
||||||
|
err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", tagOpt, v.Kind(), v)
|
||||||
|
return false, Error{t.Name, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
case reflect.Map:
|
||||||
|
if v.Type().Key().Kind() != reflect.String {
|
||||||
|
return false, &UnsupportedTypeError{v.Type()}
|
||||||
|
}
|
||||||
|
var sv stringValues
|
||||||
|
sv = v.MapKeys()
|
||||||
|
sort.Sort(sv)
|
||||||
|
result := true
|
||||||
|
for _, k := range sv {
|
||||||
|
resultItem, err := ValidateStruct(v.MapIndex(k).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
result = result && resultItem
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
case reflect.Slice:
|
||||||
|
result := true
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
var resultItem bool
|
||||||
|
var err error
|
||||||
|
if v.Index(i).Kind() != reflect.Struct {
|
||||||
|
resultItem, err = typeCheck(v.Index(i), t)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resultItem, err = ValidateStruct(v.Index(i).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = result && resultItem
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
case reflect.Array:
|
||||||
|
result := true
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
var resultItem bool
|
||||||
|
var err error
|
||||||
|
if v.Index(i).Kind() != reflect.Struct {
|
||||||
|
resultItem, err = typeCheck(v.Index(i), t)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resultItem, err = ValidateStruct(v.Index(i).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = result && resultItem
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
// If the value is an interface then encode its element
|
||||||
|
if v.IsNil() {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return ValidateStruct(v.Interface())
|
||||||
|
case reflect.Ptr:
|
||||||
|
// If the value is a pointer then check its element
|
||||||
|
if v.IsNil() {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return typeCheck(v.Elem(), t)
|
||||||
|
case reflect.Struct:
|
||||||
|
return ValidateStruct(v.Interface())
|
||||||
|
default:
|
||||||
|
return false, &UnsupportedTypeError{v.Type()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEmptyValue(v reflect.Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.String, reflect.Array:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Map, reflect.Slice:
|
||||||
|
return v.Len() == 0 || v.IsNil()
|
||||||
|
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 reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorByField returns error for specified field of the struct
|
||||||
|
// validated by ValidateStruct or empty string if there are no errors
|
||||||
|
// or this field doesn't exists or doesn't have any errors.
|
||||||
|
func ErrorByField(e error, field string) string {
|
||||||
|
if e == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ErrorsByField(e)[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorsByField returns map of errors of the struct validated
|
||||||
|
// by ValidateStruct or empty map if there are no errors.
|
||||||
|
func ErrorsByField(e error) map[string]string {
|
||||||
|
m := make(map[string]string)
|
||||||
|
if e == nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
// prototype for ValidateStruct
|
||||||
|
|
||||||
|
switch e.(type) {
|
||||||
|
case Error:
|
||||||
|
m[e.(Error).Name] = e.(Error).Err.Error()
|
||||||
|
case Errors:
|
||||||
|
for _, item := range e.(Errors).Errors() {
|
||||||
|
m[item.(Error).Name] = item.(Error).Err.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns string equivalent for reflect.Type
|
||||||
|
func (e *UnsupportedTypeError) Error() string {
|
||||||
|
return "validator: unsupported type: " + e.Type.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sv stringValues) Len() int { return len(sv) }
|
||||||
|
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
|
||||||
|
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
|
||||||
|
func (sv stringValues) get(i int) string { return sv[i].String() }
|
15
Godeps/_workspace/src/github.com/asaskevich/govalidator/wercker.yml
generated
vendored
Normal file
15
Godeps/_workspace/src/github.com/asaskevich/govalidator/wercker.yml
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
box: wercker/golang
|
||||||
|
build:
|
||||||
|
steps:
|
||||||
|
- setup-go-workspace
|
||||||
|
|
||||||
|
- script:
|
||||||
|
name: go get
|
||||||
|
code: |
|
||||||
|
go version
|
||||||
|
go get -t ./...
|
||||||
|
|
||||||
|
- script:
|
||||||
|
name: go test
|
||||||
|
code: |
|
||||||
|
go test -race ./...
|
26
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
26
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
|
@ -13,11 +13,11 @@ var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
|
||||||
|
|
||||||
// rValuesAtPath returns a slice of values found in value v. The values
|
// rValuesAtPath returns a slice of values found in value v. The values
|
||||||
// in v are explored recursively so all nested values are collected.
|
// in v are explored recursively so all nested values are collected.
|
||||||
func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool) []reflect.Value {
|
func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
|
||||||
pathparts := strings.Split(path, "||")
|
pathparts := strings.Split(path, "||")
|
||||||
if len(pathparts) > 1 {
|
if len(pathparts) > 1 {
|
||||||
for _, pathpart := range pathparts {
|
for _, pathpart := range pathparts {
|
||||||
vals := rValuesAtPath(v, pathpart, create, caseSensitive)
|
vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
|
||||||
if len(vals) > 0 {
|
if len(vals) > 0 {
|
||||||
return vals
|
return vals
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,16 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
if create && value.Kind() == reflect.Ptr && value.IsNil() {
|
if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
|
||||||
|
if !value.IsNil() {
|
||||||
|
value.Set(reflect.Zero(value.Type()))
|
||||||
|
}
|
||||||
|
return []reflect.Value{value}
|
||||||
|
}
|
||||||
|
|
||||||
|
if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
|
||||||
|
// TODO if the value is the terminus it should not be created
|
||||||
|
// if the value to be set to its position is nil.
|
||||||
value.Set(reflect.New(value.Type().Elem()))
|
value.Set(reflect.New(value.Type().Elem()))
|
||||||
value = value.Elem()
|
value = value.Elem()
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,7 +93,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||||
if !create && value.IsNil() {
|
if !createPath && value.IsNil() {
|
||||||
value = reflect.ValueOf(nil)
|
value = reflect.ValueOf(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +125,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
// pull out index
|
// pull out index
|
||||||
i := int(*index)
|
i := int(*index)
|
||||||
if i >= value.Len() { // check out of bounds
|
if i >= value.Len() { // check out of bounds
|
||||||
if create {
|
if createPath {
|
||||||
// TODO resize slice
|
// TODO resize slice
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
|
@ -127,7 +136,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
|
||||||
value = reflect.Indirect(value.Index(i))
|
value = reflect.Indirect(value.Index(i))
|
||||||
|
|
||||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||||
if !create && value.IsNil() {
|
if !createPath && value.IsNil() {
|
||||||
value = reflect.ValueOf(nil)
|
value = reflect.ValueOf(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,8 +185,11 @@ func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
|
||||||
// SetValueAtPath sets a value at the case insensitive lexical path inside
|
// SetValueAtPath sets a value at the case insensitive lexical path inside
|
||||||
// of a structure.
|
// of a structure.
|
||||||
func SetValueAtPath(i interface{}, path string, v interface{}) {
|
func SetValueAtPath(i interface{}, path string, v interface{}) {
|
||||||
if rvals := rValuesAtPath(i, path, true, false); rvals != nil {
|
if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
|
||||||
for _, rval := range rvals {
|
for _, rval := range rvals {
|
||||||
|
if rval.Kind() == reflect.Ptr && rval.IsNil() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
setValue(rval, v)
|
setValue(rval, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
17
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
|
@ -41,11 +41,20 @@ func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, op
|
||||||
Handlers: handlers,
|
Handlers: handlers,
|
||||||
}
|
}
|
||||||
|
|
||||||
maxRetries := aws.IntValue(cfg.MaxRetries)
|
switch retryer, ok := cfg.Retryer.(request.Retryer); {
|
||||||
if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
|
case ok:
|
||||||
maxRetries = 3
|
svc.Retryer = retryer
|
||||||
|
case cfg.Retryer != nil && cfg.Logger != nil:
|
||||||
|
s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
|
||||||
|
cfg.Logger.Log(s)
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
maxRetries := aws.IntValue(cfg.MaxRetries)
|
||||||
|
if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
|
||||||
|
maxRetries = 3
|
||||||
|
}
|
||||||
|
svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
|
||||||
}
|
}
|
||||||
svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
|
|
||||||
|
|
||||||
svc.AddDebugHandlers()
|
svc.AddDebugHandlers()
|
||||||
|
|
||||||
|
|
22
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
22
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
|
@ -12,6 +12,9 @@ import (
|
||||||
// is nil also.
|
// is nil also.
|
||||||
const UseServiceDefaultRetries = -1
|
const UseServiceDefaultRetries = -1
|
||||||
|
|
||||||
|
// RequestRetryer is an alias for a type that implements the request.Retryer interface.
|
||||||
|
type RequestRetryer interface{}
|
||||||
|
|
||||||
// A Config provides service configuration for service clients. By default,
|
// A Config provides service configuration for service clients. By default,
|
||||||
// all clients will use the {defaults.DefaultConfig} structure.
|
// all clients will use the {defaults.DefaultConfig} structure.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -59,6 +62,21 @@ type Config struct {
|
||||||
// configuration.
|
// configuration.
|
||||||
MaxRetries *int
|
MaxRetries *int
|
||||||
|
|
||||||
|
// Retryer guides how HTTP requests should be retried in case of recoverable failures.
|
||||||
|
//
|
||||||
|
// When nil or the value does not implement the request.Retryer interface,
|
||||||
|
// the request.DefaultRetryer will be used.
|
||||||
|
//
|
||||||
|
// When both Retryer and MaxRetries are non-nil, the former is used and
|
||||||
|
// the latter ignored.
|
||||||
|
//
|
||||||
|
// To set the Retryer field in a type-safe manner and with chaining, use
|
||||||
|
// the request.WithRetryer helper function:
|
||||||
|
//
|
||||||
|
// cfg := request.WithRetryer(aws.NewConfig(), myRetryer)
|
||||||
|
//
|
||||||
|
Retryer RequestRetryer
|
||||||
|
|
||||||
// Disables semantic parameter validation, which validates input for missing
|
// Disables semantic parameter validation, which validates input for missing
|
||||||
// required fields and/or other semantic request input errors.
|
// required fields and/or other semantic request input errors.
|
||||||
DisableParamValidation *bool
|
DisableParamValidation *bool
|
||||||
|
@ -217,6 +235,10 @@ func mergeInConfig(dst *Config, other *Config) {
|
||||||
dst.MaxRetries = other.MaxRetries
|
dst.MaxRetries = other.MaxRetries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if other.Retryer != nil {
|
||||||
|
dst.Retryer = other.Retryer
|
||||||
|
}
|
||||||
|
|
||||||
if other.DisableParamValidation != nil {
|
if other.DisableParamValidation != nil {
|
||||||
dst.DisableParamValidation = other.DisableParamValidation
|
dst.DisableParamValidation = other.DisableParamValidation
|
||||||
}
|
}
|
||||||
|
|
4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
generated
vendored
|
@ -36,7 +36,9 @@ var (
|
||||||
// creds := NewChainCredentials(
|
// creds := NewChainCredentials(
|
||||||
// []Provider{
|
// []Provider{
|
||||||
// &EnvProvider{},
|
// &EnvProvider{},
|
||||||
// &EC2RoleProvider{},
|
// &EC2RoleProvider{
|
||||||
|
// Client: ec2metadata.New(sess),
|
||||||
|
// },
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// // Usage of ChainCredentials with aws.Config
|
// // Usage of ChainCredentials with aws.Config
|
||||||
|
|
|
@ -23,9 +23,10 @@ import (
|
||||||
// p := &ec2rolecreds.EC2RoleProvider{
|
// p := &ec2rolecreds.EC2RoleProvider{
|
||||||
// // Pass in a custom timeout to be used when requesting
|
// // Pass in a custom timeout to be used when requesting
|
||||||
// // IAM EC2 Role credentials.
|
// // IAM EC2 Role credentials.
|
||||||
// Client: &http.Client{
|
// Client: ec2metadata.New(sess, aws.Config{
|
||||||
// Timeout: 10 * time.Second,
|
// HTTPClient: &http.Client{Timeout: 10 * time.Second},
|
||||||
// },
|
// }),
|
||||||
|
//
|
||||||
// // Do not use early expiry of credentials. If a non zero value is
|
// // Do not use early expiry of credentials. If a non zero value is
|
||||||
// // specified the credentials will be expired early
|
// // specified the credentials will be expired early
|
||||||
// ExpiryWindow: 0,
|
// ExpiryWindow: 0,
|
||||||
|
|
21
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
21
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
generated
vendored
|
@ -1,5 +1,10 @@
|
||||||
// Package defaults is a collection of helpers to retrieve the SDK's default
|
// Package defaults is a collection of helpers to retrieve the SDK's default
|
||||||
// configuration and handlers.
|
// configuration and handlers.
|
||||||
|
//
|
||||||
|
// Generally this package shouldn't be used directly, but session.Session
|
||||||
|
// instead. This package is useful when you need to reset the defaults
|
||||||
|
// of a session or service client to the SDK defaults before setting
|
||||||
|
// additional parameters.
|
||||||
package defaults
|
package defaults
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -34,7 +39,13 @@ func Get() Defaults {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config returns the default configuration.
|
// Config returns the default configuration without credentials.
|
||||||
|
// To retrieve a config with credentials also included use
|
||||||
|
// `defaults.Get().Config` instead.
|
||||||
|
//
|
||||||
|
// Generally you shouldn't need to use this method directly, but
|
||||||
|
// is available if you need to reset the configuration of an
|
||||||
|
// existing service client or session.
|
||||||
func Config() *aws.Config {
|
func Config() *aws.Config {
|
||||||
return aws.NewConfig().
|
return aws.NewConfig().
|
||||||
WithCredentials(credentials.AnonymousCredentials).
|
WithCredentials(credentials.AnonymousCredentials).
|
||||||
|
@ -47,6 +58,10 @@ func Config() *aws.Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handlers returns the default request handlers.
|
// Handlers returns the default request handlers.
|
||||||
|
//
|
||||||
|
// Generally you shouldn't need to use this method directly, but
|
||||||
|
// is available if you need to reset the request handlers of an
|
||||||
|
// existing service client or session.
|
||||||
func Handlers() request.Handlers {
|
func Handlers() request.Handlers {
|
||||||
var handlers request.Handlers
|
var handlers request.Handlers
|
||||||
|
|
||||||
|
@ -61,6 +76,10 @@ func Handlers() request.Handlers {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CredChain returns the default credential chain.
|
// CredChain returns the default credential chain.
|
||||||
|
//
|
||||||
|
// Generally you shouldn't need to use this method directly, but
|
||||||
|
// is available if you need to reset the credentials of an
|
||||||
|
// existing service client or session's Config.
|
||||||
func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
|
func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
|
||||||
endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true)
|
endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true)
|
||||||
|
|
||||||
|
|
14
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
generated
vendored
14
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
generated
vendored
|
@ -44,12 +44,19 @@ func (r *Request) nextPageTokens() []interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens := []interface{}{}
|
tokens := []interface{}{}
|
||||||
|
tokenAdded := false
|
||||||
for _, outToken := range r.Operation.OutputTokens {
|
for _, outToken := range r.Operation.OutputTokens {
|
||||||
v, _ := awsutil.ValuesAtPath(r.Data, outToken)
|
v, _ := awsutil.ValuesAtPath(r.Data, outToken)
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
tokens = append(tokens, v[0])
|
tokens = append(tokens, v[0])
|
||||||
|
tokenAdded = true
|
||||||
|
} else {
|
||||||
|
tokens = append(tokens, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !tokenAdded {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
}
|
}
|
||||||
|
@ -85,9 +92,10 @@ func (r *Request) NextPage() *Request {
|
||||||
// return true to keep iterating or false to stop.
|
// return true to keep iterating or false to stop.
|
||||||
func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
|
func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
|
||||||
for page := r; page != nil; page = page.NextPage() {
|
for page := r; page != nil; page = page.NextPage() {
|
||||||
page.Send()
|
if err := page.Send(); err != nil {
|
||||||
shouldContinue := fn(page.Data, !page.HasNextPage())
|
return err
|
||||||
if page.Error != nil || !shouldContinue {
|
}
|
||||||
|
if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage {
|
||||||
return page.Error
|
return page.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/retryer.go
generated
vendored
8
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/retryer.go
generated
vendored
|
@ -3,6 +3,7 @@ package request
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,6 +16,13 @@ type Retryer interface {
|
||||||
MaxRetries() int
|
MaxRetries() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithRetryer sets a config Retryer value to the given Config returning it
|
||||||
|
// for chaining.
|
||||||
|
func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config {
|
||||||
|
cfg.Retryer = retryer
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
// retryableCodes is a collection of service response codes which are retry-able
|
// retryableCodes is a collection of service response codes which are retry-able
|
||||||
// without any further action.
|
// without any further action.
|
||||||
var retryableCodes = map[string]struct{}{
|
var retryableCodes = map[string]struct{}{
|
||||||
|
|
6
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
6
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go
generated
vendored
|
@ -1,5 +1,11 @@
|
||||||
// Package session provides a way to create service clients with shared configuration
|
// Package session provides a way to create service clients with shared configuration
|
||||||
// and handlers.
|
// and handlers.
|
||||||
|
//
|
||||||
|
// Generally this package should be used instead of the `defaults` package.
|
||||||
|
//
|
||||||
|
// A session should be used to share configurations and request handlers between multiple
|
||||||
|
// service clients. When service clients need specific configuration aws.Config can be
|
||||||
|
// used to provide additional configuration directly to the service client.
|
||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
|
@ -5,4 +5,4 @@ package aws
|
||||||
const SDKName = "aws-sdk-go"
|
const SDKName = "aws-sdk-go"
|
||||||
|
|
||||||
// SDKVersion is the version of this SDK
|
// SDKVersion is the version of this SDK
|
||||||
const SDKVersion = "0.10.4"
|
const SDKVersion = "1.0.4"
|
||||||
|
|
2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/build.go
generated
vendored
2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/build.go
generated
vendored
|
@ -93,7 +93,7 @@ func buildLocationElements(r *request.Request, v reflect.Value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildBody(r *request.Request, v reflect.Value) {
|
func buildBody(r *request.Request, v reflect.Value) {
|
||||||
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
if field, ok := v.Type().FieldByName("_"); ok {
|
||||||
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
pfield, _ := v.Type().FieldByName(payloadName)
|
pfield, _ := v.Type().FieldByName(payloadName)
|
||||||
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
|
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
|
||||||
|
|
4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go
generated
vendored
4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go
generated
vendored
|
@ -12,7 +12,7 @@ func PayloadMember(i interface{}) interface{} {
|
||||||
if !v.IsValid() {
|
if !v.IsValid() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
if field, ok := v.Type().FieldByName("_"); ok {
|
||||||
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
field, _ := v.Type().FieldByName(payloadName)
|
field, _ := v.Type().FieldByName(payloadName)
|
||||||
if field.Tag.Get("type") != "structure" {
|
if field.Tag.Get("type") != "structure" {
|
||||||
|
@ -34,7 +34,7 @@ func PayloadType(i interface{}) string {
|
||||||
if !v.IsValid() {
|
if !v.IsValid() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
if field, ok := v.Type().FieldByName("_"); ok {
|
||||||
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
if member, ok := v.Type().FieldByName(payloadName); ok {
|
if member, ok := v.Type().FieldByName(payloadName); ok {
|
||||||
return member.Tag.Get("type")
|
return member.Tag.Get("type")
|
||||||
|
|
2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go
generated
vendored
2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go
generated
vendored
|
@ -33,7 +33,7 @@ func UnmarshalMeta(r *request.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalBody(r *request.Request, v reflect.Value) {
|
func unmarshalBody(r *request.Request, v reflect.Value) {
|
||||||
if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok {
|
if field, ok := v.Type().FieldByName("_"); ok {
|
||||||
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
if payloadName := field.Tag.Get("payload"); payloadName != "" {
|
||||||
pfield, _ := v.Type().FieldByName(payloadName)
|
pfield, _ := v.Type().FieldByName(payloadName)
|
||||||
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
|
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
|
||||||
|
|
|
@ -69,7 +69,7 @@ func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag refle
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case "structure":
|
case "structure":
|
||||||
if field, ok := value.Type().FieldByName("SDKShapeTraits"); ok {
|
if field, ok := value.Type().FieldByName("_"); ok {
|
||||||
tag = tag + reflect.StructTag(" ") + field.Tag
|
tag = tag + reflect.StructTag(" ") + field.Tag
|
||||||
}
|
}
|
||||||
return b.buildStruct(value, current, tag)
|
return b.buildStruct(value, current, tag)
|
||||||
|
|
|
@ -59,7 +59,7 @@ func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case "structure":
|
case "structure":
|
||||||
if field, ok := rtype.FieldByName("SDKShapeTraits"); ok {
|
if field, ok := rtype.FieldByName("_"); ok {
|
||||||
tag = field.Tag
|
tag = field.Tag
|
||||||
}
|
}
|
||||||
return parseStruct(r, node, tag)
|
return parseStruct(r, node, tag)
|
||||||
|
|
95
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter.go
generated
vendored
95
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||||
"github.com/aws/aws-sdk-go/aws/request"
|
"github.com/aws/aws-sdk-go/aws/request"
|
||||||
|
@ -47,52 +48,74 @@ func (w *Waiter) Wait() error {
|
||||||
res := method.Call([]reflect.Value{in})
|
res := method.Call([]reflect.Value{in})
|
||||||
req := res[0].Interface().(*request.Request)
|
req := res[0].Interface().(*request.Request)
|
||||||
req.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Waiter"))
|
req.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Waiter"))
|
||||||
if err := req.Send(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
err := req.Send()
|
||||||
for _, a := range w.Acceptors {
|
for _, a := range w.Acceptors {
|
||||||
|
if err != nil && a.Matcher != "error" {
|
||||||
|
// Only matcher error is valid if there is a request error
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
result := false
|
result := false
|
||||||
|
var vals []interface{}
|
||||||
switch a.Matcher {
|
switch a.Matcher {
|
||||||
case "pathAll":
|
case "pathAll", "path":
|
||||||
if vals, _ := awsutil.ValuesAtPath(req.Data, a.Argument); req.Error == nil && vals != nil {
|
// Require all matches to be equal for result to match
|
||||||
result = true
|
vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
|
||||||
for _, val := range vals {
|
result = true
|
||||||
if !awsutil.DeepEqual(val, a.Expected) {
|
for _, val := range vals {
|
||||||
result = false
|
if !awsutil.DeepEqual(val, a.Expected) {
|
||||||
break
|
result = false
|
||||||
}
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "pathAny":
|
case "pathAny":
|
||||||
if vals, _ := awsutil.ValuesAtPath(req.Data, a.Argument); req.Error == nil && vals != nil {
|
// Only a single match needs to equal for the result to match
|
||||||
for _, val := range vals {
|
vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
|
||||||
if awsutil.DeepEqual(val, a.Expected) {
|
for _, val := range vals {
|
||||||
result = true
|
if awsutil.DeepEqual(val, a.Expected) {
|
||||||
break
|
result = true
|
||||||
}
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "status":
|
case "status":
|
||||||
s := a.Expected.(int)
|
s := a.Expected.(int)
|
||||||
result = s == req.HTTPResponse.StatusCode
|
result = s == req.HTTPResponse.StatusCode
|
||||||
|
case "error":
|
||||||
|
if aerr, ok := err.(awserr.Error); ok {
|
||||||
|
result = aerr.Code() == a.Expected.(string)
|
||||||
|
}
|
||||||
|
case "pathList":
|
||||||
|
// ignored matcher
|
||||||
|
default:
|
||||||
|
logf(client, "WARNING: Waiter for %s encountered unexpected matcher: %s",
|
||||||
|
w.Config.Operation, a.Matcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result {
|
if !result {
|
||||||
switch a.State {
|
// If there was no matching result found there is nothing more to do
|
||||||
case "success":
|
// for this response, retry the request.
|
||||||
return nil // waiter completed
|
continue
|
||||||
case "failure":
|
|
||||||
if req.Error == nil {
|
|
||||||
return awserr.New("ResourceNotReady",
|
|
||||||
fmt.Sprintf("failed waiting for successful resource state"), nil)
|
|
||||||
}
|
|
||||||
return req.Error // waiter failed
|
|
||||||
case "retry":
|
|
||||||
// do nothing, just retry
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch a.State {
|
||||||
|
case "success":
|
||||||
|
// waiter completed
|
||||||
|
return nil
|
||||||
|
case "failure":
|
||||||
|
// Waiter failure state triggered
|
||||||
|
return awserr.New("ResourceNotReady",
|
||||||
|
fmt.Sprintf("failed waiting for successful resource state"), err)
|
||||||
|
case "retry":
|
||||||
|
// clear the error and retry the operation
|
||||||
|
err = nil
|
||||||
|
default:
|
||||||
|
logf(client, "WARNING: Waiter for %s encountered unexpected state: %s",
|
||||||
|
w.Config.Operation, a.State)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(time.Second * time.Duration(w.Delay))
|
time.Sleep(time.Second * time.Duration(w.Delay))
|
||||||
|
@ -101,3 +124,13 @@ func (w *Waiter) Wait() error {
|
||||||
return awserr.New("ResourceNotReady",
|
return awserr.New("ResourceNotReady",
|
||||||
fmt.Sprintf("exceeded %d wait attempts", w.MaxAttempts), nil)
|
fmt.Sprintf("exceeded %d wait attempts", w.MaxAttempts), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logf(client reflect.Value, msg string, args ...interface{}) {
|
||||||
|
cfgVal := client.FieldByName("Config")
|
||||||
|
if !cfgVal.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cfg, ok := cfgVal.Interface().(*aws.Config); ok && cfg.Logger != nil {
|
||||||
|
cfg.Logger.Log(fmt.Sprintf(msg, args...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
5171
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go
generated
vendored
5171
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go
generated
vendored
File diff suppressed because it is too large
Load diff
28
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go
generated
vendored
28
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go
generated
vendored
|
@ -18,6 +18,10 @@ type EC2API interface {
|
||||||
|
|
||||||
AllocateAddress(*ec2.AllocateAddressInput) (*ec2.AllocateAddressOutput, error)
|
AllocateAddress(*ec2.AllocateAddressInput) (*ec2.AllocateAddressOutput, error)
|
||||||
|
|
||||||
|
AllocateHostsRequest(*ec2.AllocateHostsInput) (*request.Request, *ec2.AllocateHostsOutput)
|
||||||
|
|
||||||
|
AllocateHosts(*ec2.AllocateHostsInput) (*ec2.AllocateHostsOutput, error)
|
||||||
|
|
||||||
AssignPrivateIpAddressesRequest(*ec2.AssignPrivateIpAddressesInput) (*request.Request, *ec2.AssignPrivateIpAddressesOutput)
|
AssignPrivateIpAddressesRequest(*ec2.AssignPrivateIpAddressesInput) (*request.Request, *ec2.AssignPrivateIpAddressesOutput)
|
||||||
|
|
||||||
AssignPrivateIpAddresses(*ec2.AssignPrivateIpAddressesInput) (*ec2.AssignPrivateIpAddressesOutput, error)
|
AssignPrivateIpAddresses(*ec2.AssignPrivateIpAddressesInput) (*ec2.AssignPrivateIpAddressesOutput, error)
|
||||||
|
@ -346,6 +350,14 @@ type EC2API interface {
|
||||||
|
|
||||||
DescribeFlowLogs(*ec2.DescribeFlowLogsInput) (*ec2.DescribeFlowLogsOutput, error)
|
DescribeFlowLogs(*ec2.DescribeFlowLogsInput) (*ec2.DescribeFlowLogsOutput, error)
|
||||||
|
|
||||||
|
DescribeHostsRequest(*ec2.DescribeHostsInput) (*request.Request, *ec2.DescribeHostsOutput)
|
||||||
|
|
||||||
|
DescribeHosts(*ec2.DescribeHostsInput) (*ec2.DescribeHostsOutput, error)
|
||||||
|
|
||||||
|
DescribeIdFormatRequest(*ec2.DescribeIdFormatInput) (*request.Request, *ec2.DescribeIdFormatOutput)
|
||||||
|
|
||||||
|
DescribeIdFormat(*ec2.DescribeIdFormatInput) (*ec2.DescribeIdFormatOutput, error)
|
||||||
|
|
||||||
DescribeImageAttributeRequest(*ec2.DescribeImageAttributeInput) (*request.Request, *ec2.DescribeImageAttributeOutput)
|
DescribeImageAttributeRequest(*ec2.DescribeImageAttributeInput) (*request.Request, *ec2.DescribeImageAttributeOutput)
|
||||||
|
|
||||||
DescribeImageAttribute(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error)
|
DescribeImageAttribute(*ec2.DescribeImageAttributeInput) (*ec2.DescribeImageAttributeOutput, error)
|
||||||
|
@ -612,6 +624,14 @@ type EC2API interface {
|
||||||
|
|
||||||
ImportVolume(*ec2.ImportVolumeInput) (*ec2.ImportVolumeOutput, error)
|
ImportVolume(*ec2.ImportVolumeInput) (*ec2.ImportVolumeOutput, error)
|
||||||
|
|
||||||
|
ModifyHostsRequest(*ec2.ModifyHostsInput) (*request.Request, *ec2.ModifyHostsOutput)
|
||||||
|
|
||||||
|
ModifyHosts(*ec2.ModifyHostsInput) (*ec2.ModifyHostsOutput, error)
|
||||||
|
|
||||||
|
ModifyIdFormatRequest(*ec2.ModifyIdFormatInput) (*request.Request, *ec2.ModifyIdFormatOutput)
|
||||||
|
|
||||||
|
ModifyIdFormat(*ec2.ModifyIdFormatInput) (*ec2.ModifyIdFormatOutput, error)
|
||||||
|
|
||||||
ModifyImageAttributeRequest(*ec2.ModifyImageAttributeInput) (*request.Request, *ec2.ModifyImageAttributeOutput)
|
ModifyImageAttributeRequest(*ec2.ModifyImageAttributeInput) (*request.Request, *ec2.ModifyImageAttributeOutput)
|
||||||
|
|
||||||
ModifyImageAttribute(*ec2.ModifyImageAttributeInput) (*ec2.ModifyImageAttributeOutput, error)
|
ModifyImageAttribute(*ec2.ModifyImageAttributeInput) (*ec2.ModifyImageAttributeOutput, error)
|
||||||
|
@ -620,6 +640,10 @@ type EC2API interface {
|
||||||
|
|
||||||
ModifyInstanceAttribute(*ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error)
|
ModifyInstanceAttribute(*ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error)
|
||||||
|
|
||||||
|
ModifyInstancePlacementRequest(*ec2.ModifyInstancePlacementInput) (*request.Request, *ec2.ModifyInstancePlacementOutput)
|
||||||
|
|
||||||
|
ModifyInstancePlacement(*ec2.ModifyInstancePlacementInput) (*ec2.ModifyInstancePlacementOutput, error)
|
||||||
|
|
||||||
ModifyNetworkInterfaceAttributeRequest(*ec2.ModifyNetworkInterfaceAttributeInput) (*request.Request, *ec2.ModifyNetworkInterfaceAttributeOutput)
|
ModifyNetworkInterfaceAttributeRequest(*ec2.ModifyNetworkInterfaceAttributeInput) (*request.Request, *ec2.ModifyNetworkInterfaceAttributeOutput)
|
||||||
|
|
||||||
ModifyNetworkInterfaceAttribute(*ec2.ModifyNetworkInterfaceAttributeInput) (*ec2.ModifyNetworkInterfaceAttributeOutput, error)
|
ModifyNetworkInterfaceAttribute(*ec2.ModifyNetworkInterfaceAttributeInput) (*ec2.ModifyNetworkInterfaceAttributeOutput, error)
|
||||||
|
@ -680,6 +704,10 @@ type EC2API interface {
|
||||||
|
|
||||||
ReleaseAddress(*ec2.ReleaseAddressInput) (*ec2.ReleaseAddressOutput, error)
|
ReleaseAddress(*ec2.ReleaseAddressInput) (*ec2.ReleaseAddressOutput, error)
|
||||||
|
|
||||||
|
ReleaseHostsRequest(*ec2.ReleaseHostsInput) (*request.Request, *ec2.ReleaseHostsOutput)
|
||||||
|
|
||||||
|
ReleaseHosts(*ec2.ReleaseHostsInput) (*ec2.ReleaseHostsOutput, error)
|
||||||
|
|
||||||
ReplaceNetworkAclAssociationRequest(*ec2.ReplaceNetworkAclAssociationInput) (*request.Request, *ec2.ReplaceNetworkAclAssociationOutput)
|
ReplaceNetworkAclAssociationRequest(*ec2.ReplaceNetworkAclAssociationInput) (*request.Request, *ec2.ReplaceNetworkAclAssociationOutput)
|
||||||
|
|
||||||
ReplaceNetworkAclAssociation(*ec2.ReplaceNetworkAclAssociationInput) (*ec2.ReplaceNetworkAclAssociationOutput, error)
|
ReplaceNetworkAclAssociation(*ec2.ReplaceNetworkAclAssociationInput) (*ec2.ReplaceNetworkAclAssociationOutput, error)
|
||||||
|
|
1956
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam/api.go
generated
vendored
1956
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam/api.go
generated
vendored
File diff suppressed because it is too large
Load diff
1330
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/api.go
generated
vendored
1330
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/s3/api.go
generated
vendored
File diff suppressed because it is too large
Load diff
5
Godeps/_workspace/src/github.com/coreos/etcd/client/client.go
generated
vendored
5
Godeps/_workspace/src/github.com/coreos/etcd/client/client.go
generated
vendored
|
@ -378,9 +378,12 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hctx, hcancel := context.WithCancel(ctx)
|
var hctx context.Context
|
||||||
|
var hcancel context.CancelFunc
|
||||||
if c.headerTimeout > 0 {
|
if c.headerTimeout > 0 {
|
||||||
hctx, hcancel = context.WithTimeout(ctx, c.headerTimeout)
|
hctx, hcancel = context.WithTimeout(ctx, c.headerTimeout)
|
||||||
|
} else {
|
||||||
|
hctx, hcancel = context.WithCancel(ctx)
|
||||||
}
|
}
|
||||||
defer hcancel()
|
defer hcancel()
|
||||||
|
|
||||||
|
|
2
Godeps/_workspace/src/github.com/coreos/etcd/pkg/pathutil/path.go
generated
vendored
2
Godeps/_workspace/src/github.com/coreos/etcd/pkg/pathutil/path.go
generated
vendored
|
@ -2,6 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package pathutil implements utility functions for handling slash-separated
|
||||||
|
// paths.
|
||||||
package pathutil
|
package pathutil
|
||||||
|
|
||||||
import "path"
|
import "path"
|
||||||
|
|
1
Godeps/_workspace/src/github.com/fatih/structs/.travis.yml
generated
vendored
1
Godeps/_workspace/src/github.com/fatih/structs/.travis.yml
generated
vendored
|
@ -1,5 +1,6 @@
|
||||||
language: go
|
language: go
|
||||||
go: 1.5
|
go: 1.5
|
||||||
|
sudo: false
|
||||||
before_install:
|
before_install:
|
||||||
- go get github.com/axw/gocov/gocov
|
- go get github.com/axw/gocov/gocov
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
|
|
7
Godeps/_workspace/src/github.com/fatih/structs/field.go
generated
vendored
7
Godeps/_workspace/src/github.com/fatih/structs/field.go
generated
vendored
|
@ -84,6 +84,13 @@ func (f *Field) Set(val interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zero sets the field to its zero value. It returns an error if the field is not
|
||||||
|
// settable (not addressable or not exported).
|
||||||
|
func (f *Field) Zero() error {
|
||||||
|
zero := reflect.Zero(f.value.Type()).Interface()
|
||||||
|
return f.Set(zero)
|
||||||
|
}
|
||||||
|
|
||||||
// Fields returns a slice of Fields. This is particular handy to get the fields
|
// Fields returns a slice of Fields. This is particular handy to get the fields
|
||||||
// of a nested struct . A struct tag with the content of "-" ignores the
|
// of a nested struct . A struct tag with the content of "-" ignores the
|
||||||
// checking of that particular field. Example:
|
// checking of that particular field. Example:
|
||||||
|
|
7
Godeps/_workspace/src/github.com/fatih/structs/structs.go
generated
vendored
7
Godeps/_workspace/src/github.com/fatih/structs/structs.go
generated
vendored
|
@ -94,7 +94,12 @@ func (s *Struct) Map() map[string]interface{} {
|
||||||
// map[string]interface{} too
|
// map[string]interface{} too
|
||||||
n := New(val.Interface())
|
n := New(val.Interface())
|
||||||
n.TagName = s.TagName
|
n.TagName = s.TagName
|
||||||
finalVal = n.Map()
|
m := n.Map()
|
||||||
|
if len(m) == 0 {
|
||||||
|
finalVal = val.Interface()
|
||||||
|
} else {
|
||||||
|
finalVal = m
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
finalVal = val.Interface()
|
finalVal = val.Interface()
|
||||||
}
|
}
|
||||||
|
|
20
Godeps/_workspace/src/github.com/ghodss/yaml/.gitignore
generated
vendored
Normal file
20
Godeps/_workspace/src/github.com/ghodss/yaml/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# OSX leaves these everywhere on SMB shares
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Eclipse files
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/**
|
||||||
|
|
||||||
|
# Emacs save files
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Vim-related files
|
||||||
|
[._]*.s[a-w][a-z]
|
||||||
|
[._]s[a-w][a-z]
|
||||||
|
*.un~
|
||||||
|
Session.vim
|
||||||
|
.netrwhist
|
||||||
|
|
||||||
|
# Go test binaries
|
||||||
|
*.test
|
7
Godeps/_workspace/src/github.com/ghodss/yaml/.travis.yml
generated
vendored
Normal file
7
Godeps/_workspace/src/github.com/ghodss/yaml/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
|
script:
|
||||||
|
- go test
|
||||||
|
- go build
|
50
Godeps/_workspace/src/github.com/ghodss/yaml/LICENSE
generated
vendored
Normal file
50
Godeps/_workspace/src/github.com/ghodss/yaml/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Sam Ghods
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2012 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.
|
116
Godeps/_workspace/src/github.com/ghodss/yaml/README.md
generated
vendored
Normal file
116
Godeps/_workspace/src/github.com/ghodss/yaml/README.md
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
# YAML marshaling and unmarshaling support for Go
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/ghodss/yaml.svg)](https://travis-ci.org/ghodss/yaml)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
A wrapper around [go-yaml](https://github.com/go-yaml/yaml) designed to enable a better way of handling YAML when marshaling to and from structs.
|
||||||
|
|
||||||
|
In short, this library first converts YAML to JSON using go-yaml and then uses `json.Marshal` and `json.Unmarshal` to convert to or from the struct. This means that it effectively reuses the JSON struct tags as well as the custom JSON methods `MarshalJSON` and `UnmarshalJSON` unlike go-yaml. For a detailed overview of the rationale behind this method, [see this blog post](http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/).
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
This package uses [go-yaml v2](https://github.com/go-yaml/yaml) and therefore supports [everything go-yaml supports](https://github.com/go-yaml/yaml#compatibility).
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
**Caveat #1:** When using `yaml.Marshal` and `yaml.Unmarshal`, binary data should NOT be preceded with the `!!binary` YAML tag. If you do, go-yaml will convert the binary data from base64 to native binary data, which is not compatible with JSON. You can still use binary in your YAML files though - just store them without the `!!binary` tag and decode the base64 in your code (e.g. in the custom JSON methods `MarshalJSON` and `UnmarshalJSON`). This also has the benefit that your YAML and your JSON binary data will be decoded exactly the same way. As an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
BAD:
|
||||||
|
exampleKey: !!binary gIGC
|
||||||
|
|
||||||
|
GOOD:
|
||||||
|
exampleKey: gIGC
|
||||||
|
... and decode the base64 data in your code.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Caveat #2:** When using `YAMLToJSON` directly, maps with keys that are maps will result in an error since this is not supported by JSON. This error will occur in `Unmarshal` as well since you can't unmarshal map keys anyways since struct fields can't be keys.
|
||||||
|
|
||||||
|
## Installation and usage
|
||||||
|
|
||||||
|
To install, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get github.com/ghodss/yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
And import using:
|
||||||
|
|
||||||
|
```
|
||||||
|
import "github.com/ghodss/yaml"
|
||||||
|
```
|
||||||
|
|
||||||
|
Usage is very similar to the JSON library:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ghodss/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Name string `json:"name"` // Affects YAML field names too.
|
||||||
|
Age int `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Marshal a Person struct to YAML.
|
||||||
|
p := Person{"John", 30}
|
||||||
|
y, err := yaml.Marshal(p)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(string(y))
|
||||||
|
/* Output:
|
||||||
|
name: John
|
||||||
|
age: 30
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Unmarshal the YAML back into a Person struct.
|
||||||
|
var p2 Person
|
||||||
|
err := yaml.Unmarshal(y, &p2)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(p2)
|
||||||
|
/* Output:
|
||||||
|
{John 30}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`yaml.YAMLToJSON` and `yaml.JSONToYAML` methods are also available:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ghodss/yaml"
|
||||||
|
)
|
||||||
|
func main() {
|
||||||
|
j := []byte(`{"name": "John", "age": 30}`)
|
||||||
|
y, err := yaml.JSONToYAML(j)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(string(y))
|
||||||
|
/* Output:
|
||||||
|
name: John
|
||||||
|
age: 30
|
||||||
|
*/
|
||||||
|
j2, err := yaml.YAMLToJSON(y)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(string(j2))
|
||||||
|
/* Output:
|
||||||
|
{"age":30,"name":"John"}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
```
|
497
Godeps/_workspace/src/github.com/ghodss/yaml/fields.go
generated
vendored
Normal file
497
Godeps/_workspace/src/github.com/ghodss/yaml/fields.go
generated
vendored
Normal file
|
@ -0,0 +1,497 @@
|
||||||
|
// 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 yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// indirect walks down v allocating pointers as needed,
|
||||||
|
// until it gets to a non-pointer.
|
||||||
|
// if it encounters an Unmarshaler, indirect stops and returns that.
|
||||||
|
// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
|
||||||
|
func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
|
||||||
|
// If v is a named type and is addressable,
|
||||||
|
// start with its address, so that if the type has pointer methods,
|
||||||
|
// we find them.
|
||||||
|
if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() {
|
||||||
|
v = v.Addr()
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
// Load value from interface, but only if the result will be
|
||||||
|
// usefully addressable.
|
||||||
|
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||||
|
e := v.Elem()
|
||||||
|
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||||
|
v = e
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Kind() != reflect.Ptr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.IsNil() {
|
||||||
|
v.Set(reflect.New(v.Type().Elem()))
|
||||||
|
}
|
||||||
|
if v.Type().NumMethod() > 0 {
|
||||||
|
if u, ok := v.Interface().(json.Unmarshaler); ok {
|
||||||
|
return u, nil, reflect.Value{}
|
||||||
|
}
|
||||||
|
if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
|
||||||
|
return nil, u, reflect.Value{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
return nil, nil, v
|
||||||
|
}
|
||||||
|
|
||||||
|
// A field represents a single field found in a struct.
|
||||||
|
type field struct {
|
||||||
|
name string
|
||||||
|
nameBytes []byte // []byte(name)
|
||||||
|
equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
|
||||||
|
|
||||||
|
tag bool
|
||||||
|
index []int
|
||||||
|
typ reflect.Type
|
||||||
|
omitEmpty bool
|
||||||
|
quoted bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillField(f field) field {
|
||||||
|
f.nameBytes = []byte(f.name)
|
||||||
|
f.equalFold = foldFunc(f.nameBytes)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// byName sorts field by name, breaking ties with depth,
|
||||||
|
// then breaking ties with "name came from json tag", then
|
||||||
|
// breaking ties with index sequence.
|
||||||
|
type byName []field
|
||||||
|
|
||||||
|
func (x byName) Len() int { return len(x) }
|
||||||
|
|
||||||
|
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
|
|
||||||
|
func (x byName) Less(i, j int) bool {
|
||||||
|
if x[i].name != x[j].name {
|
||||||
|
return x[i].name < x[j].name
|
||||||
|
}
|
||||||
|
if len(x[i].index) != len(x[j].index) {
|
||||||
|
return len(x[i].index) < len(x[j].index)
|
||||||
|
}
|
||||||
|
if x[i].tag != x[j].tag {
|
||||||
|
return x[i].tag
|
||||||
|
}
|
||||||
|
return byIndex(x).Less(i, j)
|
||||||
|
}
|
||||||
|
|
||||||
|
// byIndex sorts field by index sequence.
|
||||||
|
type byIndex []field
|
||||||
|
|
||||||
|
func (x byIndex) Len() int { return len(x) }
|
||||||
|
|
||||||
|
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||||
|
|
||||||
|
func (x byIndex) Less(i, j int) bool {
|
||||||
|
for k, xik := range x[i].index {
|
||||||
|
if k >= len(x[j].index) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if xik != x[j].index[k] {
|
||||||
|
return xik < x[j].index[k]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(x[i].index) < len(x[j].index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeFields returns a list of fields that JSON should recognize for the given type.
|
||||||
|
// The algorithm is breadth-first search over the set of structs to include - the top struct
|
||||||
|
// and then any reachable anonymous structs.
|
||||||
|
func typeFields(t reflect.Type) []field {
|
||||||
|
// Anonymous fields to explore at the current level and the next.
|
||||||
|
current := []field{}
|
||||||
|
next := []field{{typ: t}}
|
||||||
|
|
||||||
|
// Count of queued names for current level and the next.
|
||||||
|
count := map[reflect.Type]int{}
|
||||||
|
nextCount := map[reflect.Type]int{}
|
||||||
|
|
||||||
|
// Types already visited at an earlier level.
|
||||||
|
visited := map[reflect.Type]bool{}
|
||||||
|
|
||||||
|
// Fields found.
|
||||||
|
var fields []field
|
||||||
|
|
||||||
|
for len(next) > 0 {
|
||||||
|
current, next = next, current[:0]
|
||||||
|
count, nextCount = nextCount, map[reflect.Type]int{}
|
||||||
|
|
||||||
|
for _, f := range current {
|
||||||
|
if visited[f.typ] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
visited[f.typ] = true
|
||||||
|
|
||||||
|
// Scan f.typ for fields to include.
|
||||||
|
for i := 0; i < f.typ.NumField(); i++ {
|
||||||
|
sf := f.typ.Field(i)
|
||||||
|
if sf.PkgPath != "" { // unexported
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tag := sf.Tag.Get("json")
|
||||||
|
if tag == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, opts := parseTag(tag)
|
||||||
|
if !isValidTag(name) {
|
||||||
|
name = ""
|
||||||
|
}
|
||||||
|
index := make([]int, len(f.index)+1)
|
||||||
|
copy(index, f.index)
|
||||||
|
index[len(f.index)] = i
|
||||||
|
|
||||||
|
ft := sf.Type
|
||||||
|
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
||||||
|
// Follow pointer.
|
||||||
|
ft = ft.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record found field and index sequence.
|
||||||
|
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||||
|
tagged := name != ""
|
||||||
|
if name == "" {
|
||||||
|
name = sf.Name
|
||||||
|
}
|
||||||
|
fields = append(fields, fillField(field{
|
||||||
|
name: name,
|
||||||
|
tag: tagged,
|
||||||
|
index: index,
|
||||||
|
typ: ft,
|
||||||
|
omitEmpty: opts.Contains("omitempty"),
|
||||||
|
quoted: opts.Contains("string"),
|
||||||
|
}))
|
||||||
|
if count[f.typ] > 1 {
|
||||||
|
// If there were multiple instances, add a second,
|
||||||
|
// so that the annihilation code will see a duplicate.
|
||||||
|
// It only cares about the distinction between 1 or 2,
|
||||||
|
// so don't bother generating any more copies.
|
||||||
|
fields = append(fields, fields[len(fields)-1])
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record new anonymous struct to explore in next round.
|
||||||
|
nextCount[ft]++
|
||||||
|
if nextCount[ft] == 1 {
|
||||||
|
next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(byName(fields))
|
||||||
|
|
||||||
|
// Delete all fields that are hidden by the Go rules for embedded fields,
|
||||||
|
// except that fields with JSON tags are promoted.
|
||||||
|
|
||||||
|
// The fields are sorted in primary order of name, secondary order
|
||||||
|
// of field index length. Loop over names; for each name, delete
|
||||||
|
// hidden fields by choosing the one dominant field that survives.
|
||||||
|
out := fields[:0]
|
||||||
|
for advance, i := 0, 0; i < len(fields); i += advance {
|
||||||
|
// One iteration per name.
|
||||||
|
// Find the sequence of fields with the name of this first field.
|
||||||
|
fi := fields[i]
|
||||||
|
name := fi.name
|
||||||
|
for advance = 1; i+advance < len(fields); advance++ {
|
||||||
|
fj := fields[i+advance]
|
||||||
|
if fj.name != name {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if advance == 1 { // Only one field with this name
|
||||||
|
out = append(out, fi)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dominant, ok := dominantField(fields[i : i+advance])
|
||||||
|
if ok {
|
||||||
|
out = append(out, dominant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = out
|
||||||
|
sort.Sort(byIndex(fields))
|
||||||
|
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// dominantField looks through the fields, all of which are known to
|
||||||
|
// have the same name, to find the single field that dominates the
|
||||||
|
// others using Go's embedding rules, modified by the presence of
|
||||||
|
// JSON tags. If there are multiple top-level fields, the boolean
|
||||||
|
// will be false: This condition is an error in Go and we skip all
|
||||||
|
// the fields.
|
||||||
|
func dominantField(fields []field) (field, bool) {
|
||||||
|
// The fields are sorted in increasing index-length order. The winner
|
||||||
|
// must therefore be one with the shortest index length. Drop all
|
||||||
|
// longer entries, which is easy: just truncate the slice.
|
||||||
|
length := len(fields[0].index)
|
||||||
|
tagged := -1 // Index of first tagged field.
|
||||||
|
for i, f := range fields {
|
||||||
|
if len(f.index) > length {
|
||||||
|
fields = fields[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if f.tag {
|
||||||
|
if tagged >= 0 {
|
||||||
|
// Multiple tagged fields at the same level: conflict.
|
||||||
|
// Return no field.
|
||||||
|
return field{}, false
|
||||||
|
}
|
||||||
|
tagged = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tagged >= 0 {
|
||||||
|
return fields[tagged], true
|
||||||
|
}
|
||||||
|
// All remaining fields have the same length. If there's more than one,
|
||||||
|
// we have a conflict (two fields named "X" at the same level) and we
|
||||||
|
// return no field.
|
||||||
|
if len(fields) > 1 {
|
||||||
|
return field{}, false
|
||||||
|
}
|
||||||
|
return fields[0], true
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldCache struct {
|
||||||
|
sync.RWMutex
|
||||||
|
m map[reflect.Type][]field
|
||||||
|
}
|
||||||
|
|
||||||
|
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
|
||||||
|
func cachedTypeFields(t reflect.Type) []field {
|
||||||
|
fieldCache.RLock()
|
||||||
|
f := fieldCache.m[t]
|
||||||
|
fieldCache.RUnlock()
|
||||||
|
if f != nil {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute fields without lock.
|
||||||
|
// Might duplicate effort but won't hold other computations back.
|
||||||
|
f = typeFields(t)
|
||||||
|
if f == nil {
|
||||||
|
f = []field{}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldCache.Lock()
|
||||||
|
if fieldCache.m == nil {
|
||||||
|
fieldCache.m = map[reflect.Type][]field{}
|
||||||
|
}
|
||||||
|
fieldCache.m[t] = f
|
||||||
|
fieldCache.Unlock()
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidTag(s string) bool {
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
switch {
|
||||||
|
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
|
||||||
|
// Backslash and quote chars are reserved, but
|
||||||
|
// otherwise any punctuation chars are allowed
|
||||||
|
// in a tag name.
|
||||||
|
default:
|
||||||
|
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
|
||||||
|
kelvin = '\u212a'
|
||||||
|
smallLongEss = '\u017f'
|
||||||
|
)
|
||||||
|
|
||||||
|
// foldFunc returns one of four different case folding equivalence
|
||||||
|
// functions, from most general (and slow) to fastest:
|
||||||
|
//
|
||||||
|
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
|
||||||
|
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
|
||||||
|
// 3) asciiEqualFold, no special, but includes non-letters (including _)
|
||||||
|
// 4) simpleLetterEqualFold, no specials, no non-letters.
|
||||||
|
//
|
||||||
|
// The letters S and K are special because they map to 3 runes, not just 2:
|
||||||
|
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||||
|
// * k maps to K and to U+212A 'K' Kelvin sign
|
||||||
|
// See http://play.golang.org/p/tTxjOc0OGo
|
||||||
|
//
|
||||||
|
// The returned function is specialized for matching against s and
|
||||||
|
// should only be given s. It's not curried for performance reasons.
|
||||||
|
func foldFunc(s []byte) func(s, t []byte) bool {
|
||||||
|
nonLetter := false
|
||||||
|
special := false // special letter
|
||||||
|
for _, b := range s {
|
||||||
|
if b >= utf8.RuneSelf {
|
||||||
|
return bytes.EqualFold
|
||||||
|
}
|
||||||
|
upper := b & caseMask
|
||||||
|
if upper < 'A' || upper > 'Z' {
|
||||||
|
nonLetter = true
|
||||||
|
} else if upper == 'K' || upper == 'S' {
|
||||||
|
// See above for why these letters are special.
|
||||||
|
special = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if special {
|
||||||
|
return equalFoldRight
|
||||||
|
}
|
||||||
|
if nonLetter {
|
||||||
|
return asciiEqualFold
|
||||||
|
}
|
||||||
|
return simpleLetterEqualFold
|
||||||
|
}
|
||||||
|
|
||||||
|
// equalFoldRight is a specialization of bytes.EqualFold when s is
|
||||||
|
// known to be all ASCII (including punctuation), but contains an 's',
|
||||||
|
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
|
||||||
|
// See comments on foldFunc.
|
||||||
|
func equalFoldRight(s, t []byte) bool {
|
||||||
|
for _, sb := range s {
|
||||||
|
if len(t) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tb := t[0]
|
||||||
|
if tb < utf8.RuneSelf {
|
||||||
|
if sb != tb {
|
||||||
|
sbUpper := sb & caseMask
|
||||||
|
if 'A' <= sbUpper && sbUpper <= 'Z' {
|
||||||
|
if sbUpper != tb&caseMask {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t = t[1:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// sb is ASCII and t is not. t must be either kelvin
|
||||||
|
// sign or long s; sb must be s, S, k, or K.
|
||||||
|
tr, size := utf8.DecodeRune(t)
|
||||||
|
switch sb {
|
||||||
|
case 's', 'S':
|
||||||
|
if tr != smallLongEss {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case 'k', 'K':
|
||||||
|
if tr != kelvin {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
t = t[size:]
|
||||||
|
|
||||||
|
}
|
||||||
|
if len(t) > 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// asciiEqualFold is a specialization of bytes.EqualFold for use when
|
||||||
|
// s is all ASCII (but may contain non-letters) and contains no
|
||||||
|
// special-folding letters.
|
||||||
|
// See comments on foldFunc.
|
||||||
|
func asciiEqualFold(s, t []byte) bool {
|
||||||
|
if len(s) != len(t) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, sb := range s {
|
||||||
|
tb := t[i]
|
||||||
|
if sb == tb {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
|
||||||
|
if sb&caseMask != tb&caseMask {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
|
||||||
|
// use when s is all ASCII letters (no underscores, etc) and also
|
||||||
|
// doesn't contain 'k', 'K', 's', or 'S'.
|
||||||
|
// See comments on foldFunc.
|
||||||
|
func simpleLetterEqualFold(s, t []byte) bool {
|
||||||
|
if len(s) != len(t) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, b := range s {
|
||||||
|
if b&caseMask != t[i]&caseMask {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// tagOptions is the string following a comma in a struct field's "json"
|
||||||
|
// tag, or the empty string. It does not include the leading comma.
|
||||||
|
type tagOptions string
|
||||||
|
|
||||||
|
// parseTag splits a struct field's json tag into its name and
|
||||||
|
// comma-separated options.
|
||||||
|
func parseTag(tag string) (string, tagOptions) {
|
||||||
|
if idx := strings.Index(tag, ","); idx != -1 {
|
||||||
|
return tag[:idx], tagOptions(tag[idx+1:])
|
||||||
|
}
|
||||||
|
return tag, tagOptions("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains reports whether a comma-separated list of options
|
||||||
|
// contains a particular substr flag. substr must be surrounded by a
|
||||||
|
// string boundary or commas.
|
||||||
|
func (o tagOptions) Contains(optionName string) bool {
|
||||||
|
if len(o) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s := string(o)
|
||||||
|
for s != "" {
|
||||||
|
var next string
|
||||||
|
i := strings.Index(s, ",")
|
||||||
|
if i >= 0 {
|
||||||
|
s, next = s[:i], s[i+1:]
|
||||||
|
}
|
||||||
|
if s == optionName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
s = next
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
277
Godeps/_workspace/src/github.com/ghodss/yaml/yaml.go
generated
vendored
Normal file
277
Godeps/_workspace/src/github.com/ghodss/yaml/yaml.go
generated
vendored
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Marshals the object into JSON then converts JSON to YAML and returns the
|
||||||
|
// YAML.
|
||||||
|
func Marshal(o interface{}) ([]byte, error) {
|
||||||
|
j, err := json.Marshal(o)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error marshaling into JSON: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
y, err := JSONToYAML(j)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error converting JSON to YAML: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return y, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts YAML to JSON then uses JSON to unmarshal into an object.
|
||||||
|
func Unmarshal(y []byte, o interface{}) error {
|
||||||
|
vo := reflect.ValueOf(o)
|
||||||
|
j, err := yamlToJSON(y, &vo)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error converting YAML to JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(j, o)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error unmarshaling JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert JSON to YAML.
|
||||||
|
func JSONToYAML(j []byte) ([]byte, error) {
|
||||||
|
// Convert the JSON to an object.
|
||||||
|
var jsonObj interface{}
|
||||||
|
// We are using yaml.Unmarshal here (instead of json.Unmarshal) because the
|
||||||
|
// Go JSON library doesn't try to pick the right number type (int, float,
|
||||||
|
// etc.) when unmarshling to interface{}, it just picks float64
|
||||||
|
// universally. go-yaml does go through the effort of picking the right
|
||||||
|
// number type, so we can preserve number type throughout this process.
|
||||||
|
err := yaml.Unmarshal(j, &jsonObj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal this object into YAML.
|
||||||
|
return yaml.Marshal(jsonObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert YAML to JSON. Since JSON is a subset of YAML, passing JSON through
|
||||||
|
// this method should be a no-op.
|
||||||
|
//
|
||||||
|
// Things YAML can do that are not supported by JSON:
|
||||||
|
// * In YAML you can have binary and null keys in your maps. These are invalid
|
||||||
|
// in JSON. (int and float keys are converted to strings.)
|
||||||
|
// * Binary data in YAML with the !!binary tag is not supported. If you want to
|
||||||
|
// use binary data with this library, encode the data as base64 as usual but do
|
||||||
|
// not use the !!binary tag in your YAML. This will ensure the original base64
|
||||||
|
// encoded data makes it all the way through to the JSON.
|
||||||
|
func YAMLToJSON(y []byte) ([]byte, error) {
|
||||||
|
return yamlToJSON(y, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) {
|
||||||
|
// Convert the YAML to an object.
|
||||||
|
var yamlObj interface{}
|
||||||
|
err := yaml.Unmarshal(y, &yamlObj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// YAML objects are not completely compatible with JSON objects (e.g. you
|
||||||
|
// can have non-string keys in YAML). So, convert the YAML-compatible object
|
||||||
|
// to a JSON-compatible object, failing with an error if irrecoverable
|
||||||
|
// incompatibilties happen along the way.
|
||||||
|
jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert this object to JSON and return the data.
|
||||||
|
return json.Marshal(jsonObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Resolve jsonTarget to a concrete value (i.e. not a pointer or an
|
||||||
|
// interface). We pass decodingNull as false because we're not actually
|
||||||
|
// decoding into the value, we're just checking if the ultimate target is a
|
||||||
|
// string.
|
||||||
|
if jsonTarget != nil {
|
||||||
|
ju, tu, pv := indirect(*jsonTarget, false)
|
||||||
|
// We have a JSON or Text Umarshaler at this level, so we can't be trying
|
||||||
|
// to decode into a string.
|
||||||
|
if ju != nil || tu != nil {
|
||||||
|
jsonTarget = nil
|
||||||
|
} else {
|
||||||
|
jsonTarget = &pv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If yamlObj is a number or a boolean, check if jsonTarget is a string -
|
||||||
|
// if so, coerce. Else return normal.
|
||||||
|
// If yamlObj is a map or array, find the field that each key is
|
||||||
|
// unmarshaling to, and when you recurse pass the reflect.Value for that
|
||||||
|
// field back into this function.
|
||||||
|
switch typedYAMLObj := yamlObj.(type) {
|
||||||
|
case map[interface{}]interface{}:
|
||||||
|
// JSON does not support arbitrary keys in a map, so we must convert
|
||||||
|
// these keys to strings.
|
||||||
|
//
|
||||||
|
// From my reading of go-yaml v2 (specifically the resolve function),
|
||||||
|
// keys can only have the types string, int, int64, float64, binary
|
||||||
|
// (unsupported), or null (unsupported).
|
||||||
|
strMap := make(map[string]interface{})
|
||||||
|
for k, v := range typedYAMLObj {
|
||||||
|
// Resolve the key to a string first.
|
||||||
|
var keyString string
|
||||||
|
switch typedKey := k.(type) {
|
||||||
|
case string:
|
||||||
|
keyString = typedKey
|
||||||
|
case int:
|
||||||
|
keyString = strconv.Itoa(typedKey)
|
||||||
|
case int64:
|
||||||
|
// go-yaml will only return an int64 as a key if the system
|
||||||
|
// architecture is 32-bit and the key's value is between 32-bit
|
||||||
|
// and 64-bit. Otherwise the key type will simply be int.
|
||||||
|
keyString = strconv.FormatInt(typedKey, 10)
|
||||||
|
case float64:
|
||||||
|
// Stolen from go-yaml to use the same conversion to string as
|
||||||
|
// the go-yaml library uses to convert float to string when
|
||||||
|
// Marshaling.
|
||||||
|
s := strconv.FormatFloat(typedKey, 'g', -1, 32)
|
||||||
|
switch s {
|
||||||
|
case "+Inf":
|
||||||
|
s = ".inf"
|
||||||
|
case "-Inf":
|
||||||
|
s = "-.inf"
|
||||||
|
case "NaN":
|
||||||
|
s = ".nan"
|
||||||
|
}
|
||||||
|
keyString = s
|
||||||
|
case bool:
|
||||||
|
if typedKey {
|
||||||
|
keyString = "true"
|
||||||
|
} else {
|
||||||
|
keyString = "false"
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v",
|
||||||
|
reflect.TypeOf(k), k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// jsonTarget should be a struct or a map. If it's a struct, find
|
||||||
|
// the field it's going to map to and pass its reflect.Value. If
|
||||||
|
// it's a map, find the element type of the map and pass the
|
||||||
|
// reflect.Value created from that type. If it's neither, just pass
|
||||||
|
// nil - JSON conversion will error for us if it's a real issue.
|
||||||
|
if jsonTarget != nil {
|
||||||
|
t := *jsonTarget
|
||||||
|
if t.Kind() == reflect.Struct {
|
||||||
|
keyBytes := []byte(keyString)
|
||||||
|
// Find the field that the JSON library would use.
|
||||||
|
var f *field
|
||||||
|
fields := cachedTypeFields(t.Type())
|
||||||
|
for i := range fields {
|
||||||
|
ff := &fields[i]
|
||||||
|
if bytes.Equal(ff.nameBytes, keyBytes) {
|
||||||
|
f = ff
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Do case-insensitive comparison.
|
||||||
|
if f == nil && ff.equalFold(ff.nameBytes, keyBytes) {
|
||||||
|
f = ff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if f != nil {
|
||||||
|
// Find the reflect.Value of the most preferential
|
||||||
|
// struct field.
|
||||||
|
jtf := t.Field(f.index[0])
|
||||||
|
strMap[keyString], err = convertToJSONableObject(v, &jtf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if t.Kind() == reflect.Map {
|
||||||
|
// Create a zero value of the map's element type to use as
|
||||||
|
// the JSON target.
|
||||||
|
jtv := reflect.Zero(t.Type().Elem())
|
||||||
|
strMap[keyString], err = convertToJSONableObject(v, &jtv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strMap[keyString], err = convertToJSONableObject(v, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strMap, nil
|
||||||
|
case []interface{}:
|
||||||
|
// We need to recurse into arrays in case there are any
|
||||||
|
// map[interface{}]interface{}'s inside and to convert any
|
||||||
|
// numbers to strings.
|
||||||
|
|
||||||
|
// If jsonTarget is a slice (which it really should be), find the
|
||||||
|
// thing it's going to map to. If it's not a slice, just pass nil
|
||||||
|
// - JSON conversion will error for us if it's a real issue.
|
||||||
|
var jsonSliceElemValue *reflect.Value
|
||||||
|
if jsonTarget != nil {
|
||||||
|
t := *jsonTarget
|
||||||
|
if t.Kind() == reflect.Slice {
|
||||||
|
// By default slices point to nil, but we need a reflect.Value
|
||||||
|
// pointing to a value of the slice type, so we create one here.
|
||||||
|
ev := reflect.Indirect(reflect.New(t.Type().Elem()))
|
||||||
|
jsonSliceElemValue = &ev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make and use a new array.
|
||||||
|
arr := make([]interface{}, len(typedYAMLObj))
|
||||||
|
for i, v := range typedYAMLObj {
|
||||||
|
arr[i], err = convertToJSONableObject(v, jsonSliceElemValue)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr, nil
|
||||||
|
default:
|
||||||
|
// If the target type is a string and the YAML type is a number,
|
||||||
|
// convert the YAML type to a string.
|
||||||
|
if jsonTarget != nil && (*jsonTarget).Kind() == reflect.String {
|
||||||
|
// Based on my reading of go-yaml, it may return int, int64,
|
||||||
|
// float64, or uint64.
|
||||||
|
var s string
|
||||||
|
switch typedVal := typedYAMLObj.(type) {
|
||||||
|
case int:
|
||||||
|
s = strconv.FormatInt(int64(typedVal), 10)
|
||||||
|
case int64:
|
||||||
|
s = strconv.FormatInt(typedVal, 10)
|
||||||
|
case float64:
|
||||||
|
s = strconv.FormatFloat(typedVal, 'g', -1, 32)
|
||||||
|
case uint64:
|
||||||
|
s = strconv.FormatUint(typedVal, 10)
|
||||||
|
case bool:
|
||||||
|
if typedVal {
|
||||||
|
s = "true"
|
||||||
|
} else {
|
||||||
|
s = "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(s) > 0 {
|
||||||
|
yamlObj = interface{}(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return yamlObj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
20
Godeps/_workspace/src/github.com/go-ini/ini/README.md
generated
vendored
20
Godeps/_workspace/src/github.com/go-ini/ini/README.md
generated
vendored
|
@ -95,6 +95,12 @@ Same rule applies to key operations:
|
||||||
key := cfg.Section("").Key("key name")
|
key := cfg.Section("").Key("key name")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To check if a key exists:
|
||||||
|
|
||||||
|
```go
|
||||||
|
yes := cfg.Section("").HasKey("key name")
|
||||||
|
```
|
||||||
|
|
||||||
To create a new key:
|
To create a new key:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -133,6 +139,18 @@ val := cfg.Section("").Key("key name").Validate(func(in string) string {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you do not want any auto-transformation (such as recursive read) for the values, you can get raw value directly (this way you get much better performance):
|
||||||
|
|
||||||
|
```go
|
||||||
|
val := cfg.Section("").Key("key name").Value()
|
||||||
|
```
|
||||||
|
|
||||||
|
To check if raw value exists:
|
||||||
|
|
||||||
|
```go
|
||||||
|
yes := cfg.Section("").HasValue("test value")
|
||||||
|
```
|
||||||
|
|
||||||
To get value with types:
|
To get value with types:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -464,7 +482,7 @@ type Info struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
|
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini"))
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
||||||
|
|
20
Godeps/_workspace/src/github.com/go-ini/ini/README_ZH.md
generated
vendored
20
Godeps/_workspace/src/github.com/go-ini/ini/README_ZH.md
generated
vendored
|
@ -88,6 +88,12 @@ key, err := cfg.Section("").GetKey("key name")
|
||||||
key := cfg.Section("").Key("key name")
|
key := cfg.Section("").Key("key name")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
判断某个键是否存在:
|
||||||
|
|
||||||
|
```go
|
||||||
|
yes := cfg.Section("").HasKey("key name")
|
||||||
|
```
|
||||||
|
|
||||||
创建一个新的键:
|
创建一个新的键:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -126,6 +132,18 @@ val := cfg.Section("").Key("key name").Validate(func(in string) string {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
如果您不需要任何对值的自动转变功能(例如递归读取),可以直接获取原值(这种方式性能最佳):
|
||||||
|
|
||||||
|
```go
|
||||||
|
val := cfg.Section("").Key("key name").Value()
|
||||||
|
```
|
||||||
|
|
||||||
|
判断某个原值是否存在:
|
||||||
|
|
||||||
|
```go
|
||||||
|
yes := cfg.Section("").HasValue("test value")
|
||||||
|
```
|
||||||
|
|
||||||
获取其它类型的值:
|
获取其它类型的值:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -455,7 +473,7 @@ type Info struct{
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
|
err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini"))
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
|
||||||
|
|
28
Godeps/_workspace/src/github.com/go-ini/ini/ini.go
generated
vendored
28
Godeps/_workspace/src/github.com/go-ini/ini/ini.go
generated
vendored
|
@ -35,7 +35,7 @@ const (
|
||||||
// Maximum allowed depth when recursively substituing variable names.
|
// Maximum allowed depth when recursively substituing variable names.
|
||||||
_DEPTH_VALUES = 99
|
_DEPTH_VALUES = 99
|
||||||
|
|
||||||
_VERSION = "1.6.0"
|
_VERSION = "1.7.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Version() string {
|
func Version() string {
|
||||||
|
@ -618,6 +618,27 @@ func (s *Section) GetKey(name string) (*Key, error) {
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasKey returns true if section contains a key with given name.
|
||||||
|
func (s *Section) Haskey(name string) bool {
|
||||||
|
key, _ := s.GetKey(name)
|
||||||
|
return key != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasKey returns true if section contains given raw value.
|
||||||
|
func (s *Section) HasValue(value string) bool {
|
||||||
|
if s.f.BlockMode {
|
||||||
|
s.f.lock.RLock()
|
||||||
|
defer s.f.lock.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range s.keys {
|
||||||
|
if value == k.value {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Key assumes named Key exists in section and returns a zero-value when not.
|
// Key assumes named Key exists in section and returns a zero-value when not.
|
||||||
func (s *Section) Key(name string) *Key {
|
func (s *Section) Key(name string) *Key {
|
||||||
key, err := s.GetKey(name)
|
key, err := s.GetKey(name)
|
||||||
|
@ -737,7 +758,10 @@ func Load(source interface{}, others ...interface{}) (_ *File, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f := newFile(sources)
|
f := newFile(sources)
|
||||||
return f, f.Reload()
|
if err = f.Reload(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty returns an empty file object.
|
// Empty returns an empty file object.
|
||||||
|
|
248
Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go
generated
vendored
248
Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go
generated
vendored
|
@ -53,6 +53,20 @@ var FilterSubstringsMap = map[uint64]string{
|
||||||
FilterSubstringsFinal: "Substrings Final",
|
FilterSubstringsFinal: "Substrings Final",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
MatchingRuleAssertionMatchingRule = 1
|
||||||
|
MatchingRuleAssertionType = 2
|
||||||
|
MatchingRuleAssertionMatchValue = 3
|
||||||
|
MatchingRuleAssertionDNAttributes = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
var MatchingRuleAssertionMap = map[uint64]string{
|
||||||
|
MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule",
|
||||||
|
MatchingRuleAssertionType: "Matching Rule Assertion Type",
|
||||||
|
MatchingRuleAssertionMatchValue: "Matching Rule Assertion Match Value",
|
||||||
|
MatchingRuleAssertionDNAttributes: "Matching Rule Assertion DN Attributes",
|
||||||
|
}
|
||||||
|
|
||||||
func CompileFilter(filter string) (*ber.Packet, error) {
|
func CompileFilter(filter string) (*ber.Packet, error) {
|
||||||
if len(filter) == 0 || filter[0] != '(' {
|
if len(filter) == 0 || filter[0] != '(' {
|
||||||
return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
|
return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
|
||||||
|
@ -111,7 +125,7 @@ func DecompileFilter(packet *ber.Packet) (ret string, err error) {
|
||||||
if i == 0 && child.Tag != FilterSubstringsInitial {
|
if i == 0 && child.Tag != FilterSubstringsInitial {
|
||||||
ret += "*"
|
ret += "*"
|
||||||
}
|
}
|
||||||
ret += ber.DecodeString(child.Data.Bytes())
|
ret += EscapeFilter(ber.DecodeString(child.Data.Bytes()))
|
||||||
if child.Tag != FilterSubstringsFinal {
|
if child.Tag != FilterSubstringsFinal {
|
||||||
ret += "*"
|
ret += "*"
|
||||||
}
|
}
|
||||||
|
@ -135,6 +149,37 @@ func DecompileFilter(packet *ber.Packet) (ret string, err error) {
|
||||||
ret += ber.DecodeString(packet.Children[0].Data.Bytes())
|
ret += ber.DecodeString(packet.Children[0].Data.Bytes())
|
||||||
ret += "~="
|
ret += "~="
|
||||||
ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
|
ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
|
||||||
|
case FilterExtensibleMatch:
|
||||||
|
attr := ""
|
||||||
|
dnAttributes := false
|
||||||
|
matchingRule := ""
|
||||||
|
value := ""
|
||||||
|
|
||||||
|
for _, child := range packet.Children {
|
||||||
|
switch child.Tag {
|
||||||
|
case MatchingRuleAssertionMatchingRule:
|
||||||
|
matchingRule = ber.DecodeString(child.Data.Bytes())
|
||||||
|
case MatchingRuleAssertionType:
|
||||||
|
attr = ber.DecodeString(child.Data.Bytes())
|
||||||
|
case MatchingRuleAssertionMatchValue:
|
||||||
|
value = ber.DecodeString(child.Data.Bytes())
|
||||||
|
case MatchingRuleAssertionDNAttributes:
|
||||||
|
dnAttributes = child.Value.(bool)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(attr) > 0 {
|
||||||
|
ret += attr
|
||||||
|
}
|
||||||
|
if dnAttributes {
|
||||||
|
ret += ":dn"
|
||||||
|
}
|
||||||
|
if len(matchingRule) > 0 {
|
||||||
|
ret += ":"
|
||||||
|
ret += matchingRule
|
||||||
|
}
|
||||||
|
ret += ":="
|
||||||
|
ret += EscapeFilter(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += ")"
|
ret += ")"
|
||||||
|
@ -194,10 +239,20 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
packet.AppendChild(child)
|
packet.AppendChild(child)
|
||||||
return packet, newPos, err
|
return packet, newPos, err
|
||||||
default:
|
default:
|
||||||
|
READING_ATTR := 0
|
||||||
|
READING_EXTENSIBLE_MATCHING_RULE := 1
|
||||||
|
READING_CONDITION := 2
|
||||||
|
|
||||||
|
state := READING_ATTR
|
||||||
|
|
||||||
attribute := ""
|
attribute := ""
|
||||||
|
extensibleDNAttributes := false
|
||||||
|
extensibleMatchingRule := ""
|
||||||
condition := ""
|
condition := ""
|
||||||
|
|
||||||
for newPos < len(filter) {
|
for newPos < len(filter) {
|
||||||
currentRune, currentWidth = utf8.DecodeRuneInString(filter[newPos:])
|
remainingFilter := filter[newPos:]
|
||||||
|
currentRune, currentWidth = utf8.DecodeRuneInString(remainingFilter)
|
||||||
if currentRune == ')' {
|
if currentRune == ')' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -205,27 +260,86 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
return packet, newPos, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos))
|
return packet, newPos, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos))
|
||||||
}
|
}
|
||||||
|
|
||||||
nextRune, nextWidth := utf8.DecodeRuneInString(filter[newPos+currentWidth:])
|
switch state {
|
||||||
|
case READING_ATTR:
|
||||||
|
switch {
|
||||||
|
// Extensible rule, with only DN-matching
|
||||||
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="):
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
|
extensibleDNAttributes = true
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 5
|
||||||
|
|
||||||
switch {
|
// Extensible rule, with DN-matching and a matching OID
|
||||||
case packet != nil:
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"):
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
|
extensibleDNAttributes = true
|
||||||
|
state = READING_EXTENSIBLE_MATCHING_RULE
|
||||||
|
newPos += 4
|
||||||
|
|
||||||
|
// Extensible rule, with attr only
|
||||||
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 2
|
||||||
|
|
||||||
|
// Extensible rule, with no DN attribute matching
|
||||||
|
case currentRune == ':':
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
|
state = READING_EXTENSIBLE_MATCHING_RULE
|
||||||
|
newPos += 1
|
||||||
|
|
||||||
|
// Equality condition
|
||||||
|
case currentRune == '=':
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 1
|
||||||
|
|
||||||
|
// Greater-than or equal
|
||||||
|
case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="):
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 2
|
||||||
|
|
||||||
|
// Less-than or equal
|
||||||
|
case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="):
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 2
|
||||||
|
|
||||||
|
// Approx
|
||||||
|
case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="):
|
||||||
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch])
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 2
|
||||||
|
|
||||||
|
// Still reading the attribute name
|
||||||
|
default:
|
||||||
|
attribute += fmt.Sprintf("%c", currentRune)
|
||||||
|
newPos += currentWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
case READING_EXTENSIBLE_MATCHING_RULE:
|
||||||
|
switch {
|
||||||
|
|
||||||
|
// Matching rule OID is done
|
||||||
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
||||||
|
state = READING_CONDITION
|
||||||
|
newPos += 2
|
||||||
|
|
||||||
|
// Still reading the matching rule oid
|
||||||
|
default:
|
||||||
|
extensibleMatchingRule += fmt.Sprintf("%c", currentRune)
|
||||||
|
newPos += currentWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
case READING_CONDITION:
|
||||||
|
// append to the condition
|
||||||
condition += fmt.Sprintf("%c", currentRune)
|
condition += fmt.Sprintf("%c", currentRune)
|
||||||
case currentRune == '=':
|
newPos += currentWidth
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
|
|
||||||
case currentRune == '>' && nextRune == '=':
|
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
|
|
||||||
newPos += nextWidth // we're skipping the next character as well
|
|
||||||
case currentRune == '<' && nextRune == '=':
|
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
|
|
||||||
newPos += nextWidth // we're skipping the next character as well
|
|
||||||
case currentRune == '~' && nextRune == '=':
|
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterLessOrEqual])
|
|
||||||
newPos += nextWidth // we're skipping the next character as well
|
|
||||||
case packet == nil:
|
|
||||||
attribute += fmt.Sprintf("%c", currentRune)
|
|
||||||
}
|
}
|
||||||
newPos += currentWidth
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if newPos == len(filter) {
|
if newPos == len(filter) {
|
||||||
err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
|
err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
|
||||||
return packet, newPos, err
|
return packet, newPos, err
|
||||||
|
@ -236,6 +350,36 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
case packet.Tag == FilterExtensibleMatch:
|
||||||
|
// MatchingRuleAssertion ::= SEQUENCE {
|
||||||
|
// matchingRule [1] MatchingRuleID OPTIONAL,
|
||||||
|
// type [2] AttributeDescription OPTIONAL,
|
||||||
|
// matchValue [3] AssertionValue,
|
||||||
|
// dnAttributes [4] BOOLEAN DEFAULT FALSE
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Include the matching rule oid, if specified
|
||||||
|
if len(extensibleMatchingRule) > 0 {
|
||||||
|
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchingRule, extensibleMatchingRule, MatchingRuleAssertionMap[MatchingRuleAssertionMatchingRule]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include the attribute, if specified
|
||||||
|
if len(attribute) > 0 {
|
||||||
|
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionType, attribute, MatchingRuleAssertionMap[MatchingRuleAssertionType]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the value (only required child)
|
||||||
|
encodedString, err := escapedStringToEncodedBytes(condition)
|
||||||
|
if err != nil {
|
||||||
|
return packet, newPos, err
|
||||||
|
}
|
||||||
|
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue]))
|
||||||
|
|
||||||
|
// Defaults to false, so only include in the sequence if true
|
||||||
|
if extensibleDNAttributes {
|
||||||
|
packet.AppendChild(ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionDNAttributes, extensibleDNAttributes, MatchingRuleAssertionMap[MatchingRuleAssertionDNAttributes]))
|
||||||
|
}
|
||||||
|
|
||||||
case packet.Tag == FilterEqualityMatch && condition == "*":
|
case packet.Tag == FilterEqualityMatch && condition == "*":
|
||||||
packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute, FilterMap[FilterPresent])
|
packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute, FilterMap[FilterPresent])
|
||||||
case packet.Tag == FilterEqualityMatch && strings.Contains(condition, "*"):
|
case packet.Tag == FilterEqualityMatch && strings.Contains(condition, "*"):
|
||||||
|
@ -257,38 +401,56 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
default:
|
default:
|
||||||
tag = FilterSubstringsAny
|
tag = FilterSubstringsAny
|
||||||
}
|
}
|
||||||
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, part, FilterSubstringsMap[uint64(tag)]))
|
encodedString, err := escapedStringToEncodedBytes(part)
|
||||||
|
if err != nil {
|
||||||
|
return packet, newPos, err
|
||||||
|
}
|
||||||
|
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)]))
|
||||||
}
|
}
|
||||||
packet.AppendChild(seq)
|
packet.AppendChild(seq)
|
||||||
default:
|
default:
|
||||||
var buffer bytes.Buffer
|
encodedString, err := escapedStringToEncodedBytes(condition)
|
||||||
for i := 0; i < len(condition); i++ {
|
if err != nil {
|
||||||
// Check for escaped hex characters and convert them to their literal value for transport.
|
return packet, newPos, err
|
||||||
if condition[i] == '\\' {
|
|
||||||
// http://tools.ietf.org/search/rfc4515
|
|
||||||
// \ (%x5C) is not a valid character unless it is followed by two HEX characters due to not
|
|
||||||
// being a member of UTF1SUBSET.
|
|
||||||
if i+2 > len(condition) {
|
|
||||||
err = NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
|
|
||||||
return packet, newPos, err
|
|
||||||
}
|
|
||||||
if escByte, decodeErr := hexpac.DecodeString(condition[i+1 : i+3]); decodeErr != nil {
|
|
||||||
err = NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
|
|
||||||
return packet, newPos, err
|
|
||||||
} else {
|
|
||||||
buffer.WriteByte(escByte[0])
|
|
||||||
i += 2 // +1 from end of loop, so 3 total for \xx.
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer.WriteString(string(condition[i]))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, buffer.String(), "Condition"))
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
|
||||||
}
|
}
|
||||||
|
|
||||||
newPos += currentWidth
|
newPos += currentWidth
|
||||||
return packet, newPos, err
|
return packet, newPos, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert from "ABC\xx\xx\xx" form to literal bytes for transport
|
||||||
|
func escapedStringToEncodedBytes(escapedString string) (string, error) {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
i := 0
|
||||||
|
for i < len(escapedString) {
|
||||||
|
currentRune, currentWidth := utf8.DecodeRuneInString(escapedString[i:])
|
||||||
|
if currentRune == utf8.RuneError {
|
||||||
|
return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for escaped hex characters and convert them to their literal value for transport.
|
||||||
|
if currentRune == '\\' {
|
||||||
|
// http://tools.ietf.org/search/rfc4515
|
||||||
|
// \ (%x5C) is not a valid character unless it is followed by two HEX characters due to not
|
||||||
|
// being a member of UTF1SUBSET.
|
||||||
|
if i+2 > len(escapedString) {
|
||||||
|
return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
|
||||||
|
}
|
||||||
|
if escByte, decodeErr := hexpac.DecodeString(escapedString[i+1 : i+3]); decodeErr != nil {
|
||||||
|
return "", NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
|
||||||
|
} else {
|
||||||
|
buffer.WriteByte(escByte[0])
|
||||||
|
i += 2 // +1 from end of loop, so 3 total for \xx.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.WriteRune(currentRune)
|
||||||
|
}
|
||||||
|
|
||||||
|
i += currentWidth
|
||||||
|
}
|
||||||
|
return buffer.String(), nil
|
||||||
|
}
|
||||||
|
|
5
Godeps/_workspace/src/github.com/gocql/gocql/AUTHORS
generated
vendored
5
Godeps/_workspace/src/github.com/gocql/gocql/AUTHORS
generated
vendored
|
@ -57,4 +57,7 @@ Adrien Bustany <adrien@bustany.org>
|
||||||
Andrey Smirnov <smirnov.andrey@gmail.com>
|
Andrey Smirnov <smirnov.andrey@gmail.com>
|
||||||
Adam Weiner <adamsweiner@gmail.com>
|
Adam Weiner <adamsweiner@gmail.com>
|
||||||
Daniel Cannon <daniel@danielcannon.co.uk>
|
Daniel Cannon <daniel@danielcannon.co.uk>
|
||||||
Johnny Bergström <johnny@joonix.se>
|
Johnny Bergström <johnny@joonix.se>
|
||||||
|
Adriano Orioli <orioli.adriano@gmail.com>
|
||||||
|
Claudiu Raveica <claudiu.raveica@gmail.com>
|
||||||
|
Artem Chernyshev <artem.0xD2@gmail.com>
|
||||||
|
|
3
Godeps/_workspace/src/github.com/gocql/gocql/cluster.go
generated
vendored
3
Godeps/_workspace/src/github.com/gocql/gocql/cluster.go
generated
vendored
|
@ -9,7 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gocql/gocql/lru"
|
"github.com/gocql/gocql/internal/lru"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultMaxPreparedStmts = 1000
|
const defaultMaxPreparedStmts = 1000
|
||||||
|
@ -89,7 +89,6 @@ type ClusterConfig struct {
|
||||||
Port int // port (default: 9042)
|
Port int // port (default: 9042)
|
||||||
Keyspace string // initial keyspace (optional)
|
Keyspace string // initial keyspace (optional)
|
||||||
NumConns int // number of connections per host (default: 2)
|
NumConns int // number of connections per host (default: 2)
|
||||||
NumStreams int // number of streams per connection (default: max per protocol, either 128 or 32768)
|
|
||||||
Consistency Consistency // default consistency level (default: Quorum)
|
Consistency Consistency // default consistency level (default: Quorum)
|
||||||
Compressor Compressor // compression algorithm (default: nil)
|
Compressor Compressor // compression algorithm (default: nil)
|
||||||
Authenticator Authenticator // authenticator (default: nil)
|
Authenticator Authenticator // authenticator (default: nil)
|
||||||
|
|
120
Godeps/_workspace/src/github.com/gocql/gocql/conn.go
generated
vendored
120
Godeps/_workspace/src/github.com/gocql/gocql/conn.go
generated
vendored
|
@ -18,8 +18,26 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gocql/gocql/internal/streams"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
approvedAuthenticators = [...]string{
|
||||||
|
"org.apache.cassandra.auth.PasswordAuthenticator",
|
||||||
|
"com.instaclustr.cassandra.auth.SharedSecretAuthenticator",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func approve(authenticator string) bool {
|
||||||
|
for _, s := range approvedAuthenticators {
|
||||||
|
if authenticator == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
//JoinHostPort is a utility to return a address string that can be used
|
//JoinHostPort is a utility to return a address string that can be used
|
||||||
//gocql.Conn to form a connection with a host.
|
//gocql.Conn to form a connection with a host.
|
||||||
func JoinHostPort(addr string, port int) string {
|
func JoinHostPort(addr string, port int) string {
|
||||||
|
@ -41,7 +59,7 @@ type PasswordAuthenticator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PasswordAuthenticator) Challenge(req []byte) ([]byte, Authenticator, error) {
|
func (p PasswordAuthenticator) Challenge(req []byte) ([]byte, Authenticator, error) {
|
||||||
if string(req) != "org.apache.cassandra.auth.PasswordAuthenticator" {
|
if !approve(string(req)) {
|
||||||
return nil, nil, fmt.Errorf("unexpected authenticator %q", req)
|
return nil, nil, fmt.Errorf("unexpected authenticator %q", req)
|
||||||
}
|
}
|
||||||
resp := make([]byte, 2+len(p.Username)+len(p.Password))
|
resp := make([]byte, 2+len(p.Username)+len(p.Password))
|
||||||
|
@ -75,7 +93,6 @@ type ConnConfig struct {
|
||||||
ProtoVersion int
|
ProtoVersion int
|
||||||
CQLVersion string
|
CQLVersion string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
NumStreams int
|
|
||||||
Compressor Compressor
|
Compressor Compressor
|
||||||
Authenticator Authenticator
|
Authenticator Authenticator
|
||||||
Keepalive time.Duration
|
Keepalive time.Duration
|
||||||
|
@ -103,8 +120,9 @@ type Conn struct {
|
||||||
|
|
||||||
headerBuf []byte
|
headerBuf []byte
|
||||||
|
|
||||||
uniq chan int
|
streams *streams.IDGenerator
|
||||||
calls []callReq
|
mu sync.RWMutex
|
||||||
|
calls map[int]*callReq
|
||||||
|
|
||||||
errorHandler ConnErrorHandler
|
errorHandler ConnErrorHandler
|
||||||
compressor Compressor
|
compressor Compressor
|
||||||
|
@ -153,26 +171,15 @@ func Connect(addr string, cfg *ConnConfig, errorHandler ConnErrorHandler, sessio
|
||||||
}
|
}
|
||||||
|
|
||||||
headerSize := 8
|
headerSize := 8
|
||||||
|
|
||||||
maxStreams := 128
|
|
||||||
if cfg.ProtoVersion > protoVersion2 {
|
if cfg.ProtoVersion > protoVersion2 {
|
||||||
maxStreams = 32768
|
|
||||||
headerSize = 9
|
headerSize = 9
|
||||||
}
|
}
|
||||||
|
|
||||||
streams := cfg.NumStreams
|
|
||||||
if streams <= 0 || streams >= maxStreams {
|
|
||||||
streams = maxStreams
|
|
||||||
} else {
|
|
||||||
streams++
|
|
||||||
}
|
|
||||||
|
|
||||||
c := &Conn{
|
c := &Conn{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
r: bufio.NewReader(conn),
|
r: bufio.NewReader(conn),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
uniq: make(chan int, streams),
|
calls: make(map[int]*callReq),
|
||||||
calls: make([]callReq, streams),
|
|
||||||
timeout: cfg.Timeout,
|
timeout: cfg.Timeout,
|
||||||
version: uint8(cfg.ProtoVersion),
|
version: uint8(cfg.ProtoVersion),
|
||||||
addr: conn.RemoteAddr().String(),
|
addr: conn.RemoteAddr().String(),
|
||||||
|
@ -182,19 +189,13 @@ func Connect(addr string, cfg *ConnConfig, errorHandler ConnErrorHandler, sessio
|
||||||
headerBuf: make([]byte, headerSize),
|
headerBuf: make([]byte, headerSize),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
session: session,
|
session: session,
|
||||||
|
streams: streams.New(cfg.ProtoVersion),
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Keepalive > 0 {
|
if cfg.Keepalive > 0 {
|
||||||
c.setKeepalive(cfg.Keepalive)
|
c.setKeepalive(cfg.Keepalive)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reserve stream 0 incase cassandra returns an error on it without us sending
|
|
||||||
// a request.
|
|
||||||
for i := 1; i < streams; i++ {
|
|
||||||
c.calls[i].resp = make(chan error)
|
|
||||||
c.uniq <- i
|
|
||||||
}
|
|
||||||
|
|
||||||
go c.serve()
|
go c.serve()
|
||||||
|
|
||||||
if err := c.startup(); err != nil {
|
if err := c.startup(); err != nil {
|
||||||
|
@ -324,8 +325,8 @@ func (c *Conn) closeWithError(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// we should attempt to deliver the error back to the caller if it
|
// we should attempt to deliver the error back to the caller if it
|
||||||
// exists
|
// exists
|
||||||
for id := 0; id < len(c.calls); id++ {
|
c.mu.RLock()
|
||||||
req := &c.calls[id]
|
for _, req := range c.calls {
|
||||||
// we need to send the error to all waiting queries, put the state
|
// we need to send the error to all waiting queries, put the state
|
||||||
// of this conn into not active so that it can not execute any queries.
|
// of this conn into not active so that it can not execute any queries.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -335,6 +336,7 @@ func (c *Conn) closeWithError(err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c.mu.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if error was nil then unblock the quit channel
|
// if error was nil then unblock the quit channel
|
||||||
|
@ -391,7 +393,7 @@ func (c *Conn) recv() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.stream > len(c.calls) {
|
if head.stream > c.streams.NumStreams {
|
||||||
return fmt.Errorf("gocql: frame header stream is beyond call exepected bounds: %d", head.stream)
|
return fmt.Errorf("gocql: frame header stream is beyond call exepected bounds: %d", head.stream)
|
||||||
} else if head.stream == -1 {
|
} else if head.stream == -1 {
|
||||||
// TODO: handle cassandra event frames, we shouldnt get any currently
|
// TODO: handle cassandra event frames, we shouldnt get any currently
|
||||||
|
@ -418,8 +420,10 @@ func (c *Conn) recv() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
call := &c.calls[head.stream]
|
c.mu.RLock()
|
||||||
if call == nil || call.framer == nil {
|
call, ok := c.calls[head.stream]
|
||||||
|
c.mu.RUnlock()
|
||||||
|
if call == nil || call.framer == nil || !ok {
|
||||||
log.Printf("gocql: received response for stream which has no handler: header=%v\n", head)
|
log.Printf("gocql: received response for stream which has no handler: header=%v\n", head)
|
||||||
return c.discardFrame(head)
|
return c.discardFrame(head)
|
||||||
}
|
}
|
||||||
|
@ -447,19 +451,25 @@ func (c *Conn) recv() error {
|
||||||
|
|
||||||
type callReq struct {
|
type callReq struct {
|
||||||
// could use a waitgroup but this allows us to do timeouts on the read/send
|
// could use a waitgroup but this allows us to do timeouts on the read/send
|
||||||
resp chan error
|
resp chan error
|
||||||
framer *framer
|
framer *framer
|
||||||
timeout chan struct{} // indicates to recv() that a call has timedout
|
timeout chan struct{} // indicates to recv() that a call has timedout
|
||||||
|
streamID int // current stream in use
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) releaseStream(stream int) {
|
func (c *Conn) releaseStream(stream int) {
|
||||||
call := &c.calls[stream]
|
c.mu.Lock()
|
||||||
call.framer = nil
|
call := c.calls[stream]
|
||||||
|
if call != nil && stream != call.streamID {
|
||||||
select {
|
panic(fmt.Sprintf("attempt to release streamID with ivalid stream: %d -> %+v\n", stream, call))
|
||||||
case c.uniq <- stream:
|
} else if call == nil {
|
||||||
case <-c.quit:
|
panic(fmt.Sprintf("releasing a stream not in use: %d", stream))
|
||||||
}
|
}
|
||||||
|
delete(c.calls, stream)
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
streamPool.Put(call)
|
||||||
|
c.streams.Clear(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) handleTimeout() {
|
func (c *Conn) handleTimeout() {
|
||||||
|
@ -468,20 +478,41 @@ func (c *Conn) handleTimeout() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
streamPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return &callReq{
|
||||||
|
resp: make(chan error),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func (c *Conn) exec(req frameWriter, tracer Tracer) (*framer, error) {
|
func (c *Conn) exec(req frameWriter, tracer Tracer) (*framer, error) {
|
||||||
// TODO: move tracer onto conn
|
// TODO: move tracer onto conn
|
||||||
var stream int
|
stream, ok := c.streams.GetStream()
|
||||||
select {
|
if !ok {
|
||||||
case stream = <-c.uniq:
|
fmt.Println(c.streams)
|
||||||
case <-c.quit:
|
return nil, ErrNoStreams
|
||||||
return nil, ErrConnectionClosed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resp is basically a waiting semaphore protecting the framer
|
// resp is basically a waiting semaphore protecting the framer
|
||||||
framer := newFramer(c, c, c.compressor, c.version)
|
framer := newFramer(c, c, c.compressor, c.version)
|
||||||
call := &c.calls[stream]
|
|
||||||
|
c.mu.Lock()
|
||||||
|
call := c.calls[stream]
|
||||||
|
if call != nil {
|
||||||
|
c.mu.Unlock()
|
||||||
|
return nil, fmt.Errorf("attempting to use stream already in use: %d -> %d", stream, call.streamID)
|
||||||
|
} else {
|
||||||
|
call = streamPool.Get().(*callReq)
|
||||||
|
}
|
||||||
|
c.calls[stream] = call
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
call.framer = framer
|
call.framer = framer
|
||||||
call.timeout = make(chan struct{})
|
call.timeout = make(chan struct{})
|
||||||
|
call.streamID = stream
|
||||||
|
|
||||||
if tracer != nil {
|
if tracer != nil {
|
||||||
framer.trace()
|
framer.trace()
|
||||||
|
@ -749,7 +780,7 @@ func (c *Conn) Address() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) AvailableStreams() int {
|
func (c *Conn) AvailableStreams() int {
|
||||||
return len(c.uniq)
|
return c.streams.Available()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) UseKeyspace(keyspace string) error {
|
func (c *Conn) UseKeyspace(keyspace string) error {
|
||||||
|
@ -961,4 +992,5 @@ var (
|
||||||
ErrTimeoutNoResponse = errors.New("gocql: no response received from cassandra within timeout period")
|
ErrTimeoutNoResponse = errors.New("gocql: no response received from cassandra within timeout period")
|
||||||
ErrTooManyTimeouts = errors.New("gocql: too many query timeouts on the connection")
|
ErrTooManyTimeouts = errors.New("gocql: too many query timeouts on the connection")
|
||||||
ErrConnectionClosed = errors.New("gocql: connection closed waiting for response")
|
ErrConnectionClosed = errors.New("gocql: connection closed waiting for response")
|
||||||
|
ErrNoStreams = errors.New("gocql: no streams available on connection")
|
||||||
)
|
)
|
||||||
|
|
1
Godeps/_workspace/src/github.com/gocql/gocql/connectionpool.go
generated
vendored
1
Godeps/_workspace/src/github.com/gocql/gocql/connectionpool.go
generated
vendored
|
@ -97,7 +97,6 @@ func newPolicyConnPool(session *Session, hostPolicy HostSelectionPolicy,
|
||||||
ProtoVersion: cfg.ProtoVersion,
|
ProtoVersion: cfg.ProtoVersion,
|
||||||
CQLVersion: cfg.CQLVersion,
|
CQLVersion: cfg.CQLVersion,
|
||||||
Timeout: cfg.Timeout,
|
Timeout: cfg.Timeout,
|
||||||
NumStreams: cfg.NumStreams,
|
|
||||||
Compressor: cfg.Compressor,
|
Compressor: cfg.Compressor,
|
||||||
Authenticator: cfg.Authenticator,
|
Authenticator: cfg.Authenticator,
|
||||||
Keepalive: cfg.SocketKeepalive,
|
Keepalive: cfg.SocketKeepalive,
|
||||||
|
|
5
Godeps/_workspace/src/github.com/gocql/gocql/control.go
generated
vendored
5
Godeps/_workspace/src/github.com/gocql/gocql/control.go
generated
vendored
|
@ -7,11 +7,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ensure that the atomic variable is aligned to a 64bit boundary
|
||||||
|
// so that atomic operations can be applied on 32bit architectures.
|
||||||
type controlConn struct {
|
type controlConn struct {
|
||||||
|
connecting uint64
|
||||||
|
|
||||||
session *Session
|
session *Session
|
||||||
|
|
||||||
conn atomic.Value
|
conn atomic.Value
|
||||||
connecting uint64
|
|
||||||
|
|
||||||
retry RetryPolicy
|
retry RetryPolicy
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
|
||||||
package gocql
|
package murmur
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func murmur3H1(data []byte) uint64 {
|
func Murmur3H1(data []byte) uint64 {
|
||||||
length := len(data)
|
length := len(data)
|
||||||
|
|
||||||
var h1, h2, k1, k2 uint64
|
var h1, h2, k1, k2 uint64
|
|
@ -1,10 +1,10 @@
|
||||||
// +build appengine
|
// +build appengine
|
||||||
|
|
||||||
package gocql
|
package murmur
|
||||||
|
|
||||||
import "encoding/binary"
|
import "encoding/binary"
|
||||||
|
|
||||||
func murmur3H1(data []byte) uint64 {
|
func Murmur3H1(data []byte) uint64 {
|
||||||
length := len(data)
|
length := len(data)
|
||||||
|
|
||||||
var h1, h2, k1, k2 uint64
|
var h1, h2, k1, k2 uint64
|
140
Godeps/_workspace/src/github.com/gocql/gocql/internal/streams/streams.go
generated
vendored
Normal file
140
Godeps/_workspace/src/github.com/gocql/gocql/internal/streams/streams.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
package streams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
const bucketBits = 64
|
||||||
|
|
||||||
|
// IDGenerator tracks and allocates streams which are in use.
|
||||||
|
type IDGenerator struct {
|
||||||
|
NumStreams int
|
||||||
|
inuseStreams int32
|
||||||
|
numBuckets uint32
|
||||||
|
|
||||||
|
// streams is a bitset where each bit represents a stream, a 1 implies in use
|
||||||
|
streams []uint64
|
||||||
|
offset uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(protocol int) *IDGenerator {
|
||||||
|
maxStreams := 128
|
||||||
|
if protocol > 2 {
|
||||||
|
maxStreams = 32768
|
||||||
|
}
|
||||||
|
|
||||||
|
buckets := maxStreams / 64
|
||||||
|
// reserve stream 0
|
||||||
|
streams := make([]uint64, buckets)
|
||||||
|
streams[0] = 1 << 63
|
||||||
|
|
||||||
|
return &IDGenerator{
|
||||||
|
NumStreams: maxStreams,
|
||||||
|
streams: streams,
|
||||||
|
numBuckets: uint32(buckets),
|
||||||
|
offset: uint32(buckets) - 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamFromBucket(bucket, streamInBucket int) int {
|
||||||
|
return (bucket * bucketBits) + streamInBucket
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IDGenerator) GetStream() (int, bool) {
|
||||||
|
// based closely on the java-driver stream ID generator
|
||||||
|
// avoid false sharing subsequent requests.
|
||||||
|
offset := atomic.LoadUint32(&s.offset)
|
||||||
|
for !atomic.CompareAndSwapUint32(&s.offset, offset, (offset+1)%s.numBuckets) {
|
||||||
|
offset = atomic.LoadUint32(&s.offset)
|
||||||
|
}
|
||||||
|
offset = (offset + 1) % s.numBuckets
|
||||||
|
|
||||||
|
for i := uint32(0); i < s.numBuckets; i++ {
|
||||||
|
pos := int((i + offset) % s.numBuckets)
|
||||||
|
|
||||||
|
bucket := atomic.LoadUint64(&s.streams[pos])
|
||||||
|
if bucket == math.MaxUint64 {
|
||||||
|
// all streams in use
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 0; j < bucketBits; j++ {
|
||||||
|
mask := uint64(1 << streamOffset(j))
|
||||||
|
if bucket&mask == 0 {
|
||||||
|
if atomic.CompareAndSwapUint64(&s.streams[pos], bucket, bucket|mask) {
|
||||||
|
atomic.AddInt32(&s.inuseStreams, 1)
|
||||||
|
return streamFromBucket(int(pos), j), true
|
||||||
|
}
|
||||||
|
bucket = atomic.LoadUint64(&s.streams[offset])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func bitfmt(b uint64) string {
|
||||||
|
return strconv.FormatUint(b, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the bucket offset of a given stream
|
||||||
|
func bucketOffset(i int) int {
|
||||||
|
return i / bucketBits
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamOffset(stream int) uint64 {
|
||||||
|
return bucketBits - uint64(stream%bucketBits) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSet(bits uint64, stream int) bool {
|
||||||
|
return bits>>streamOffset(stream)&1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IDGenerator) isSet(stream int) bool {
|
||||||
|
bits := atomic.LoadUint64(&s.streams[bucketOffset(stream)])
|
||||||
|
return isSet(bits, stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IDGenerator) String() string {
|
||||||
|
size := s.numBuckets * (bucketBits + 1)
|
||||||
|
buf := make([]byte, 0, size)
|
||||||
|
for i := 0; i < int(s.numBuckets); i++ {
|
||||||
|
bits := atomic.LoadUint64(&s.streams[i])
|
||||||
|
buf = append(buf, bitfmt(bits)...)
|
||||||
|
buf = append(buf, ' ')
|
||||||
|
}
|
||||||
|
return string(buf[:size-1 : size-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IDGenerator) Clear(stream int) (inuse bool) {
|
||||||
|
offset := bucketOffset(stream)
|
||||||
|
bucket := atomic.LoadUint64(&s.streams[offset])
|
||||||
|
|
||||||
|
mask := uint64(1) << streamOffset(stream)
|
||||||
|
if bucket&mask != mask {
|
||||||
|
// already cleared
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for !atomic.CompareAndSwapUint64(&s.streams[offset], bucket, bucket & ^mask) {
|
||||||
|
bucket = atomic.LoadUint64(&s.streams[offset])
|
||||||
|
if bucket&mask != mask {
|
||||||
|
// already cleared
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make this account for 0 stream being reserved
|
||||||
|
if atomic.AddInt32(&s.inuseStreams, -1) < 0 {
|
||||||
|
// TODO(zariel): remove this
|
||||||
|
panic("negative streams inuse")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *IDGenerator) Available() int {
|
||||||
|
return s.NumStreams - int(atomic.LoadInt32(&s.inuseStreams)) - 1
|
||||||
|
}
|
20
Godeps/_workspace/src/github.com/gocql/gocql/policies.go
generated
vendored
20
Godeps/_workspace/src/github.com/gocql/gocql/policies.go
generated
vendored
|
@ -354,12 +354,20 @@ func (r *roundRobinConnPolicy) SetConns(conns []*Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *roundRobinConnPolicy) Pick(qry *Query) *Conn {
|
func (r *roundRobinConnPolicy) Pick(qry *Query) *Conn {
|
||||||
pos := atomic.AddUint32(&r.pos, 1)
|
pos := int(atomic.AddUint32(&r.pos, 1) - 1)
|
||||||
var conn *Conn
|
|
||||||
r.mu.RLock()
|
r.mu.RLock()
|
||||||
if len(r.conns) > 0 {
|
defer r.mu.RUnlock()
|
||||||
conn = r.conns[pos%uint32(len(r.conns))]
|
|
||||||
|
if len(r.conns) == 0 {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
r.mu.RUnlock()
|
|
||||||
return conn
|
for i := 0; i < len(r.conns); i++ {
|
||||||
|
conn := r.conns[(pos+i)%len(r.conns)]
|
||||||
|
if conn.AvailableStreams() > 0 {
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
17
Godeps/_workspace/src/github.com/gocql/gocql/session.go
generated
vendored
17
Godeps/_workspace/src/github.com/gocql/gocql/session.go
generated
vendored
|
@ -16,7 +16,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/gocql/gocql/lru"
|
"github.com/gocql/gocql/internal/lru"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Session is the interface used by users to interact with the database.
|
// Session is the interface used by users to interact with the database.
|
||||||
|
@ -54,15 +54,6 @@ func NewSession(cfg ClusterConfig) (*Session, error) {
|
||||||
return nil, ErrNoHosts
|
return nil, ErrNoHosts
|
||||||
}
|
}
|
||||||
|
|
||||||
maxStreams := 128
|
|
||||||
if cfg.ProtoVersion > protoVersion2 {
|
|
||||||
maxStreams = 32768
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.NumStreams <= 0 || cfg.NumStreams > maxStreams {
|
|
||||||
cfg.NumStreams = maxStreams
|
|
||||||
}
|
|
||||||
|
|
||||||
//Adjust the size of the prepared statements cache to match the latest configuration
|
//Adjust the size of the prepared statements cache to match the latest configuration
|
||||||
stmtsLRU.Lock()
|
stmtsLRU.Lock()
|
||||||
initStmtsLRU(cfg.MaxPreparedStmts)
|
initStmtsLRU(cfg.MaxPreparedStmts)
|
||||||
|
@ -893,6 +884,12 @@ func (iter *Iter) Close() error {
|
||||||
return iter.err
|
return iter.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WillSwitchPage detects if iterator reached end of current page
|
||||||
|
// and the next page is available.
|
||||||
|
func (iter *Iter) WillSwitchPage() bool {
|
||||||
|
return iter.pos >= len(iter.rows) && iter.next != nil
|
||||||
|
}
|
||||||
|
|
||||||
// checkErrAndNotFound handle error and NotFound in one method.
|
// checkErrAndNotFound handle error and NotFound in one method.
|
||||||
func (iter *Iter) checkErrAndNotFound() error {
|
func (iter *Iter) checkErrAndNotFound() error {
|
||||||
if iter.err != nil {
|
if iter.err != nil {
|
||||||
|
|
4
Godeps/_workspace/src/github.com/gocql/gocql/token.go
generated
vendored
4
Godeps/_workspace/src/github.com/gocql/gocql/token.go
generated
vendored
|
@ -12,6 +12,8 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gocql/gocql/internal/murmur"
|
||||||
)
|
)
|
||||||
|
|
||||||
// a token partitioner
|
// a token partitioner
|
||||||
|
@ -36,7 +38,7 @@ func (p murmur3Partitioner) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p murmur3Partitioner) Hash(partitionKey []byte) token {
|
func (p murmur3Partitioner) Hash(partitionKey []byte) token {
|
||||||
h1 := murmur3H1(partitionKey)
|
h1 := murmur.Murmur3H1(partitionKey)
|
||||||
return murmur3Token(int64(h1))
|
return murmur3Token(int64(h1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
68
Godeps/_workspace/src/github.com/google/go-github/github/issues_events.go
generated
vendored
68
Godeps/_workspace/src/github.com/google/go-github/github/issues_events.go
generated
vendored
|
@ -22,52 +22,52 @@ type IssueEvent struct {
|
||||||
// values are:
|
// values are:
|
||||||
//
|
//
|
||||||
// closed
|
// closed
|
||||||
// The issue was closed by the actor. When the commit_id is
|
// The Actor closed the issue.
|
||||||
// present, it identifies the commit that closed the issue using
|
// If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit.
|
||||||
// “closes / fixes #NN” syntax.
|
|
||||||
//
|
|
||||||
// reopened
|
|
||||||
// The issue was reopened by the actor.
|
|
||||||
//
|
|
||||||
// subscribed
|
|
||||||
// The actor subscribed to receive notifications for an issue.
|
|
||||||
//
|
//
|
||||||
// merged
|
// merged
|
||||||
// The issue was merged by the actor. The commit_id attribute is the SHA1 of the HEAD commit that was merged.
|
// The Actor merged into master a branch containing a commit mentioning the issue.
|
||||||
|
// CommitID holds the SHA1 of the merge commit.
|
||||||
//
|
//
|
||||||
// referenced
|
// referenced
|
||||||
// The issue was referenced from a commit message. The commit_id attribute is the commit SHA1 of where that happened.
|
// The Actor committed to master a commit mentioning the issue in its commit message.
|
||||||
|
// CommitID holds the SHA1 of the commit.
|
||||||
//
|
//
|
||||||
// mentioned
|
// reopened, locked, unlocked
|
||||||
// The actor was @mentioned in an issue body.
|
// The Actor did that to the issue.
|
||||||
//
|
|
||||||
// assigned
|
|
||||||
// The issue was assigned to the actor.
|
|
||||||
//
|
|
||||||
// head_ref_deleted
|
|
||||||
// The pull request’s branch was deleted.
|
|
||||||
//
|
|
||||||
// head_ref_restored
|
|
||||||
// The pull request’s branch was restored.
|
|
||||||
//
|
|
||||||
// labeled
|
|
||||||
// A label was added.
|
|
||||||
//
|
//
|
||||||
// renamed
|
// renamed
|
||||||
// The issue title was changed.
|
// The Actor changed the issue title from Rename.From to Rename.To.
|
||||||
|
//
|
||||||
|
// mentioned
|
||||||
|
// Someone unspecified @mentioned the Actor [sic] in an issue comment body.
|
||||||
|
//
|
||||||
|
// assigned, unassigned
|
||||||
|
// The Actor assigned the issue to or removed the assignment from the Assignee.
|
||||||
|
//
|
||||||
|
// labeled, unlabeled
|
||||||
|
// The Actor added or removed the Label from the issue.
|
||||||
|
//
|
||||||
|
// milestoned, demilestoned
|
||||||
|
// The Actor added or removed the issue from the Milestone.
|
||||||
|
//
|
||||||
|
// subscribed, unsubscribed
|
||||||
|
// The Actor subscribed to or unsubscribed from notifications for an issue.
|
||||||
|
//
|
||||||
|
// head_ref_deleted, head_ref_restored
|
||||||
|
// The pull request’s branch was deleted or restored.
|
||||||
|
//
|
||||||
Event *string `json:"event,omitempty"`
|
Event *string `json:"event,omitempty"`
|
||||||
|
|
||||||
// The SHA of the commit that referenced this commit, if applicable.
|
|
||||||
CommitID *string `json:"commit_id,omitempty"`
|
|
||||||
|
|
||||||
CreatedAt *time.Time `json:"created_at,omitempty"`
|
CreatedAt *time.Time `json:"created_at,omitempty"`
|
||||||
Issue *Issue `json:"issue,omitempty"`
|
Issue *Issue `json:"issue,omitempty"`
|
||||||
|
|
||||||
// Only present on 'labeled' events.
|
// Only present on certain events; see above.
|
||||||
Label *Label `json:"label,omitempty"`
|
Assignee *User `json:"assignee,omitempty"`
|
||||||
|
CommitID *string `json:"commit_id,omitempty"`
|
||||||
// Only present on 'renamed' events.
|
Milestone *Milestone `json:"milestone,omitempty"`
|
||||||
Rename *Rename `json:"rename,omitempty"`
|
Label *Label `json:"label,omitempty"`
|
||||||
|
Rename *Rename `json:"rename,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListIssueEvents lists events for the specified issue.
|
// ListIssueEvents lists events for the specified issue.
|
||||||
|
|
2
Godeps/_workspace/src/github.com/hashicorp/consul/api/README.md
generated
vendored
2
Godeps/_workspace/src/github.com/hashicorp/consul/api/README.md
generated
vendored
|
@ -4,7 +4,7 @@ Consul API client
|
||||||
This package provides the `api` package which attempts to
|
This package provides the `api` package which attempts to
|
||||||
provide programmatic access to the full Consul API.
|
provide programmatic access to the full Consul API.
|
||||||
|
|
||||||
Currently, all of the Consul APIs included in version 0.3 are supported.
|
Currently, all of the Consul APIs included in version 0.6.0 are supported.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
=============
|
=============
|
||||||
|
|
16
Godeps/_workspace/src/github.com/hashicorp/consul/api/agent.go
generated
vendored
16
Godeps/_workspace/src/github.com/hashicorp/consul/api/agent.go
generated
vendored
|
@ -63,13 +63,15 @@ type AgentCheckRegistration struct {
|
||||||
// AgentServiceCheck is used to create an associated
|
// AgentServiceCheck is used to create an associated
|
||||||
// check for a service
|
// check for a service
|
||||||
type AgentServiceCheck struct {
|
type AgentServiceCheck struct {
|
||||||
Script string `json:",omitempty"`
|
Script string `json:",omitempty"`
|
||||||
Interval string `json:",omitempty"`
|
DockerContainerID string `json:",omitempty"`
|
||||||
Timeout string `json:",omitempty"`
|
Shell string `json:",omitempty"` // Only supported for Docker.
|
||||||
TTL string `json:",omitempty"`
|
Interval string `json:",omitempty"`
|
||||||
HTTP string `json:",omitempty"`
|
Timeout string `json:",omitempty"`
|
||||||
TCP string `json:",omitempty"`
|
TTL string `json:",omitempty"`
|
||||||
Status string `json:",omitempty"`
|
HTTP string `json:",omitempty"`
|
||||||
|
TCP string `json:",omitempty"`
|
||||||
|
Status string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
type AgentServiceChecks []*AgentServiceCheck
|
type AgentServiceChecks []*AgentServiceCheck
|
||||||
|
|
||||||
|
|
40
Godeps/_workspace/src/github.com/hashicorp/consul/api/lock.go
generated
vendored
40
Godeps/_workspace/src/github.com/hashicorp/consul/api/lock.go
generated
vendored
|
@ -2,6 +2,7 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -22,9 +23,15 @@ const (
|
||||||
|
|
||||||
// DefaultLockRetryTime is how long we wait after a failed lock acquisition
|
// DefaultLockRetryTime is how long we wait after a failed lock acquisition
|
||||||
// before attempting to do the lock again. This is so that once a lock-delay
|
// before attempting to do the lock again. This is so that once a lock-delay
|
||||||
// is in affect, we do not hot loop retrying the acquisition.
|
// is in effect, we do not hot loop retrying the acquisition.
|
||||||
DefaultLockRetryTime = 5 * time.Second
|
DefaultLockRetryTime = 5 * time.Second
|
||||||
|
|
||||||
|
// DefaultMonitorRetryTime is how long we wait after a failed monitor check
|
||||||
|
// of a lock (500 response code). This allows the monitor to ride out brief
|
||||||
|
// periods of unavailability, subject to the MonitorRetries setting in the
|
||||||
|
// lock options which is by default set to 0, disabling this feature.
|
||||||
|
DefaultMonitorRetryTime = 2 * time.Second
|
||||||
|
|
||||||
// LockFlagValue is a magic flag we set to indicate a key
|
// LockFlagValue is a magic flag we set to indicate a key
|
||||||
// is being used for a lock. It is used to detect a potential
|
// is being used for a lock. It is used to detect a potential
|
||||||
// conflict with a semaphore.
|
// conflict with a semaphore.
|
||||||
|
@ -62,11 +69,13 @@ type Lock struct {
|
||||||
|
|
||||||
// LockOptions is used to parameterize the Lock behavior.
|
// LockOptions is used to parameterize the Lock behavior.
|
||||||
type LockOptions struct {
|
type LockOptions struct {
|
||||||
Key string // Must be set and have write permissions
|
Key string // Must be set and have write permissions
|
||||||
Value []byte // Optional, value to associate with the lock
|
Value []byte // Optional, value to associate with the lock
|
||||||
Session string // Optional, created if not specified
|
Session string // Optional, created if not specified
|
||||||
SessionName string // Optional, defaults to DefaultLockSessionName
|
SessionName string // Optional, defaults to DefaultLockSessionName
|
||||||
SessionTTL string // Optional, defaults to DefaultLockSessionTTL
|
SessionTTL string // Optional, defaults to DefaultLockSessionTTL
|
||||||
|
MonitorRetries int // Optional, defaults to 0 which means no retries
|
||||||
|
MonitorRetryTime time.Duration // Optional, defaults to DefaultMonitorRetryTime
|
||||||
}
|
}
|
||||||
|
|
||||||
// LockKey returns a handle to a lock struct which can be used
|
// LockKey returns a handle to a lock struct which can be used
|
||||||
|
@ -96,6 +105,9 @@ func (c *Client) LockOpts(opts *LockOptions) (*Lock, error) {
|
||||||
return nil, fmt.Errorf("invalid SessionTTL: %v", err)
|
return nil, fmt.Errorf("invalid SessionTTL: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if opts.MonitorRetryTime == 0 {
|
||||||
|
opts.MonitorRetryTime = DefaultMonitorRetryTime
|
||||||
|
}
|
||||||
l := &Lock{
|
l := &Lock{
|
||||||
c: c,
|
c: c,
|
||||||
opts: opts,
|
opts: opts,
|
||||||
|
@ -327,8 +339,24 @@ func (l *Lock) monitorLock(session string, stopCh chan struct{}) {
|
||||||
kv := l.c.KV()
|
kv := l.c.KV()
|
||||||
opts := &QueryOptions{RequireConsistent: true}
|
opts := &QueryOptions{RequireConsistent: true}
|
||||||
WAIT:
|
WAIT:
|
||||||
|
retries := l.opts.MonitorRetries
|
||||||
|
RETRY:
|
||||||
pair, meta, err := kv.Get(l.opts.Key, opts)
|
pair, meta, err := kv.Get(l.opts.Key, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// TODO (slackpad) - Make a real error type here instead of using
|
||||||
|
// a string check.
|
||||||
|
const serverError = "Unexpected response code: 500"
|
||||||
|
|
||||||
|
// If configured we can try to ride out a brief Consul unavailability
|
||||||
|
// by doing retries. Note that we have to attempt the retry in a non-
|
||||||
|
// blocking fashion so that we have a clean place to reset the retry
|
||||||
|
// counter if service is restored.
|
||||||
|
if retries > 0 && strings.Contains(err.Error(), serverError) {
|
||||||
|
time.Sleep(l.opts.MonitorRetryTime)
|
||||||
|
retries--
|
||||||
|
opts.WaitIndex = 0
|
||||||
|
goto RETRY
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if pair != nil && pair.Session == session {
|
if pair != nil && pair.Session == session {
|
||||||
|
|
14
Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
14
Godeps/_workspace/src/github.com/hashicorp/go-cleanhttp/cleanhttp.go
generated
vendored
|
@ -3,13 +3,14 @@ package cleanhttp
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultTransport returns a new http.Transport with the same default values
|
// DefaultTransport returns a new http.Transport with the same default values
|
||||||
// as http.DefaultTransport
|
// as http.DefaultTransport
|
||||||
func DefaultTransport() *http.Transport {
|
func DefaultTransport() *http.Transport {
|
||||||
return &http.Transport{
|
transport := &http.Transport{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
Dial: (&net.Dialer{
|
Dial: (&net.Dialer{
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 30 * time.Second,
|
||||||
|
@ -17,6 +18,8 @@ func DefaultTransport() *http.Transport {
|
||||||
}).Dial,
|
}).Dial,
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
SetTransportFinalizer(transport)
|
||||||
|
return transport
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultClient returns a new http.Client with the same default values as
|
// DefaultClient returns a new http.Client with the same default values as
|
||||||
|
@ -26,3 +29,12 @@ func DefaultClient() *http.Client {
|
||||||
Transport: DefaultTransport(),
|
Transport: DefaultTransport(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTransportFinalizer sets a finalizer on the transport to ensure that
|
||||||
|
// idle connections are closed prior to garbage collection; otherwise
|
||||||
|
// these may leak
|
||||||
|
func SetTransportFinalizer(transport *http.Transport) {
|
||||||
|
runtime.SetFinalizer(&transport, func(t **http.Transport) {
|
||||||
|
(*t).CloseIdleConnections()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -5,4 +5,4 @@ Generates UUID-format strings using purely high quality random bytes.
|
||||||
Documentation
|
Documentation
|
||||||
=============
|
=============
|
||||||
|
|
||||||
The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/uuid).
|
The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/go-uuid).
|
212
Godeps/_workspace/src/github.com/hashicorp/golang-lru/2q.go
generated
vendored
Normal file
212
Godeps/_workspace/src/github.com/hashicorp/golang-lru/2q.go
generated
vendored
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/golang-lru/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Default2QRecentRatio is the ratio of the 2Q cache dedicated
|
||||||
|
// to recently added entries that have only been accessed once.
|
||||||
|
Default2QRecentRatio = 0.25
|
||||||
|
|
||||||
|
// Default2QGhostEntries is the default ratio of ghost
|
||||||
|
// entries kept to track entries recently evicted
|
||||||
|
Default2QGhostEntries = 0.50
|
||||||
|
)
|
||||||
|
|
||||||
|
// TwoQueueCache is a thread-safe fixed size 2Q cache.
|
||||||
|
// 2Q is an enhancement over the standard LRU cache
|
||||||
|
// in that it tracks both frequently and recently used
|
||||||
|
// entries seperately. This avoids a burst in access to new
|
||||||
|
// entries from evicting frequently used entries. It adds some
|
||||||
|
// additional tracking overhead to the standard LRU cache, and is
|
||||||
|
// computationally about 2x the cost, and adds some metadata over
|
||||||
|
// head. The ARCCache is similar, but does not require setting any
|
||||||
|
// parameters.
|
||||||
|
type TwoQueueCache struct {
|
||||||
|
size int
|
||||||
|
recentSize int
|
||||||
|
|
||||||
|
recent *internal.LRU
|
||||||
|
frequent *internal.LRU
|
||||||
|
recentEvict *internal.LRU
|
||||||
|
lock sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// New2Q creates a new TwoQueueCache using the default
|
||||||
|
// values for the parameters.
|
||||||
|
func New2Q(size int) (*TwoQueueCache, error) {
|
||||||
|
return New2QParams(size, Default2QRecentRatio, Default2QGhostEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New2QParams creates a new TwoQueueCache using the provided
|
||||||
|
// parameter values.
|
||||||
|
func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
|
||||||
|
if size <= 0 {
|
||||||
|
return nil, fmt.Errorf("invalid size")
|
||||||
|
}
|
||||||
|
if recentRatio < 0.0 || recentRatio > 1.0 {
|
||||||
|
return nil, fmt.Errorf("invalid recent ratio")
|
||||||
|
}
|
||||||
|
if ghostRatio < 0.0 || ghostRatio > 1.0 {
|
||||||
|
return nil, fmt.Errorf("invalid ghost ratio")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the sub-sizes
|
||||||
|
recentSize := int(float64(size) * recentRatio)
|
||||||
|
evictSize := int(float64(size) * ghostRatio)
|
||||||
|
|
||||||
|
// Allocate the LRUs
|
||||||
|
recent, err := internal.NewLRU(size, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
frequent, err := internal.NewLRU(size, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
recentEvict, err := internal.NewLRU(evictSize, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the cache
|
||||||
|
c := &TwoQueueCache{
|
||||||
|
size: size,
|
||||||
|
recentSize: recentSize,
|
||||||
|
recent: recent,
|
||||||
|
frequent: frequent,
|
||||||
|
recentEvict: recentEvict,
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Get(key interface{}) (interface{}, bool) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
// Check if this is a frequent value
|
||||||
|
if val, ok := c.frequent.Get(key); ok {
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the value is contained in recent, then we
|
||||||
|
// promote it to frequent
|
||||||
|
if val, ok := c.recent.Peek(key); ok {
|
||||||
|
c.recent.Remove(key)
|
||||||
|
c.frequent.Add(key, val)
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// No hit
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Add(key, value interface{}) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
// Check if the value is frequently used already,
|
||||||
|
// and just update the value
|
||||||
|
if c.frequent.Contains(key) {
|
||||||
|
c.frequent.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the value is recently used, and promote
|
||||||
|
// the value into the frequent list
|
||||||
|
if c.recent.Contains(key) {
|
||||||
|
c.recent.Remove(key)
|
||||||
|
c.frequent.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the value was recently evicted, add it to the
|
||||||
|
// frequently used list
|
||||||
|
if c.recentEvict.Contains(key) {
|
||||||
|
c.ensureSpace(true)
|
||||||
|
c.recentEvict.Remove(key)
|
||||||
|
c.frequent.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to the recently seen list
|
||||||
|
c.ensureSpace(false)
|
||||||
|
c.recent.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensureSpace is used to ensure we have space in the cache
|
||||||
|
func (c *TwoQueueCache) ensureSpace(recentEvict bool) {
|
||||||
|
// If we have space, nothing to do
|
||||||
|
recentLen := c.recent.Len()
|
||||||
|
freqLen := c.frequent.Len()
|
||||||
|
if recentLen+freqLen < c.size {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the recent buffer is larger than
|
||||||
|
// the target, evict from there
|
||||||
|
if recentLen > 0 && (recentLen > c.recentSize || (recentLen == c.recentSize && !recentEvict)) {
|
||||||
|
k, _, _ := c.recent.RemoveOldest()
|
||||||
|
c.recentEvict.Add(k, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from the frequent list otherwise
|
||||||
|
c.frequent.RemoveOldest()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Len() int {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
return c.recent.Len() + c.frequent.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Keys() []interface{} {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
k1 := c.frequent.Keys()
|
||||||
|
k2 := c.recent.Keys()
|
||||||
|
return append(k1, k2...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Remove(key interface{}) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
if c.frequent.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.recent.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.recentEvict.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Purge() {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
c.recent.Purge()
|
||||||
|
c.frequent.Purge()
|
||||||
|
c.recentEvict.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Contains(key interface{}) bool {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
return c.frequent.Contains(key) || c.recent.Contains(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TwoQueueCache) Peek(key interface{}) (interface{}, bool) {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
if val, ok := c.frequent.Peek(key); ok {
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
return c.recent.Peek(key)
|
||||||
|
}
|
257
Godeps/_workspace/src/github.com/hashicorp/golang-lru/arc.go
generated
vendored
Normal file
257
Godeps/_workspace/src/github.com/hashicorp/golang-lru/arc.go
generated
vendored
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/golang-lru/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ARCCache is a thread-safe fixed size Adaptive Replacement Cache (ARC).
|
||||||
|
// ARC is an enhancement over the standard LRU cache in that tracks both
|
||||||
|
// frequency and recency of use. This avoids a burst in access to new
|
||||||
|
// entries from evicting the frequently used older entries. It adds some
|
||||||
|
// additional tracking overhead to a standard LRU cache, computationally
|
||||||
|
// it is roughly 2x the cost, and the extra memory overhead is linear
|
||||||
|
// with the size of the cache. ARC has been patented by IBM, but is
|
||||||
|
// similar to the TwoQueueCache (2Q) which requires setting parameters.
|
||||||
|
type ARCCache struct {
|
||||||
|
size int // Size is the total capacity of the cache
|
||||||
|
p int // P is the dynamic preference towards T1 or T2
|
||||||
|
|
||||||
|
t1 *internal.LRU // T1 is the LRU for recently accessed items
|
||||||
|
b1 *internal.LRU // B1 is the LRU for evictions from t1
|
||||||
|
|
||||||
|
t2 *internal.LRU // T2 is the LRU for frequently accessed items
|
||||||
|
b2 *internal.LRU // B2 is the LRU for evictions from t2
|
||||||
|
|
||||||
|
lock sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewARC creates an ARC of the given size
|
||||||
|
func NewARC(size int) (*ARCCache, error) {
|
||||||
|
// Create the sub LRUs
|
||||||
|
b1, err := internal.NewLRU(size, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b2, err := internal.NewLRU(size, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t1, err := internal.NewLRU(size, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t2, err := internal.NewLRU(size, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the ARC
|
||||||
|
c := &ARCCache{
|
||||||
|
size: size,
|
||||||
|
p: 0,
|
||||||
|
t1: t1,
|
||||||
|
b1: b1,
|
||||||
|
t2: t2,
|
||||||
|
b2: b2,
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get looks up a key's value from the cache.
|
||||||
|
func (c *ARCCache) Get(key interface{}) (interface{}, bool) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
// Ff the value is contained in T1 (recent), then
|
||||||
|
// promote it to T2 (frequent)
|
||||||
|
if val, ok := c.t1.Peek(key); ok {
|
||||||
|
c.t1.Remove(key)
|
||||||
|
c.t2.Add(key, val)
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the value is contained in T2 (frequent)
|
||||||
|
if val, ok := c.t2.Get(key); ok {
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// No hit
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a value to the cache.
|
||||||
|
func (c *ARCCache) Add(key, value interface{}) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
|
// Check if the value is contained in T1 (recent), and potentially
|
||||||
|
// promote it to frequent T2
|
||||||
|
if c.t1.Contains(key) {
|
||||||
|
c.t1.Remove(key)
|
||||||
|
c.t2.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the value is already in T2 (frequent) and update it
|
||||||
|
if c.t2.Contains(key) {
|
||||||
|
c.t2.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this value was recently evicted as part of the
|
||||||
|
// recently used list
|
||||||
|
if c.b1.Contains(key) {
|
||||||
|
// T1 set is too small, increase P appropriately
|
||||||
|
delta := 1
|
||||||
|
b1Len := c.b1.Len()
|
||||||
|
b2Len := c.b2.Len()
|
||||||
|
if b2Len > b1Len {
|
||||||
|
delta = b2Len / b1Len
|
||||||
|
}
|
||||||
|
if c.p+delta >= c.size {
|
||||||
|
c.p = c.size
|
||||||
|
} else {
|
||||||
|
c.p += delta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potentially need to make room in the cache
|
||||||
|
if c.t1.Len()+c.t2.Len() >= c.size {
|
||||||
|
c.replace(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from B1
|
||||||
|
c.b1.Remove(key)
|
||||||
|
|
||||||
|
// Add the key to the frequently used list
|
||||||
|
c.t2.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this value was recently evicted as part of the
|
||||||
|
// frequently used list
|
||||||
|
if c.b2.Contains(key) {
|
||||||
|
// T2 set is too small, decrease P appropriately
|
||||||
|
delta := 1
|
||||||
|
b1Len := c.b1.Len()
|
||||||
|
b2Len := c.b2.Len()
|
||||||
|
if b1Len > b2Len {
|
||||||
|
delta = b1Len / b2Len
|
||||||
|
}
|
||||||
|
if delta >= c.p {
|
||||||
|
c.p = 0
|
||||||
|
} else {
|
||||||
|
c.p -= delta
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potentially need to make room in the cache
|
||||||
|
if c.t1.Len()+c.t2.Len() >= c.size {
|
||||||
|
c.replace(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from B2
|
||||||
|
c.b2.Remove(key)
|
||||||
|
|
||||||
|
// Add the key to the frequntly used list
|
||||||
|
c.t2.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Potentially need to make room in the cache
|
||||||
|
if c.t1.Len()+c.t2.Len() >= c.size {
|
||||||
|
c.replace(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the size of the ghost buffers trim
|
||||||
|
if c.b1.Len() > c.size-c.p {
|
||||||
|
c.b1.RemoveOldest()
|
||||||
|
}
|
||||||
|
if c.b2.Len() > c.p {
|
||||||
|
c.b2.RemoveOldest()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to the recently seen list
|
||||||
|
c.t1.Add(key, value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace is used to adaptively evict from either T1 or T2
|
||||||
|
// based on the current learned value of P
|
||||||
|
func (c *ARCCache) replace(b2ContainsKey bool) {
|
||||||
|
t1Len := c.t1.Len()
|
||||||
|
if t1Len > 0 && (t1Len > c.p || (t1Len == c.p && b2ContainsKey)) {
|
||||||
|
k, _, ok := c.t1.RemoveOldest()
|
||||||
|
if ok {
|
||||||
|
c.b1.Add(k, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
k, _, ok := c.t2.RemoveOldest()
|
||||||
|
if ok {
|
||||||
|
c.b2.Add(k, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of cached entries
|
||||||
|
func (c *ARCCache) Len() int {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
return c.t1.Len() + c.t2.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all the cached keys
|
||||||
|
func (c *ARCCache) Keys() []interface{} {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
k1 := c.t1.Keys()
|
||||||
|
k2 := c.t2.Keys()
|
||||||
|
return append(k1, k2...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove is used to purge a key from the cache
|
||||||
|
func (c *ARCCache) Remove(key interface{}) {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
if c.t1.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.t2.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.b1.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.b2.Remove(key) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge is used to clear the cache
|
||||||
|
func (c *ARCCache) Purge() {
|
||||||
|
c.lock.Lock()
|
||||||
|
defer c.lock.Unlock()
|
||||||
|
c.t1.Purge()
|
||||||
|
c.t2.Purge()
|
||||||
|
c.b1.Purge()
|
||||||
|
c.b2.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains is used to check if the cache contains a key
|
||||||
|
// without updating recency or frequency.
|
||||||
|
func (c *ARCCache) Contains(key interface{}) bool {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
return c.t1.Contains(key) || c.t2.Contains(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peek is used to inspect the cache value of a key
|
||||||
|
// without updating recency or frequency.
|
||||||
|
func (c *ARCCache) Peek(key interface{}) (interface{}, bool) {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
if val, ok := c.t1.Peek(key); ok {
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
return c.t2.Peek(key)
|
||||||
|
}
|
160
Godeps/_workspace/src/github.com/hashicorp/golang-lru/internal/lru.go
generated
vendored
Normal file
160
Godeps/_workspace/src/github.com/hashicorp/golang-lru/internal/lru.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/list"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EvictCallback is used to get a callback when a cache entry is evicted
|
||||||
|
type EvictCallback func(key interface{}, value interface{})
|
||||||
|
|
||||||
|
// LRU implements a non-thread safe fixed size LRU cache
|
||||||
|
type LRU struct {
|
||||||
|
size int
|
||||||
|
evictList *list.List
|
||||||
|
items map[interface{}]*list.Element
|
||||||
|
onEvict EvictCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry is used to hold a value in the evictList
|
||||||
|
type entry struct {
|
||||||
|
key interface{}
|
||||||
|
value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLRU constructs an LRU of the given size
|
||||||
|
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
||||||
|
if size <= 0 {
|
||||||
|
return nil, errors.New("Must provide a positive size")
|
||||||
|
}
|
||||||
|
c := &LRU{
|
||||||
|
size: size,
|
||||||
|
evictList: list.New(),
|
||||||
|
items: make(map[interface{}]*list.Element),
|
||||||
|
onEvict: onEvict,
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge is used to completely clear the cache
|
||||||
|
func (c *LRU) Purge() {
|
||||||
|
for k, v := range c.items {
|
||||||
|
if c.onEvict != nil {
|
||||||
|
c.onEvict(k, v.Value.(*entry).value)
|
||||||
|
}
|
||||||
|
delete(c.items, k)
|
||||||
|
}
|
||||||
|
c.evictList.Init()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a value to the cache. Returns true if an eviction occured.
|
||||||
|
func (c *LRU) Add(key, value interface{}) bool {
|
||||||
|
// Check for existing item
|
||||||
|
if ent, ok := c.items[key]; ok {
|
||||||
|
c.evictList.MoveToFront(ent)
|
||||||
|
ent.Value.(*entry).value = value
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new item
|
||||||
|
ent := &entry{key, value}
|
||||||
|
entry := c.evictList.PushFront(ent)
|
||||||
|
c.items[key] = entry
|
||||||
|
|
||||||
|
evict := c.evictList.Len() > c.size
|
||||||
|
// Verify size not exceeded
|
||||||
|
if evict {
|
||||||
|
c.removeOldest()
|
||||||
|
}
|
||||||
|
return evict
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get looks up a key's value from the cache.
|
||||||
|
func (c *LRU) Get(key interface{}) (value interface{}, ok bool) {
|
||||||
|
if ent, ok := c.items[key]; ok {
|
||||||
|
c.evictList.MoveToFront(ent)
|
||||||
|
return ent.Value.(*entry).value, true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a key is in the cache, without updating the recent-ness
|
||||||
|
// or deleting it for being stale.
|
||||||
|
func (c *LRU) Contains(key interface{}) (ok bool) {
|
||||||
|
_, ok = c.items[key]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the key value (or undefined if not found) without updating
|
||||||
|
// the "recently used"-ness of the key.
|
||||||
|
func (c *LRU) Peek(key interface{}) (value interface{}, ok bool) {
|
||||||
|
if ent, ok := c.items[key]; ok {
|
||||||
|
return ent.Value.(*entry).value, true
|
||||||
|
}
|
||||||
|
return nil, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the provided key from the cache, returning if the
|
||||||
|
// key was contained.
|
||||||
|
func (c *LRU) Remove(key interface{}) bool {
|
||||||
|
if ent, ok := c.items[key]; ok {
|
||||||
|
c.removeElement(ent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
|
func (c *LRU) RemoveOldest() (interface{}, interface{}, bool) {
|
||||||
|
ent := c.evictList.Back()
|
||||||
|
if ent != nil {
|
||||||
|
c.removeElement(ent)
|
||||||
|
kv := ent.Value.(*entry)
|
||||||
|
return kv.key, kv.value, true
|
||||||
|
}
|
||||||
|
return nil, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOldest returns the oldest entry
|
||||||
|
func (c *LRU) GetOldest() (interface{}, interface{}, bool) {
|
||||||
|
ent := c.evictList.Back()
|
||||||
|
if ent != nil {
|
||||||
|
kv := ent.Value.(*entry)
|
||||||
|
return kv.key, kv.value, true
|
||||||
|
}
|
||||||
|
return nil, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns a slice of the keys in the cache, from oldest to newest.
|
||||||
|
func (c *LRU) Keys() []interface{} {
|
||||||
|
keys := make([]interface{}, len(c.items))
|
||||||
|
i := 0
|
||||||
|
for ent := c.evictList.Back(); ent != nil; ent = ent.Prev() {
|
||||||
|
keys[i] = ent.Value.(*entry).key
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of items in the cache.
|
||||||
|
func (c *LRU) Len() int {
|
||||||
|
return c.evictList.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeOldest removes the oldest item from the cache.
|
||||||
|
func (c *LRU) removeOldest() {
|
||||||
|
ent := c.evictList.Back()
|
||||||
|
if ent != nil {
|
||||||
|
c.removeElement(ent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeElement is used to remove a given list element from the cache
|
||||||
|
func (c *LRU) removeElement(e *list.Element) {
|
||||||
|
c.evictList.Remove(e)
|
||||||
|
kv := e.Value.(*entry)
|
||||||
|
delete(c.items, kv.key)
|
||||||
|
if c.onEvict != nil {
|
||||||
|
c.onEvict(kv.key, kv.value)
|
||||||
|
}
|
||||||
|
}
|
157
Godeps/_workspace/src/github.com/hashicorp/golang-lru/lru.go
generated
vendored
157
Godeps/_workspace/src/github.com/hashicorp/golang-lru/lru.go
generated
vendored
|
@ -4,24 +4,15 @@
|
||||||
package lru
|
package lru
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
|
||||||
"errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/golang-lru/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cache is a thread-safe fixed size LRU cache.
|
// Cache is a thread-safe fixed size LRU cache.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
size int
|
lru *internal.LRU
|
||||||
evictList *list.List
|
lock sync.RWMutex
|
||||||
items map[interface{}]*list.Element
|
|
||||||
lock sync.RWMutex
|
|
||||||
onEvicted func(key interface{}, value interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// entry is used to hold a value in the evictList
|
|
||||||
type entry struct {
|
|
||||||
key interface{}
|
|
||||||
value interface{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates an LRU of the given size
|
// New creates an LRU of the given size
|
||||||
|
@ -29,15 +20,15 @@ func New(size int) (*Cache, error) {
|
||||||
return NewWithEvict(size, nil)
|
return NewWithEvict(size, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewWithEvict constructs a fixed size cache with the given eviction
|
||||||
|
// callback.
|
||||||
func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
|
func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
|
||||||
if size <= 0 {
|
lru, err := internal.NewLRU(size, internal.EvictCallback(onEvicted))
|
||||||
return nil, errors.New("Must provide a positive size")
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
c := &Cache{
|
c := &Cache{
|
||||||
size: size,
|
lru: lru,
|
||||||
evictList: list.New(),
|
|
||||||
items: make(map[interface{}]*list.Element),
|
|
||||||
onEvicted: onEvicted,
|
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
@ -45,155 +36,79 @@ func NewWithEvict(size int, onEvicted func(key interface{}, value interface{}))
|
||||||
// Purge is used to completely clear the cache
|
// Purge is used to completely clear the cache
|
||||||
func (c *Cache) Purge() {
|
func (c *Cache) Purge() {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
c.lru.Purge()
|
||||||
|
c.lock.Unlock()
|
||||||
for k, v := range c.items {
|
|
||||||
if c.onEvicted != nil {
|
|
||||||
c.onEvicted(k, v.Value.(*entry).value)
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(c.items, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 occured.
|
||||||
func (c *Cache) Add(key, value interface{}) bool {
|
func (c *Cache) Add(key, value interface{}) bool {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
return c.lru.Add(key, value)
|
||||||
// Check for existing item
|
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
c.evictList.MoveToFront(ent)
|
|
||||||
ent.Value.(*entry).value = value
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new item
|
|
||||||
ent := &entry{key, value}
|
|
||||||
entry := c.evictList.PushFront(ent)
|
|
||||||
c.items[key] = entry
|
|
||||||
|
|
||||||
evict := c.evictList.Len() > c.size
|
|
||||||
// Verify size not exceeded
|
|
||||||
if evict {
|
|
||||||
c.removeOldest()
|
|
||||||
}
|
|
||||||
return evict
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
// Get looks up a key's value from the cache.
|
||||||
func (c *Cache) Get(key interface{}) (value interface{}, ok bool) {
|
func (c *Cache) Get(key interface{}) (interface{}, bool) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
return c.lru.Get(key)
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
c.evictList.MoveToFront(ent)
|
|
||||||
return ent.Value.(*entry).value, true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a key is in the cache, without updating the recent-ness or deleting it for being stale.
|
// Check if a key is in the cache, without updating the recent-ness
|
||||||
func (c *Cache) Contains(key interface{}) (ok bool) {
|
// or deleting it for being stale.
|
||||||
|
func (c *Cache) Contains(key interface{}) bool {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
|
return c.lru.Contains(key)
|
||||||
_, ok = c.items[key]
|
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the key value (or undefined if not found) without updating the "recently used"-ness of the key.
|
// Returns the key value (or undefined if not found) without updating
|
||||||
// (If you find yourself using this a lot, you might be using the wrong sort of data structure, but there are some use cases where it's handy.)
|
// the "recently used"-ness of the key.
|
||||||
func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
|
func (c *Cache) Peek(key interface{}) (interface{}, bool) {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
|
return c.lru.Peek(key)
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
return ent.Value.(*entry).value, true
|
|
||||||
}
|
|
||||||
return nil, ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainsOrAdd checks if a key is in the cache (without updating the recent-ness or deleting it for being stale),
|
// ContainsOrAdd checks if a key is in the cache without updating the
|
||||||
// if not, adds the value. Returns whether found and whether an eviction occurred.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evict bool) {
|
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evict bool) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
_, ok = c.items[key]
|
if c.lru.Contains(key) {
|
||||||
if ok {
|
|
||||||
return true, false
|
return true, false
|
||||||
|
} else {
|
||||||
|
evict := c.lru.Add(key, value)
|
||||||
|
return false, evict
|
||||||
}
|
}
|
||||||
|
|
||||||
ent := &entry{key, value}
|
|
||||||
entry := c.evictList.PushFront(ent)
|
|
||||||
c.items[key] = entry
|
|
||||||
|
|
||||||
evict = c.evictList.Len() > c.size
|
|
||||||
// Verify size not exceeded
|
|
||||||
if evict {
|
|
||||||
c.removeOldest()
|
|
||||||
}
|
|
||||||
return false, evict
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
// Remove removes the provided key from the cache.
|
||||||
func (c *Cache) Remove(key interface{}) {
|
func (c *Cache) Remove(key interface{}) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
c.lru.Remove(key)
|
||||||
|
c.lock.Unlock()
|
||||||
if ent, ok := c.items[key]; ok {
|
|
||||||
c.removeElement(ent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *Cache) RemoveOldest() {
|
func (c *Cache) RemoveOldest() {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
c.lru.RemoveOldest()
|
||||||
c.removeOldest()
|
c.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keys returns a slice of the keys in the cache, from oldest to newest.
|
// Keys returns a slice of the keys in the cache, from oldest to newest.
|
||||||
func (c *Cache) Keys() []interface{} {
|
func (c *Cache) Keys() []interface{} {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
|
return c.lru.Keys()
|
||||||
keys := make([]interface{}, len(c.items))
|
|
||||||
ent := c.evictList.Back()
|
|
||||||
i := 0
|
|
||||||
for ent != nil {
|
|
||||||
keys[i] = ent.Value.(*entry).key
|
|
||||||
ent = ent.Prev()
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the number of items in the cache.
|
// Len returns the number of items in the cache.
|
||||||
func (c *Cache) Len() int {
|
func (c *Cache) Len() int {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
return c.evictList.Len()
|
return c.lru.Len()
|
||||||
}
|
|
||||||
|
|
||||||
// removeOldest removes the oldest item from the cache.
|
|
||||||
func (c *Cache) removeOldest() {
|
|
||||||
ent := c.evictList.Back()
|
|
||||||
if ent != nil {
|
|
||||||
c.removeElement(ent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeElement is used to remove a given list element from the cache
|
|
||||||
func (c *Cache) removeElement(e *list.Element) {
|
|
||||||
c.evictList.Remove(e)
|
|
||||||
kv := e.Value.(*entry)
|
|
||||||
delete(c.items, kv.key)
|
|
||||||
if c.onEvicted != nil {
|
|
||||||
c.onEvicted(kv.key, kv.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
10
Godeps/_workspace/src/github.com/kardianos/osext/osext.go
generated
vendored
10
Godeps/_workspace/src/github.com/kardianos/osext/osext.go
generated
vendored
|
@ -7,12 +7,18 @@ package osext
|
||||||
|
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
|
|
||||||
|
var cx, ce = executableClean()
|
||||||
|
|
||||||
|
func executableClean() (string, error) {
|
||||||
|
p, err := executable()
|
||||||
|
return filepath.Clean(p), err
|
||||||
|
}
|
||||||
|
|
||||||
// Executable returns an absolute path that can be used to
|
// Executable returns an absolute path that can be used to
|
||||||
// re-invoke the current program.
|
// re-invoke the current program.
|
||||||
// It may not be valid after the current program exits.
|
// It may not be valid after the current program exits.
|
||||||
func Executable() (string, error) {
|
func Executable() (string, error) {
|
||||||
p, err := executable()
|
return cx, ce
|
||||||
return filepath.Clean(p), err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns same path as Executable, returns just the folder
|
// Returns same path as Executable, returns just the folder
|
||||||
|
|
46
Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
generated
vendored
46
Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
generated
vendored
|
@ -53,30 +53,30 @@ func executable() (string, error) {
|
||||||
// NULL terminated arguments.
|
// NULL terminated arguments.
|
||||||
var args []string
|
var args []string
|
||||||
argv := uintptr(unsafe.Pointer(&buf[0]))
|
argv := uintptr(unsafe.Pointer(&buf[0]))
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
argp := *(**[1<<20]byte)(unsafe.Pointer(argv))
|
argp := *(**[1 << 20]byte)(unsafe.Pointer(argv))
|
||||||
if argp == nil {
|
if argp == nil {
|
||||||
break
|
break
|
||||||
}
|
|
||||||
for i := 0; uintptr(i) < n; i++ {
|
|
||||||
// we don't want the full arguments list
|
|
||||||
if string(argp[i]) == " " {
|
|
||||||
break Loop
|
|
||||||
}
|
|
||||||
if argp[i] != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
args = append(args, string(argp[:i]))
|
|
||||||
n -= uintptr(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if n < unsafe.Sizeof(argv) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
argv += unsafe.Sizeof(argv)
|
|
||||||
n -= unsafe.Sizeof(argv)
|
|
||||||
}
|
}
|
||||||
|
for i := 0; uintptr(i) < n; i++ {
|
||||||
|
// we don't want the full arguments list
|
||||||
|
if string(argp[i]) == " " {
|
||||||
|
break Loop
|
||||||
|
}
|
||||||
|
if argp[i] != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
args = append(args, string(argp[:i]))
|
||||||
|
n -= uintptr(i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if n < unsafe.Sizeof(argv) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
argv += unsafe.Sizeof(argv)
|
||||||
|
n -= unsafe.Sizeof(argv)
|
||||||
|
}
|
||||||
execPath = args[0]
|
execPath = args[0]
|
||||||
// There is no canonical way to get an executable path on
|
// There is no canonical way to get an executable path on
|
||||||
// OpenBSD, so check PATH in case we are called directly
|
// OpenBSD, so check PATH in case we are called directly
|
||||||
|
|
14
Godeps/_workspace/src/github.com/lib/pq/conn.go
generated
vendored
14
Godeps/_workspace/src/github.com/lib/pq/conn.go
generated
vendored
|
@ -557,13 +557,15 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
|
||||||
cn.bad = true
|
cn.bad = true
|
||||||
errorf("unexpected message %q in simple query execution", t)
|
errorf("unexpected message %q in simple query execution", t)
|
||||||
}
|
}
|
||||||
res = &rows{
|
if res == nil {
|
||||||
cn: cn,
|
res = &rows{
|
||||||
colNames: st.colNames,
|
cn: cn,
|
||||||
colTyps: st.colTyps,
|
colNames: st.colNames,
|
||||||
colFmts: st.colFmts,
|
colTyps: st.colTyps,
|
||||||
done: true,
|
colFmts: st.colFmts,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
res.done = true
|
||||||
case 'Z':
|
case 'Z':
|
||||||
cn.processReadyForQuery(r)
|
cn.processReadyForQuery(r)
|
||||||
// done
|
// done
|
||||||
|
|
2
Godeps/_workspace/src/golang.org/x/crypto/ssh/kex.go
generated
vendored
2
Godeps/_workspace/src/golang.org/x/crypto/ssh/kex.go
generated
vendored
|
@ -8,8 +8,8 @@ import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/subtle"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
188
Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE
generated
vendored
Normal file
188
Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
|
||||||
|
Copyright (c) 2011-2014 - Canonical Inc.
|
||||||
|
|
||||||
|
This software is licensed under the LGPLv3, included below.
|
||||||
|
|
||||||
|
As a special exception to the GNU Lesser General Public License version 3
|
||||||
|
("LGPL3"), the copyright holders of this Library give you permission to
|
||||||
|
convey to a third party a Combined Work that links statically or dynamically
|
||||||
|
to this Library without providing any Minimal Corresponding Source or
|
||||||
|
Minimal Application Code as set out in 4d or providing the installation
|
||||||
|
information set out in section 4e, provided that you comply with the other
|
||||||
|
provisions of LGPL3 and provided that you meet, for the Application the
|
||||||
|
terms and conditions of the license(s) which apply to the Application.
|
||||||
|
|
||||||
|
Except as stated in this special exception, the provisions of LGPL3 will
|
||||||
|
continue to comply in full to this Library. If you modify this Library, you
|
||||||
|
may apply this exception to your version of this Library, but you are not
|
||||||
|
obliged to do so. If you do not wish to do so, delete this exception
|
||||||
|
statement from your version. This exception does not (and cannot) modify any
|
||||||
|
license terms which apply to the Application, with which you must still
|
||||||
|
comply.
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
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 that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU 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 as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
31
Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml
generated
vendored
Normal file
31
Godeps/_workspace/src/gopkg.in/yaml.v2/LICENSE.libyaml
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
The following files were ported to Go from C files of libyaml, and thus
|
||||||
|
are still covered by their original copyright and license:
|
||||||
|
|
||||||
|
apic.go
|
||||||
|
emitterc.go
|
||||||
|
parserc.go
|
||||||
|
readerc.go
|
||||||
|
scannerc.go
|
||||||
|
writerc.go
|
||||||
|
yamlh.go
|
||||||
|
yamlprivateh.go
|
||||||
|
|
||||||
|
Copyright (c) 2006 Kirill Simonov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
131
Godeps/_workspace/src/gopkg.in/yaml.v2/README.md
generated
vendored
Normal file
131
Godeps/_workspace/src/gopkg.in/yaml.v2/README.md
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
# YAML support for the Go language
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
The yaml package enables Go programs to comfortably encode and decode YAML
|
||||||
|
values. It was developed within [Canonical](https://www.canonical.com) as
|
||||||
|
part of the [juju](https://juju.ubuntu.com) project, and is based on a
|
||||||
|
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
|
||||||
|
C library to parse and generate YAML data quickly and reliably.
|
||||||
|
|
||||||
|
Compatibility
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The yaml package supports most of YAML 1.1 and 1.2, including support for
|
||||||
|
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
|
||||||
|
implemented, and base-60 floats from YAML 1.1 are purposefully not
|
||||||
|
supported since they're a poor design and are gone in YAML 1.2.
|
||||||
|
|
||||||
|
Installation and usage
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The import path for the package is *gopkg.in/yaml.v2*.
|
||||||
|
|
||||||
|
To install it, run:
|
||||||
|
|
||||||
|
go get gopkg.in/yaml.v2
|
||||||
|
|
||||||
|
API documentation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
If opened in a browser, the import path itself leads to the API documentation:
|
||||||
|
|
||||||
|
* [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
|
||||||
|
|
||||||
|
API stability
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details.
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var data = `
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
`
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
A string
|
||||||
|
B struct {
|
||||||
|
RenamedC int `yaml:"c"`
|
||||||
|
D []int `yaml:",flow"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
t := T{}
|
||||||
|
|
||||||
|
err := yaml.Unmarshal([]byte(data), &t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- t:\n%v\n\n", t)
|
||||||
|
|
||||||
|
d, err := yaml.Marshal(&t)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||||
|
|
||||||
|
m := make(map[interface{}]interface{})
|
||||||
|
|
||||||
|
err = yaml.Unmarshal([]byte(data), &m)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- m:\n%v\n\n", m)
|
||||||
|
|
||||||
|
d, err = yaml.Marshal(&m)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("error: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This example will generate the following output:
|
||||||
|
|
||||||
|
```
|
||||||
|
--- t:
|
||||||
|
{Easy! {2 [3 4]}}
|
||||||
|
|
||||||
|
--- t dump:
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d: [3, 4]
|
||||||
|
|
||||||
|
|
||||||
|
--- m:
|
||||||
|
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||||
|
|
||||||
|
--- m dump:
|
||||||
|
a: Easy!
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
d:
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
```
|
||||||
|
|
742
Godeps/_workspace/src/gopkg.in/yaml.v2/apic.go
generated
vendored
Normal file
742
Godeps/_workspace/src/gopkg.in/yaml.v2/apic.go
generated
vendored
Normal file
|
@ -0,0 +1,742 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
|
||||||
|
//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
|
||||||
|
|
||||||
|
// Check if we can move the queue at the beginning of the buffer.
|
||||||
|
if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
|
||||||
|
if parser.tokens_head != len(parser.tokens) {
|
||||||
|
copy(parser.tokens, parser.tokens[parser.tokens_head:])
|
||||||
|
}
|
||||||
|
parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
|
||||||
|
parser.tokens_head = 0
|
||||||
|
}
|
||||||
|
parser.tokens = append(parser.tokens, *token)
|
||||||
|
if pos < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
|
||||||
|
parser.tokens[parser.tokens_head+pos] = *token
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new parser object.
|
||||||
|
func yaml_parser_initialize(parser *yaml_parser_t) bool {
|
||||||
|
*parser = yaml_parser_t{
|
||||||
|
raw_buffer: make([]byte, 0, input_raw_buffer_size),
|
||||||
|
buffer: make([]byte, 0, input_buffer_size),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a parser object.
|
||||||
|
func yaml_parser_delete(parser *yaml_parser_t) {
|
||||||
|
*parser = yaml_parser_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String read handler.
|
||||||
|
func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||||
|
if parser.input_pos == len(parser.input) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
n = copy(buffer, parser.input[parser.input_pos:])
|
||||||
|
parser.input_pos += n
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// File read handler.
|
||||||
|
func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
|
||||||
|
return parser.input_file.Read(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a string input.
|
||||||
|
func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
|
||||||
|
if parser.read_handler != nil {
|
||||||
|
panic("must set the input source only once")
|
||||||
|
}
|
||||||
|
parser.read_handler = yaml_string_read_handler
|
||||||
|
parser.input = input
|
||||||
|
parser.input_pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a file input.
|
||||||
|
func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) {
|
||||||
|
if parser.read_handler != nil {
|
||||||
|
panic("must set the input source only once")
|
||||||
|
}
|
||||||
|
parser.read_handler = yaml_file_read_handler
|
||||||
|
parser.input_file = file
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the source encoding.
|
||||||
|
func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
|
||||||
|
if parser.encoding != yaml_ANY_ENCODING {
|
||||||
|
panic("must set the encoding only once")
|
||||||
|
}
|
||||||
|
parser.encoding = encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new emitter object.
|
||||||
|
func yaml_emitter_initialize(emitter *yaml_emitter_t) bool {
|
||||||
|
*emitter = yaml_emitter_t{
|
||||||
|
buffer: make([]byte, output_buffer_size),
|
||||||
|
raw_buffer: make([]byte, 0, output_raw_buffer_size),
|
||||||
|
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
|
||||||
|
events: make([]yaml_event_t, 0, initial_queue_size),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an emitter object.
|
||||||
|
func yaml_emitter_delete(emitter *yaml_emitter_t) {
|
||||||
|
*emitter = yaml_emitter_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String write handler.
|
||||||
|
func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||||
|
*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// File write handler.
|
||||||
|
func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
|
||||||
|
_, err := emitter.output_file.Write(buffer)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a string output.
|
||||||
|
func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
|
||||||
|
if emitter.write_handler != nil {
|
||||||
|
panic("must set the output target only once")
|
||||||
|
}
|
||||||
|
emitter.write_handler = yaml_string_write_handler
|
||||||
|
emitter.output_buffer = output_buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a file output.
|
||||||
|
func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Writer) {
|
||||||
|
if emitter.write_handler != nil {
|
||||||
|
panic("must set the output target only once")
|
||||||
|
}
|
||||||
|
emitter.write_handler = yaml_file_write_handler
|
||||||
|
emitter.output_file = file
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the output encoding.
|
||||||
|
func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
|
||||||
|
if emitter.encoding != yaml_ANY_ENCODING {
|
||||||
|
panic("must set the output encoding only once")
|
||||||
|
}
|
||||||
|
emitter.encoding = encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the canonical output style.
|
||||||
|
func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
|
||||||
|
emitter.canonical = canonical
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Set the indentation increment.
|
||||||
|
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
|
||||||
|
if indent < 2 || indent > 9 {
|
||||||
|
indent = 2
|
||||||
|
}
|
||||||
|
emitter.best_indent = indent
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the preferred line width.
|
||||||
|
func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
|
||||||
|
if width < 0 {
|
||||||
|
width = -1
|
||||||
|
}
|
||||||
|
emitter.best_width = width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set if unescaped non-ASCII characters are allowed.
|
||||||
|
func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
|
||||||
|
emitter.unicode = unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the preferred line break character.
|
||||||
|
func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
|
||||||
|
emitter.line_break = line_break
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Destroy a token object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(void)
|
||||||
|
//yaml_token_delete(yaml_token_t *token)
|
||||||
|
//{
|
||||||
|
// assert(token); // Non-NULL token object expected.
|
||||||
|
//
|
||||||
|
// switch (token.type)
|
||||||
|
// {
|
||||||
|
// case YAML_TAG_DIRECTIVE_TOKEN:
|
||||||
|
// yaml_free(token.data.tag_directive.handle);
|
||||||
|
// yaml_free(token.data.tag_directive.prefix);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_ALIAS_TOKEN:
|
||||||
|
// yaml_free(token.data.alias.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_ANCHOR_TOKEN:
|
||||||
|
// yaml_free(token.data.anchor.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_TAG_TOKEN:
|
||||||
|
// yaml_free(token.data.tag.handle);
|
||||||
|
// yaml_free(token.data.tag.suffix);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case YAML_SCALAR_TOKEN:
|
||||||
|
// yaml_free(token.data.scalar.value);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// memset(token, 0, sizeof(yaml_token_t));
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Check if a string is a valid UTF-8 sequence.
|
||||||
|
// *
|
||||||
|
// * Check 'reader.c' for more details on UTF-8 encoding.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//static int
|
||||||
|
//yaml_check_utf8(yaml_char_t *start, size_t length)
|
||||||
|
//{
|
||||||
|
// yaml_char_t *end = start+length;
|
||||||
|
// yaml_char_t *pointer = start;
|
||||||
|
//
|
||||||
|
// while (pointer < end) {
|
||||||
|
// unsigned char octet;
|
||||||
|
// unsigned int width;
|
||||||
|
// unsigned int value;
|
||||||
|
// size_t k;
|
||||||
|
//
|
||||||
|
// octet = pointer[0];
|
||||||
|
// width = (octet & 0x80) == 0x00 ? 1 :
|
||||||
|
// (octet & 0xE0) == 0xC0 ? 2 :
|
||||||
|
// (octet & 0xF0) == 0xE0 ? 3 :
|
||||||
|
// (octet & 0xF8) == 0xF0 ? 4 : 0;
|
||||||
|
// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
|
||||||
|
// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
|
||||||
|
// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
|
||||||
|
// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
|
||||||
|
// if (!width) return 0;
|
||||||
|
// if (pointer+width > end) return 0;
|
||||||
|
// for (k = 1; k < width; k ++) {
|
||||||
|
// octet = pointer[k];
|
||||||
|
// if ((octet & 0xC0) != 0x80) return 0;
|
||||||
|
// value = (value << 6) + (octet & 0x3F);
|
||||||
|
// }
|
||||||
|
// if (!((width == 1) ||
|
||||||
|
// (width == 2 && value >= 0x80) ||
|
||||||
|
// (width == 3 && value >= 0x800) ||
|
||||||
|
// (width == 4 && value >= 0x10000))) return 0;
|
||||||
|
//
|
||||||
|
// pointer += width;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return 1;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
|
||||||
|
// Create STREAM-START.
|
||||||
|
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_STREAM_START_EVENT,
|
||||||
|
encoding: encoding,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create STREAM-END.
|
||||||
|
func yaml_stream_end_event_initialize(event *yaml_event_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_STREAM_END_EVENT,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create DOCUMENT-START.
|
||||||
|
func yaml_document_start_event_initialize(event *yaml_event_t, version_directive *yaml_version_directive_t,
|
||||||
|
tag_directives []yaml_tag_directive_t, implicit bool) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_DOCUMENT_START_EVENT,
|
||||||
|
version_directive: version_directive,
|
||||||
|
tag_directives: tag_directives,
|
||||||
|
implicit: implicit,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create DOCUMENT-END.
|
||||||
|
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_DOCUMENT_END_EVENT,
|
||||||
|
implicit: implicit,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Create ALIAS.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
|
||||||
|
//{
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// anchor_copy *yaml_char_t = NULL
|
||||||
|
//
|
||||||
|
// assert(event) // Non-NULL event object is expected.
|
||||||
|
// assert(anchor) // Non-NULL anchor is expected.
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
|
||||||
|
//
|
||||||
|
// anchor_copy = yaml_strdup(anchor)
|
||||||
|
// if (!anchor_copy)
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Create SCALAR.
|
||||||
|
func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SCALAR_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
value: value,
|
||||||
|
implicit: plain_implicit,
|
||||||
|
quoted_implicit: quoted_implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SEQUENCE-START.
|
||||||
|
func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SEQUENCE_START_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
implicit: implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SEQUENCE-END.
|
||||||
|
func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_SEQUENCE_END_EVENT,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MAPPING-START.
|
||||||
|
func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_MAPPING_START_EVENT,
|
||||||
|
anchor: anchor,
|
||||||
|
tag: tag,
|
||||||
|
implicit: implicit,
|
||||||
|
style: yaml_style_t(style),
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create MAPPING-END.
|
||||||
|
func yaml_mapping_end_event_initialize(event *yaml_event_t) bool {
|
||||||
|
*event = yaml_event_t{
|
||||||
|
typ: yaml_MAPPING_END_EVENT,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an event object.
|
||||||
|
func yaml_event_delete(event *yaml_event_t) {
|
||||||
|
*event = yaml_event_t{}
|
||||||
|
}
|
||||||
|
|
||||||
|
///*
|
||||||
|
// * Create a document object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_initialize(document *yaml_document_t,
|
||||||
|
// version_directive *yaml_version_directive_t,
|
||||||
|
// tag_directives_start *yaml_tag_directive_t,
|
||||||
|
// tag_directives_end *yaml_tag_directive_t,
|
||||||
|
// start_implicit int, end_implicit int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_t
|
||||||
|
// end *yaml_node_t
|
||||||
|
// top *yaml_node_t
|
||||||
|
// } nodes = { NULL, NULL, NULL }
|
||||||
|
// version_directive_copy *yaml_version_directive_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_tag_directive_t
|
||||||
|
// end *yaml_tag_directive_t
|
||||||
|
// top *yaml_tag_directive_t
|
||||||
|
// } tag_directives_copy = { NULL, NULL, NULL }
|
||||||
|
// value yaml_tag_directive_t = { NULL, NULL }
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
// assert((tag_directives_start && tag_directives_end) ||
|
||||||
|
// (tag_directives_start == tag_directives_end))
|
||||||
|
// // Valid tag directives are expected.
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// if (version_directive) {
|
||||||
|
// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
|
||||||
|
// if (!version_directive_copy) goto error
|
||||||
|
// version_directive_copy.major = version_directive.major
|
||||||
|
// version_directive_copy.minor = version_directive.minor
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (tag_directives_start != tag_directives_end) {
|
||||||
|
// tag_directive *yaml_tag_directive_t
|
||||||
|
// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
|
||||||
|
// goto error
|
||||||
|
// for (tag_directive = tag_directives_start
|
||||||
|
// tag_directive != tag_directives_end; tag_directive ++) {
|
||||||
|
// assert(tag_directive.handle)
|
||||||
|
// assert(tag_directive.prefix)
|
||||||
|
// if (!yaml_check_utf8(tag_directive.handle,
|
||||||
|
// strlen((char *)tag_directive.handle)))
|
||||||
|
// goto error
|
||||||
|
// if (!yaml_check_utf8(tag_directive.prefix,
|
||||||
|
// strlen((char *)tag_directive.prefix)))
|
||||||
|
// goto error
|
||||||
|
// value.handle = yaml_strdup(tag_directive.handle)
|
||||||
|
// value.prefix = yaml_strdup(tag_directive.prefix)
|
||||||
|
// if (!value.handle || !value.prefix) goto error
|
||||||
|
// if (!PUSH(&context, tag_directives_copy, value))
|
||||||
|
// goto error
|
||||||
|
// value.handle = NULL
|
||||||
|
// value.prefix = NULL
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
|
||||||
|
// tag_directives_copy.start, tag_directives_copy.top,
|
||||||
|
// start_implicit, end_implicit, mark, mark)
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, nodes)
|
||||||
|
// yaml_free(version_directive_copy)
|
||||||
|
// while (!STACK_EMPTY(&context, tag_directives_copy)) {
|
||||||
|
// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
|
||||||
|
// yaml_free(value.handle)
|
||||||
|
// yaml_free(value.prefix)
|
||||||
|
// }
|
||||||
|
// STACK_DEL(&context, tag_directives_copy)
|
||||||
|
// yaml_free(value.handle)
|
||||||
|
// yaml_free(value.prefix)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Destroy a document object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(void)
|
||||||
|
//yaml_document_delete(document *yaml_document_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// tag_directive *yaml_tag_directive_t
|
||||||
|
//
|
||||||
|
// context.error = YAML_NO_ERROR // Eliminate a compliler warning.
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// while (!STACK_EMPTY(&context, document.nodes)) {
|
||||||
|
// node yaml_node_t = POP(&context, document.nodes)
|
||||||
|
// yaml_free(node.tag)
|
||||||
|
// switch (node.type) {
|
||||||
|
// case YAML_SCALAR_NODE:
|
||||||
|
// yaml_free(node.data.scalar.value)
|
||||||
|
// break
|
||||||
|
// case YAML_SEQUENCE_NODE:
|
||||||
|
// STACK_DEL(&context, node.data.sequence.items)
|
||||||
|
// break
|
||||||
|
// case YAML_MAPPING_NODE:
|
||||||
|
// STACK_DEL(&context, node.data.mapping.pairs)
|
||||||
|
// break
|
||||||
|
// default:
|
||||||
|
// assert(0) // Should not happen.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// STACK_DEL(&context, document.nodes)
|
||||||
|
//
|
||||||
|
// yaml_free(document.version_directive)
|
||||||
|
// for (tag_directive = document.tag_directives.start
|
||||||
|
// tag_directive != document.tag_directives.end
|
||||||
|
// tag_directive++) {
|
||||||
|
// yaml_free(tag_directive.handle)
|
||||||
|
// yaml_free(tag_directive.prefix)
|
||||||
|
// }
|
||||||
|
// yaml_free(document.tag_directives.start)
|
||||||
|
//
|
||||||
|
// memset(document, 0, sizeof(yaml_document_t))
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Get a document node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(yaml_node_t *)
|
||||||
|
//yaml_document_get_node(document *yaml_document_t, index int)
|
||||||
|
//{
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
|
||||||
|
// return document.nodes.start + index - 1
|
||||||
|
// }
|
||||||
|
// return NULL
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Get the root object.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(yaml_node_t *)
|
||||||
|
//yaml_document_get_root_node(document *yaml_document_t)
|
||||||
|
//{
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (document.nodes.top != document.nodes.start) {
|
||||||
|
// return document.nodes.start
|
||||||
|
// }
|
||||||
|
// return NULL
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a scalar node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_scalar(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, value *yaml_char_t, length int,
|
||||||
|
// style yaml_scalar_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// value_copy *yaml_char_t = NULL
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
// assert(value) // Non-NULL value is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (length < 0) {
|
||||||
|
// length = strlen((char *)value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(value, length)) goto error
|
||||||
|
// value_copy = yaml_malloc(length+1)
|
||||||
|
// if (!value_copy) goto error
|
||||||
|
// memcpy(value_copy, value, length)
|
||||||
|
// value_copy[length] = '\0'
|
||||||
|
//
|
||||||
|
// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
// yaml_free(value_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a sequence node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_sequence(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, style yaml_sequence_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_item_t
|
||||||
|
// end *yaml_node_item_t
|
||||||
|
// top *yaml_node_item_t
|
||||||
|
// } items = { NULL, NULL, NULL }
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
|
||||||
|
// style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, items)
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Add a mapping node to a document.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_add_mapping(document *yaml_document_t,
|
||||||
|
// tag *yaml_char_t, style yaml_mapping_style_t)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
// mark yaml_mark_t = { 0, 0, 0 }
|
||||||
|
// tag_copy *yaml_char_t = NULL
|
||||||
|
// struct {
|
||||||
|
// start *yaml_node_pair_t
|
||||||
|
// end *yaml_node_pair_t
|
||||||
|
// top *yaml_node_pair_t
|
||||||
|
// } pairs = { NULL, NULL, NULL }
|
||||||
|
// node yaml_node_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document object is expected.
|
||||||
|
//
|
||||||
|
// if (!tag) {
|
||||||
|
// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
|
||||||
|
// tag_copy = yaml_strdup(tag)
|
||||||
|
// if (!tag_copy) goto error
|
||||||
|
//
|
||||||
|
// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
|
||||||
|
//
|
||||||
|
// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
|
||||||
|
// style, mark, mark)
|
||||||
|
// if (!PUSH(&context, document.nodes, node)) goto error
|
||||||
|
//
|
||||||
|
// return document.nodes.top - document.nodes.start
|
||||||
|
//
|
||||||
|
//error:
|
||||||
|
// STACK_DEL(&context, pairs)
|
||||||
|
// yaml_free(tag_copy)
|
||||||
|
//
|
||||||
|
// return 0
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Append an item to a sequence node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_append_sequence_item(document *yaml_document_t,
|
||||||
|
// sequence int, item int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document is required.
|
||||||
|
// assert(sequence > 0
|
||||||
|
// && document.nodes.start + sequence <= document.nodes.top)
|
||||||
|
// // Valid sequence id is required.
|
||||||
|
// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
|
||||||
|
// // A sequence node is required.
|
||||||
|
// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
|
||||||
|
// // Valid item id is required.
|
||||||
|
//
|
||||||
|
// if (!PUSH(&context,
|
||||||
|
// document.nodes.start[sequence-1].data.sequence.items, item))
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///*
|
||||||
|
// * Append a pair of a key and a value to a mapping node.
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//YAML_DECLARE(int)
|
||||||
|
//yaml_document_append_mapping_pair(document *yaml_document_t,
|
||||||
|
// mapping int, key int, value int)
|
||||||
|
//{
|
||||||
|
// struct {
|
||||||
|
// error yaml_error_type_t
|
||||||
|
// } context
|
||||||
|
//
|
||||||
|
// pair yaml_node_pair_t
|
||||||
|
//
|
||||||
|
// assert(document) // Non-NULL document is required.
|
||||||
|
// assert(mapping > 0
|
||||||
|
// && document.nodes.start + mapping <= document.nodes.top)
|
||||||
|
// // Valid mapping id is required.
|
||||||
|
// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
|
||||||
|
// // A mapping node is required.
|
||||||
|
// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
|
||||||
|
// // Valid key id is required.
|
||||||
|
// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
|
||||||
|
// // Valid value id is required.
|
||||||
|
//
|
||||||
|
// pair.key = key
|
||||||
|
// pair.value = value
|
||||||
|
//
|
||||||
|
// if (!PUSH(&context,
|
||||||
|
// document.nodes.start[mapping-1].data.mapping.pairs, pair))
|
||||||
|
// return 0
|
||||||
|
//
|
||||||
|
// return 1
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
683
Godeps/_workspace/src/gopkg.in/yaml.v2/decode.go
generated
vendored
Normal file
683
Godeps/_workspace/src/gopkg.in/yaml.v2/decode.go
generated
vendored
Normal file
|
@ -0,0 +1,683 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
documentNode = 1 << iota
|
||||||
|
mappingNode
|
||||||
|
sequenceNode
|
||||||
|
scalarNode
|
||||||
|
aliasNode
|
||||||
|
)
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
kind int
|
||||||
|
line, column int
|
||||||
|
tag string
|
||||||
|
value string
|
||||||
|
implicit bool
|
||||||
|
children []*node
|
||||||
|
anchors map[string]*node
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Parser, produces a node tree out of a libyaml event stream.
|
||||||
|
|
||||||
|
type parser struct {
|
||||||
|
parser yaml_parser_t
|
||||||
|
event yaml_event_t
|
||||||
|
doc *node
|
||||||
|
}
|
||||||
|
|
||||||
|
func newParser(b []byte) *parser {
|
||||||
|
p := parser{}
|
||||||
|
if !yaml_parser_initialize(&p.parser) {
|
||||||
|
panic("failed to initialize YAML emitter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) == 0 {
|
||||||
|
b = []byte{'\n'}
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml_parser_set_input_string(&p.parser, b)
|
||||||
|
|
||||||
|
p.skip()
|
||||||
|
if p.event.typ != yaml_STREAM_START_EVENT {
|
||||||
|
panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
|
||||||
|
}
|
||||||
|
p.skip()
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) destroy() {
|
||||||
|
if p.event.typ != yaml_NO_EVENT {
|
||||||
|
yaml_event_delete(&p.event)
|
||||||
|
}
|
||||||
|
yaml_parser_delete(&p.parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) skip() {
|
||||||
|
if p.event.typ != yaml_NO_EVENT {
|
||||||
|
if p.event.typ == yaml_STREAM_END_EVENT {
|
||||||
|
failf("attempted to go past the end of stream; corrupted value?")
|
||||||
|
}
|
||||||
|
yaml_event_delete(&p.event)
|
||||||
|
}
|
||||||
|
if !yaml_parser_parse(&p.parser, &p.event) {
|
||||||
|
p.fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) fail() {
|
||||||
|
var where string
|
||||||
|
var line int
|
||||||
|
if p.parser.problem_mark.line != 0 {
|
||||||
|
line = p.parser.problem_mark.line
|
||||||
|
} else if p.parser.context_mark.line != 0 {
|
||||||
|
line = p.parser.context_mark.line
|
||||||
|
}
|
||||||
|
if line != 0 {
|
||||||
|
where = "line " + strconv.Itoa(line) + ": "
|
||||||
|
}
|
||||||
|
var msg string
|
||||||
|
if len(p.parser.problem) > 0 {
|
||||||
|
msg = p.parser.problem
|
||||||
|
} else {
|
||||||
|
msg = "unknown problem parsing YAML content"
|
||||||
|
}
|
||||||
|
failf("%s%s", where, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) anchor(n *node, anchor []byte) {
|
||||||
|
if anchor != nil {
|
||||||
|
p.doc.anchors[string(anchor)] = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) parse() *node {
|
||||||
|
switch p.event.typ {
|
||||||
|
case yaml_SCALAR_EVENT:
|
||||||
|
return p.scalar()
|
||||||
|
case yaml_ALIAS_EVENT:
|
||||||
|
return p.alias()
|
||||||
|
case yaml_MAPPING_START_EVENT:
|
||||||
|
return p.mapping()
|
||||||
|
case yaml_SEQUENCE_START_EVENT:
|
||||||
|
return p.sequence()
|
||||||
|
case yaml_DOCUMENT_START_EVENT:
|
||||||
|
return p.document()
|
||||||
|
case yaml_STREAM_END_EVENT:
|
||||||
|
// Happens when attempting to decode an empty buffer.
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ)))
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) node(kind int) *node {
|
||||||
|
return &node{
|
||||||
|
kind: kind,
|
||||||
|
line: p.event.start_mark.line,
|
||||||
|
column: p.event.start_mark.column,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) document() *node {
|
||||||
|
n := p.node(documentNode)
|
||||||
|
n.anchors = make(map[string]*node)
|
||||||
|
p.doc = n
|
||||||
|
p.skip()
|
||||||
|
n.children = append(n.children, p.parse())
|
||||||
|
if p.event.typ != yaml_DOCUMENT_END_EVENT {
|
||||||
|
panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
|
||||||
|
}
|
||||||
|
p.skip()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) alias() *node {
|
||||||
|
n := p.node(aliasNode)
|
||||||
|
n.value = string(p.event.anchor)
|
||||||
|
p.skip()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) scalar() *node {
|
||||||
|
n := p.node(scalarNode)
|
||||||
|
n.value = string(p.event.value)
|
||||||
|
n.tag = string(p.event.tag)
|
||||||
|
n.implicit = p.event.implicit
|
||||||
|
p.anchor(n, p.event.anchor)
|
||||||
|
p.skip()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) sequence() *node {
|
||||||
|
n := p.node(sequenceNode)
|
||||||
|
p.anchor(n, p.event.anchor)
|
||||||
|
p.skip()
|
||||||
|
for p.event.typ != yaml_SEQUENCE_END_EVENT {
|
||||||
|
n.children = append(n.children, p.parse())
|
||||||
|
}
|
||||||
|
p.skip()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parser) mapping() *node {
|
||||||
|
n := p.node(mappingNode)
|
||||||
|
p.anchor(n, p.event.anchor)
|
||||||
|
p.skip()
|
||||||
|
for p.event.typ != yaml_MAPPING_END_EVENT {
|
||||||
|
n.children = append(n.children, p.parse(), p.parse())
|
||||||
|
}
|
||||||
|
p.skip()
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Decoder, unmarshals a node into a provided value.
|
||||||
|
|
||||||
|
type decoder struct {
|
||||||
|
doc *node
|
||||||
|
aliases map[string]bool
|
||||||
|
mapType reflect.Type
|
||||||
|
terrors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
mapItemType = reflect.TypeOf(MapItem{})
|
||||||
|
durationType = reflect.TypeOf(time.Duration(0))
|
||||||
|
defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
|
||||||
|
ifaceType = defaultMapType.Elem()
|
||||||
|
)
|
||||||
|
|
||||||
|
func newDecoder() *decoder {
|
||||||
|
d := &decoder{mapType: defaultMapType}
|
||||||
|
d.aliases = make(map[string]bool)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) terror(n *node, tag string, out reflect.Value) {
|
||||||
|
if n.tag != "" {
|
||||||
|
tag = n.tag
|
||||||
|
}
|
||||||
|
value := n.value
|
||||||
|
if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
|
||||||
|
if len(value) > 10 {
|
||||||
|
value = " `" + value[:7] + "...`"
|
||||||
|
} else {
|
||||||
|
value = " `" + value + "`"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
|
||||||
|
terrlen := len(d.terrors)
|
||||||
|
err := u.UnmarshalYAML(func(v interface{}) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
d.unmarshal(n, reflect.ValueOf(v))
|
||||||
|
if len(d.terrors) > terrlen {
|
||||||
|
issues := d.terrors[terrlen:]
|
||||||
|
d.terrors = d.terrors[:terrlen]
|
||||||
|
return &TypeError{issues}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if e, ok := err.(*TypeError); ok {
|
||||||
|
d.terrors = append(d.terrors, e.Errors...)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
|
||||||
|
// if a value is found to implement it.
|
||||||
|
// It returns the initialized and dereferenced out value, whether
|
||||||
|
// unmarshalling was already done by UnmarshalYAML, and if so whether
|
||||||
|
// its types unmarshalled appropriately.
|
||||||
|
//
|
||||||
|
// If n holds a null value, prepare returns before doing anything.
|
||||||
|
func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
|
||||||
|
if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "") {
|
||||||
|
return out, false, false
|
||||||
|
}
|
||||||
|
again := true
|
||||||
|
for again {
|
||||||
|
again = false
|
||||||
|
if out.Kind() == reflect.Ptr {
|
||||||
|
if out.IsNil() {
|
||||||
|
out.Set(reflect.New(out.Type().Elem()))
|
||||||
|
}
|
||||||
|
out = out.Elem()
|
||||||
|
again = true
|
||||||
|
}
|
||||||
|
if out.CanAddr() {
|
||||||
|
if u, ok := out.Addr().Interface().(Unmarshaler); ok {
|
||||||
|
good = d.callUnmarshaler(n, u)
|
||||||
|
return out, true, good
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
|
||||||
|
switch n.kind {
|
||||||
|
case documentNode:
|
||||||
|
return d.document(n, out)
|
||||||
|
case aliasNode:
|
||||||
|
return d.alias(n, out)
|
||||||
|
}
|
||||||
|
out, unmarshaled, good := d.prepare(n, out)
|
||||||
|
if unmarshaled {
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
switch n.kind {
|
||||||
|
case scalarNode:
|
||||||
|
good = d.scalar(n, out)
|
||||||
|
case mappingNode:
|
||||||
|
good = d.mapping(n, out)
|
||||||
|
case sequenceNode:
|
||||||
|
good = d.sequence(n, out)
|
||||||
|
default:
|
||||||
|
panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
|
||||||
|
}
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) document(n *node, out reflect.Value) (good bool) {
|
||||||
|
if len(n.children) == 1 {
|
||||||
|
d.doc = n
|
||||||
|
d.unmarshal(n.children[0], out)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
|
||||||
|
an, ok := d.doc.anchors[n.value]
|
||||||
|
if !ok {
|
||||||
|
failf("unknown anchor '%s' referenced", n.value)
|
||||||
|
}
|
||||||
|
if d.aliases[n.value] {
|
||||||
|
failf("anchor '%s' value contains itself", n.value)
|
||||||
|
}
|
||||||
|
d.aliases[n.value] = true
|
||||||
|
good = d.unmarshal(an, out)
|
||||||
|
delete(d.aliases, n.value)
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroValue reflect.Value
|
||||||
|
|
||||||
|
func resetMap(out reflect.Value) {
|
||||||
|
for _, k := range out.MapKeys() {
|
||||||
|
out.SetMapIndex(k, zeroValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
|
||||||
|
var tag string
|
||||||
|
var resolved interface{}
|
||||||
|
if n.tag == "" && !n.implicit {
|
||||||
|
tag = yaml_STR_TAG
|
||||||
|
resolved = n.value
|
||||||
|
} else {
|
||||||
|
tag, resolved = resolve(n.tag, n.value)
|
||||||
|
if tag == yaml_BINARY_TAG {
|
||||||
|
data, err := base64.StdEncoding.DecodeString(resolved.(string))
|
||||||
|
if err != nil {
|
||||||
|
failf("!!binary value contains invalid base64 data")
|
||||||
|
}
|
||||||
|
resolved = string(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if resolved == nil {
|
||||||
|
if out.Kind() == reflect.Map && !out.CanAddr() {
|
||||||
|
resetMap(out)
|
||||||
|
} else {
|
||||||
|
out.Set(reflect.Zero(out.Type()))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if s, ok := resolved.(string); ok && out.CanAddr() {
|
||||||
|
if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok {
|
||||||
|
err := u.UnmarshalText([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
if tag == yaml_BINARY_TAG {
|
||||||
|
out.SetString(resolved.(string))
|
||||||
|
good = true
|
||||||
|
} else if resolved != nil {
|
||||||
|
out.SetString(n.value)
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
if resolved == nil {
|
||||||
|
out.Set(reflect.Zero(out.Type()))
|
||||||
|
} else {
|
||||||
|
out.Set(reflect.ValueOf(resolved))
|
||||||
|
}
|
||||||
|
good = true
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case int:
|
||||||
|
if !out.OverflowInt(int64(resolved)) {
|
||||||
|
out.SetInt(int64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
if !out.OverflowInt(resolved) {
|
||||||
|
out.SetInt(resolved)
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case uint64:
|
||||||
|
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
|
||||||
|
out.SetInt(int64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
|
||||||
|
out.SetInt(int64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
if out.Type() == durationType {
|
||||||
|
d, err := time.ParseDuration(resolved)
|
||||||
|
if err == nil {
|
||||||
|
out.SetInt(int64(d))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case int:
|
||||||
|
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case uint64:
|
||||||
|
if !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
|
||||||
|
out.SetUint(uint64(resolved))
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Bool:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case bool:
|
||||||
|
out.SetBool(resolved)
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
switch resolved := resolved.(type) {
|
||||||
|
case int:
|
||||||
|
out.SetFloat(float64(resolved))
|
||||||
|
good = true
|
||||||
|
case int64:
|
||||||
|
out.SetFloat(float64(resolved))
|
||||||
|
good = true
|
||||||
|
case uint64:
|
||||||
|
out.SetFloat(float64(resolved))
|
||||||
|
good = true
|
||||||
|
case float64:
|
||||||
|
out.SetFloat(resolved)
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
case reflect.Ptr:
|
||||||
|
if out.Type().Elem() == reflect.TypeOf(resolved) {
|
||||||
|
// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
|
||||||
|
elem := reflect.New(out.Type().Elem())
|
||||||
|
elem.Elem().Set(reflect.ValueOf(resolved))
|
||||||
|
out.Set(elem)
|
||||||
|
good = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !good {
|
||||||
|
d.terror(n, tag, out)
|
||||||
|
}
|
||||||
|
return good
|
||||||
|
}
|
||||||
|
|
||||||
|
func settableValueOf(i interface{}) reflect.Value {
|
||||||
|
v := reflect.ValueOf(i)
|
||||||
|
sv := reflect.New(v.Type()).Elem()
|
||||||
|
sv.Set(v)
|
||||||
|
return sv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
|
||||||
|
l := len(n.children)
|
||||||
|
|
||||||
|
var iface reflect.Value
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
out.Set(reflect.MakeSlice(out.Type(), l, l))
|
||||||
|
case reflect.Interface:
|
||||||
|
// No type hints. Will have to use a generic sequence.
|
||||||
|
iface = out
|
||||||
|
out = settableValueOf(make([]interface{}, l))
|
||||||
|
default:
|
||||||
|
d.terror(n, yaml_SEQ_TAG, out)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
et := out.Type().Elem()
|
||||||
|
|
||||||
|
j := 0
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
e := reflect.New(et).Elem()
|
||||||
|
if ok := d.unmarshal(n.children[i], e); ok {
|
||||||
|
out.Index(j).Set(e)
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Set(out.Slice(0, j))
|
||||||
|
if iface.IsValid() {
|
||||||
|
iface.Set(out)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
|
||||||
|
switch out.Kind() {
|
||||||
|
case reflect.Struct:
|
||||||
|
return d.mappingStruct(n, out)
|
||||||
|
case reflect.Slice:
|
||||||
|
return d.mappingSlice(n, out)
|
||||||
|
case reflect.Map:
|
||||||
|
// okay
|
||||||
|
case reflect.Interface:
|
||||||
|
if d.mapType.Kind() == reflect.Map {
|
||||||
|
iface := out
|
||||||
|
out = reflect.MakeMap(d.mapType)
|
||||||
|
iface.Set(out)
|
||||||
|
} else {
|
||||||
|
slicev := reflect.New(d.mapType).Elem()
|
||||||
|
if !d.mappingSlice(n, slicev) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
out.Set(slicev)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
d.terror(n, yaml_MAP_TAG, out)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
outt := out.Type()
|
||||||
|
kt := outt.Key()
|
||||||
|
et := outt.Elem()
|
||||||
|
|
||||||
|
mapType := d.mapType
|
||||||
|
if outt.Key() == ifaceType && outt.Elem() == ifaceType {
|
||||||
|
d.mapType = outt
|
||||||
|
}
|
||||||
|
|
||||||
|
if out.IsNil() {
|
||||||
|
out.Set(reflect.MakeMap(outt))
|
||||||
|
}
|
||||||
|
l := len(n.children)
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
if isMerge(n.children[i]) {
|
||||||
|
d.merge(n.children[i+1], out)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k := reflect.New(kt).Elem()
|
||||||
|
if d.unmarshal(n.children[i], k) {
|
||||||
|
kkind := k.Kind()
|
||||||
|
if kkind == reflect.Interface {
|
||||||
|
kkind = k.Elem().Kind()
|
||||||
|
}
|
||||||
|
if kkind == reflect.Map || kkind == reflect.Slice {
|
||||||
|
failf("invalid map key: %#v", k.Interface())
|
||||||
|
}
|
||||||
|
e := reflect.New(et).Elem()
|
||||||
|
if d.unmarshal(n.children[i+1], e) {
|
||||||
|
out.SetMapIndex(k, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.mapType = mapType
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
|
||||||
|
outt := out.Type()
|
||||||
|
if outt.Elem() != mapItemType {
|
||||||
|
d.terror(n, yaml_MAP_TAG, out)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
mapType := d.mapType
|
||||||
|
d.mapType = outt
|
||||||
|
|
||||||
|
var slice []MapItem
|
||||||
|
var l = len(n.children)
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
if isMerge(n.children[i]) {
|
||||||
|
d.merge(n.children[i+1], out)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
item := MapItem{}
|
||||||
|
k := reflect.ValueOf(&item.Key).Elem()
|
||||||
|
if d.unmarshal(n.children[i], k) {
|
||||||
|
v := reflect.ValueOf(&item.Value).Elem()
|
||||||
|
if d.unmarshal(n.children[i+1], v) {
|
||||||
|
slice = append(slice, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Set(reflect.ValueOf(slice))
|
||||||
|
d.mapType = mapType
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
|
||||||
|
sinfo, err := getStructInfo(out.Type())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
name := settableValueOf("")
|
||||||
|
l := len(n.children)
|
||||||
|
|
||||||
|
var inlineMap reflect.Value
|
||||||
|
var elemType reflect.Type
|
||||||
|
if sinfo.InlineMap != -1 {
|
||||||
|
inlineMap = out.Field(sinfo.InlineMap)
|
||||||
|
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
|
||||||
|
elemType = inlineMap.Type().Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < l; i += 2 {
|
||||||
|
ni := n.children[i]
|
||||||
|
if isMerge(ni) {
|
||||||
|
d.merge(n.children[i+1], out)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !d.unmarshal(ni, name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info, ok := sinfo.FieldsMap[name.String()]; ok {
|
||||||
|
var field reflect.Value
|
||||||
|
if info.Inline == nil {
|
||||||
|
field = out.Field(info.Num)
|
||||||
|
} else {
|
||||||
|
field = out.FieldByIndex(info.Inline)
|
||||||
|
}
|
||||||
|
d.unmarshal(n.children[i+1], field)
|
||||||
|
} else if sinfo.InlineMap != -1 {
|
||||||
|
if inlineMap.IsNil() {
|
||||||
|
inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
|
||||||
|
}
|
||||||
|
value := reflect.New(elemType).Elem()
|
||||||
|
d.unmarshal(n.children[i+1], value)
|
||||||
|
inlineMap.SetMapIndex(name, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func failWantMap() {
|
||||||
|
failf("map merge requires map or sequence of maps as the value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) merge(n *node, out reflect.Value) {
|
||||||
|
switch n.kind {
|
||||||
|
case mappingNode:
|
||||||
|
d.unmarshal(n, out)
|
||||||
|
case aliasNode:
|
||||||
|
an, ok := d.doc.anchors[n.value]
|
||||||
|
if ok && an.kind != mappingNode {
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
d.unmarshal(n, out)
|
||||||
|
case sequenceNode:
|
||||||
|
// Step backwards as earlier nodes take precedence.
|
||||||
|
for i := len(n.children) - 1; i >= 0; i-- {
|
||||||
|
ni := n.children[i]
|
||||||
|
if ni.kind == aliasNode {
|
||||||
|
an, ok := d.doc.anchors[ni.value]
|
||||||
|
if ok && an.kind != mappingNode {
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
} else if ni.kind != mappingNode {
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
d.unmarshal(ni, out)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
failWantMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMerge(n *node) bool {
|
||||||
|
return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
|
||||||
|
}
|
1685
Godeps/_workspace/src/gopkg.in/yaml.v2/emitterc.go
generated
vendored
Normal file
1685
Godeps/_workspace/src/gopkg.in/yaml.v2/emitterc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
306
Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go
generated
vendored
Normal file
306
Godeps/_workspace/src/gopkg.in/yaml.v2/encode.go
generated
vendored
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type encoder struct {
|
||||||
|
emitter yaml_emitter_t
|
||||||
|
event yaml_event_t
|
||||||
|
out []byte
|
||||||
|
flow bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncoder() (e *encoder) {
|
||||||
|
e = &encoder{}
|
||||||
|
e.must(yaml_emitter_initialize(&e.emitter))
|
||||||
|
yaml_emitter_set_output_string(&e.emitter, &e.out)
|
||||||
|
yaml_emitter_set_unicode(&e.emitter, true)
|
||||||
|
e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING))
|
||||||
|
e.emit()
|
||||||
|
e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true))
|
||||||
|
e.emit()
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) finish() {
|
||||||
|
e.must(yaml_document_end_event_initialize(&e.event, true))
|
||||||
|
e.emit()
|
||||||
|
e.emitter.open_ended = false
|
||||||
|
e.must(yaml_stream_end_event_initialize(&e.event))
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) destroy() {
|
||||||
|
yaml_emitter_delete(&e.emitter)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) emit() {
|
||||||
|
// This will internally delete the e.event value.
|
||||||
|
if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT {
|
||||||
|
e.must(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) must(ok bool) {
|
||||||
|
if !ok {
|
||||||
|
msg := e.emitter.problem
|
||||||
|
if msg == "" {
|
||||||
|
msg = "unknown problem generating YAML content"
|
||||||
|
}
|
||||||
|
failf("%s", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||||
|
if !in.IsValid() {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iface := in.Interface()
|
||||||
|
if m, ok := iface.(Marshaler); ok {
|
||||||
|
v, err := m.MarshalYAML()
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
if v == nil {
|
||||||
|
e.nilv()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
in = reflect.ValueOf(v)
|
||||||
|
} else if m, ok := iface.(encoding.TextMarshaler); ok {
|
||||||
|
text, err := m.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
fail(err)
|
||||||
|
}
|
||||||
|
in = reflect.ValueOf(string(text))
|
||||||
|
}
|
||||||
|
switch in.Kind() {
|
||||||
|
case reflect.Interface:
|
||||||
|
if in.IsNil() {
|
||||||
|
e.nilv()
|
||||||
|
} else {
|
||||||
|
e.marshal(tag, in.Elem())
|
||||||
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
e.mapv(tag, in)
|
||||||
|
case reflect.Ptr:
|
||||||
|
if in.IsNil() {
|
||||||
|
e.nilv()
|
||||||
|
} else {
|
||||||
|
e.marshal(tag, in.Elem())
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
e.structv(tag, in)
|
||||||
|
case reflect.Slice:
|
||||||
|
if in.Type().Elem() == mapItemType {
|
||||||
|
e.itemsv(tag, in)
|
||||||
|
} else {
|
||||||
|
e.slicev(tag, in)
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
e.stringv(tag, in)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
if in.Type() == durationType {
|
||||||
|
e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
|
||||||
|
} else {
|
||||||
|
e.intv(tag, in)
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
e.uintv(tag, in)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
e.floatv(tag, in)
|
||||||
|
case reflect.Bool:
|
||||||
|
e.boolv(tag, in)
|
||||||
|
default:
|
||||||
|
panic("cannot marshal type: " + in.Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) mapv(tag string, in reflect.Value) {
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
keys := keyList(in.MapKeys())
|
||||||
|
sort.Sort(keys)
|
||||||
|
for _, k := range keys {
|
||||||
|
e.marshal("", k)
|
||||||
|
e.marshal("", in.MapIndex(k))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) itemsv(tag string, in reflect.Value) {
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
|
||||||
|
for _, item := range slice {
|
||||||
|
e.marshal("", reflect.ValueOf(item.Key))
|
||||||
|
e.marshal("", reflect.ValueOf(item.Value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) structv(tag string, in reflect.Value) {
|
||||||
|
sinfo, err := getStructInfo(in.Type())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
e.mappingv(tag, func() {
|
||||||
|
for _, info := range sinfo.FieldsList {
|
||||||
|
var value reflect.Value
|
||||||
|
if info.Inline == nil {
|
||||||
|
value = in.Field(info.Num)
|
||||||
|
} else {
|
||||||
|
value = in.FieldByIndex(info.Inline)
|
||||||
|
}
|
||||||
|
if info.OmitEmpty && isZero(value) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
e.marshal("", reflect.ValueOf(info.Key))
|
||||||
|
e.flow = info.Flow
|
||||||
|
e.marshal("", value)
|
||||||
|
}
|
||||||
|
if sinfo.InlineMap >= 0 {
|
||||||
|
m := in.Field(sinfo.InlineMap)
|
||||||
|
if m.Len() > 0 {
|
||||||
|
e.flow = false
|
||||||
|
keys := keyList(m.MapKeys())
|
||||||
|
sort.Sort(keys)
|
||||||
|
for _, k := range keys {
|
||||||
|
if _, found := sinfo.FieldsMap[k.String()]; found {
|
||||||
|
panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
|
||||||
|
}
|
||||||
|
e.marshal("", k)
|
||||||
|
e.flow = false
|
||||||
|
e.marshal("", m.MapIndex(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) mappingv(tag string, f func()) {
|
||||||
|
implicit := tag == ""
|
||||||
|
style := yaml_BLOCK_MAPPING_STYLE
|
||||||
|
if e.flow {
|
||||||
|
e.flow = false
|
||||||
|
style = yaml_FLOW_MAPPING_STYLE
|
||||||
|
}
|
||||||
|
e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||||
|
e.emit()
|
||||||
|
f()
|
||||||
|
e.must(yaml_mapping_end_event_initialize(&e.event))
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) slicev(tag string, in reflect.Value) {
|
||||||
|
implicit := tag == ""
|
||||||
|
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||||
|
if e.flow {
|
||||||
|
e.flow = false
|
||||||
|
style = yaml_FLOW_SEQUENCE_STYLE
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||||
|
e.emit()
|
||||||
|
n := in.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
e.marshal("", in.Index(i))
|
||||||
|
}
|
||||||
|
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||||
|
e.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
|
||||||
|
//
|
||||||
|
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
|
||||||
|
// in YAML 1.2 and by this package, but these should be marshalled quoted for
|
||||||
|
// the time being for compatibility with other parsers.
|
||||||
|
func isBase60Float(s string) (result bool) {
|
||||||
|
// Fast path.
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
c := s[0]
|
||||||
|
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Do the full match.
|
||||||
|
return base60float.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// From http://yaml.org/type/float.html, except the regular expression there
|
||||||
|
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
|
||||||
|
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
|
||||||
|
|
||||||
|
func (e *encoder) stringv(tag string, in reflect.Value) {
|
||||||
|
var style yaml_scalar_style_t
|
||||||
|
s := in.String()
|
||||||
|
rtag, rs := resolve("", s)
|
||||||
|
if rtag == yaml_BINARY_TAG {
|
||||||
|
if tag == "" || tag == yaml_STR_TAG {
|
||||||
|
tag = rtag
|
||||||
|
s = rs.(string)
|
||||||
|
} else if tag == yaml_BINARY_TAG {
|
||||||
|
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||||
|
} else {
|
||||||
|
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) {
|
||||||
|
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||||
|
} else if strings.Contains(s, "\n") {
|
||||||
|
style = yaml_LITERAL_SCALAR_STYLE
|
||||||
|
} else {
|
||||||
|
style = yaml_PLAIN_SCALAR_STYLE
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, style)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) boolv(tag string, in reflect.Value) {
|
||||||
|
var s string
|
||||||
|
if in.Bool() {
|
||||||
|
s = "true"
|
||||||
|
} else {
|
||||||
|
s = "false"
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) intv(tag string, in reflect.Value) {
|
||||||
|
s := strconv.FormatInt(in.Int(), 10)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) uintv(tag string, in reflect.Value) {
|
||||||
|
s := strconv.FormatUint(in.Uint(), 10)
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) floatv(tag string, in reflect.Value) {
|
||||||
|
// FIXME: Handle 64 bits here.
|
||||||
|
s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32)
|
||||||
|
switch s {
|
||||||
|
case "+Inf":
|
||||||
|
s = ".inf"
|
||||||
|
case "-Inf":
|
||||||
|
s = "-.inf"
|
||||||
|
case "NaN":
|
||||||
|
s = ".nan"
|
||||||
|
}
|
||||||
|
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) nilv() {
|
||||||
|
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
|
||||||
|
implicit := tag == ""
|
||||||
|
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
|
||||||
|
e.emit()
|
||||||
|
}
|
1096
Godeps/_workspace/src/gopkg.in/yaml.v2/parserc.go
generated
vendored
Normal file
1096
Godeps/_workspace/src/gopkg.in/yaml.v2/parserc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
391
Godeps/_workspace/src/gopkg.in/yaml.v2/readerc.go
generated
vendored
Normal file
391
Godeps/_workspace/src/gopkg.in/yaml.v2/readerc.go
generated
vendored
Normal file
|
@ -0,0 +1,391 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set the reader error and return 0.
|
||||||
|
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
|
||||||
|
parser.error = yaml_READER_ERROR
|
||||||
|
parser.problem = problem
|
||||||
|
parser.problem_offset = offset
|
||||||
|
parser.problem_value = value
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte order marks.
|
||||||
|
const (
|
||||||
|
bom_UTF8 = "\xef\xbb\xbf"
|
||||||
|
bom_UTF16LE = "\xff\xfe"
|
||||||
|
bom_UTF16BE = "\xfe\xff"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Determine the input stream encoding by checking the BOM symbol. If no BOM is
|
||||||
|
// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
|
||||||
|
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
|
||||||
|
// Ensure that we had enough bytes in the raw buffer.
|
||||||
|
for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
|
||||||
|
if !yaml_parser_update_raw_buffer(parser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the encoding.
|
||||||
|
buf := parser.raw_buffer
|
||||||
|
pos := parser.raw_buffer_pos
|
||||||
|
avail := len(buf) - pos
|
||||||
|
if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
|
||||||
|
parser.encoding = yaml_UTF16LE_ENCODING
|
||||||
|
parser.raw_buffer_pos += 2
|
||||||
|
parser.offset += 2
|
||||||
|
} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
|
||||||
|
parser.encoding = yaml_UTF16BE_ENCODING
|
||||||
|
parser.raw_buffer_pos += 2
|
||||||
|
parser.offset += 2
|
||||||
|
} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
|
||||||
|
parser.encoding = yaml_UTF8_ENCODING
|
||||||
|
parser.raw_buffer_pos += 3
|
||||||
|
parser.offset += 3
|
||||||
|
} else {
|
||||||
|
parser.encoding = yaml_UTF8_ENCODING
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the raw buffer.
|
||||||
|
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
|
||||||
|
size_read := 0
|
||||||
|
|
||||||
|
// Return if the raw buffer is full.
|
||||||
|
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return on EOF.
|
||||||
|
if parser.eof {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the remaining bytes in the raw buffer to the beginning.
|
||||||
|
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
|
||||||
|
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
|
||||||
|
}
|
||||||
|
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
|
||||||
|
parser.raw_buffer_pos = 0
|
||||||
|
|
||||||
|
// Call the read handler to fill the buffer.
|
||||||
|
size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
|
||||||
|
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
|
||||||
|
if err == io.EOF {
|
||||||
|
parser.eof = true
|
||||||
|
} else if err != nil {
|
||||||
|
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the buffer contains at least `length` characters.
|
||||||
|
// Return true on success, false on failure.
|
||||||
|
//
|
||||||
|
// The length is supposed to be significantly less that the buffer size.
|
||||||
|
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
|
||||||
|
if parser.read_handler == nil {
|
||||||
|
panic("read handler must be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the EOF flag is set and the raw buffer is empty, do nothing.
|
||||||
|
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return if the buffer contains enough characters.
|
||||||
|
if parser.unread >= length {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the input encoding if it is not known yet.
|
||||||
|
if parser.encoding == yaml_ANY_ENCODING {
|
||||||
|
if !yaml_parser_determine_encoding(parser) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the unread characters to the beginning of the buffer.
|
||||||
|
buffer_len := len(parser.buffer)
|
||||||
|
if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
|
||||||
|
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
|
||||||
|
buffer_len -= parser.buffer_pos
|
||||||
|
parser.buffer_pos = 0
|
||||||
|
} else if parser.buffer_pos == buffer_len {
|
||||||
|
buffer_len = 0
|
||||||
|
parser.buffer_pos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the whole buffer for writing, and cut it before returning.
|
||||||
|
parser.buffer = parser.buffer[:cap(parser.buffer)]
|
||||||
|
|
||||||
|
// Fill the buffer until it has enough characters.
|
||||||
|
first := true
|
||||||
|
for parser.unread < length {
|
||||||
|
|
||||||
|
// Fill the raw buffer if necessary.
|
||||||
|
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||||
|
if !yaml_parser_update_raw_buffer(parser) {
|
||||||
|
parser.buffer = parser.buffer[:buffer_len]
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = false
|
||||||
|
|
||||||
|
// Decode the raw buffer.
|
||||||
|
inner:
|
||||||
|
for parser.raw_buffer_pos != len(parser.raw_buffer) {
|
||||||
|
var value rune
|
||||||
|
var width int
|
||||||
|
|
||||||
|
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
|
||||||
|
|
||||||
|
// Decode the next character.
|
||||||
|
switch parser.encoding {
|
||||||
|
case yaml_UTF8_ENCODING:
|
||||||
|
// Decode a UTF-8 character. Check RFC 3629
|
||||||
|
// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
|
||||||
|
//
|
||||||
|
// The following table (taken from the RFC) is used for
|
||||||
|
// decoding.
|
||||||
|
//
|
||||||
|
// Char. number range | UTF-8 octet sequence
|
||||||
|
// (hexadecimal) | (binary)
|
||||||
|
// --------------------+------------------------------------
|
||||||
|
// 0000 0000-0000 007F | 0xxxxxxx
|
||||||
|
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||||
|
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
//
|
||||||
|
// Additionally, the characters in the range 0xD800-0xDFFF
|
||||||
|
// are prohibited as they are reserved for use with UTF-16
|
||||||
|
// surrogate pairs.
|
||||||
|
|
||||||
|
// Determine the length of the UTF-8 sequence.
|
||||||
|
octet := parser.raw_buffer[parser.raw_buffer_pos]
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
width = 1
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
width = 2
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
width = 3
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
width = 4
|
||||||
|
default:
|
||||||
|
// The leading octet is invalid.
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid leading UTF-8 octet",
|
||||||
|
parser.offset, int(octet))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the raw buffer contains an incomplete character.
|
||||||
|
if width > raw_unread {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-8 octet sequence",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the leading octet.
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
value = rune(octet & 0x7F)
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
value = rune(octet & 0x1F)
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
value = rune(octet & 0x0F)
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
value = rune(octet & 0x07)
|
||||||
|
default:
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check and decode the trailing octets.
|
||||||
|
for k := 1; k < width; k++ {
|
||||||
|
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
|
||||||
|
|
||||||
|
// Check if the octet is valid.
|
||||||
|
if (octet & 0xC0) != 0x80 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid trailing UTF-8 octet",
|
||||||
|
parser.offset+k, int(octet))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the octet.
|
||||||
|
value = (value << 6) + rune(octet&0x3F)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the length of the sequence against the value.
|
||||||
|
switch {
|
||||||
|
case width == 1:
|
||||||
|
case width == 2 && value >= 0x80:
|
||||||
|
case width == 3 && value >= 0x800:
|
||||||
|
case width == 4 && value >= 0x10000:
|
||||||
|
default:
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid length of a UTF-8 sequence",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the range of the value.
|
||||||
|
if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"invalid Unicode character",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
|
||||||
|
var low, high int
|
||||||
|
if parser.encoding == yaml_UTF16LE_ENCODING {
|
||||||
|
low, high = 0, 1
|
||||||
|
} else {
|
||||||
|
high, low = 1, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// The UTF-16 encoding is not as simple as one might
|
||||||
|
// naively think. Check RFC 2781
|
||||||
|
// (http://www.ietf.org/rfc/rfc2781.txt).
|
||||||
|
//
|
||||||
|
// Normally, two subsequent bytes describe a Unicode
|
||||||
|
// character. However a special technique (called a
|
||||||
|
// surrogate pair) is used for specifying character
|
||||||
|
// values larger than 0xFFFF.
|
||||||
|
//
|
||||||
|
// A surrogate pair consists of two pseudo-characters:
|
||||||
|
// high surrogate area (0xD800-0xDBFF)
|
||||||
|
// low surrogate area (0xDC00-0xDFFF)
|
||||||
|
//
|
||||||
|
// The following formulas are used for decoding
|
||||||
|
// and encoding characters using surrogate pairs:
|
||||||
|
//
|
||||||
|
// U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
|
||||||
|
// U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
|
||||||
|
// W1 = 110110yyyyyyyyyy
|
||||||
|
// W2 = 110111xxxxxxxxxx
|
||||||
|
//
|
||||||
|
// where U is the character value, W1 is the high surrogate
|
||||||
|
// area, W2 is the low surrogate area.
|
||||||
|
|
||||||
|
// Check for incomplete UTF-16 character.
|
||||||
|
if raw_unread < 2 {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-16 character",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the character.
|
||||||
|
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
|
||||||
|
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
|
||||||
|
|
||||||
|
// Check for unexpected low surrogate area.
|
||||||
|
if value&0xFC00 == 0xDC00 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"unexpected low surrogate area",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a high surrogate area.
|
||||||
|
if value&0xFC00 == 0xD800 {
|
||||||
|
width = 4
|
||||||
|
|
||||||
|
// Check for incomplete surrogate pair.
|
||||||
|
if raw_unread < 4 {
|
||||||
|
if parser.eof {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"incomplete UTF-16 surrogate pair",
|
||||||
|
parser.offset, -1)
|
||||||
|
}
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next character.
|
||||||
|
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
|
||||||
|
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
|
||||||
|
|
||||||
|
// Check for a low surrogate area.
|
||||||
|
if value2&0xFC00 != 0xDC00 {
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"expected low surrogate area",
|
||||||
|
parser.offset+2, int(value2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the value of the surrogate pair.
|
||||||
|
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
|
||||||
|
} else {
|
||||||
|
width = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("impossible")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is in the allowed range:
|
||||||
|
// #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
|
||||||
|
// | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
|
||||||
|
// | [#x10000-#x10FFFF] (32 bit)
|
||||||
|
switch {
|
||||||
|
case value == 0x09:
|
||||||
|
case value == 0x0A:
|
||||||
|
case value == 0x0D:
|
||||||
|
case value >= 0x20 && value <= 0x7E:
|
||||||
|
case value == 0x85:
|
||||||
|
case value >= 0xA0 && value <= 0xD7FF:
|
||||||
|
case value >= 0xE000 && value <= 0xFFFD:
|
||||||
|
case value >= 0x10000 && value <= 0x10FFFF:
|
||||||
|
default:
|
||||||
|
return yaml_parser_set_reader_error(parser,
|
||||||
|
"control characters are not allowed",
|
||||||
|
parser.offset, int(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the raw pointers.
|
||||||
|
parser.raw_buffer_pos += width
|
||||||
|
parser.offset += width
|
||||||
|
|
||||||
|
// Finally put the character into the buffer.
|
||||||
|
if value <= 0x7F {
|
||||||
|
// 0000 0000-0000 007F . 0xxxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(value)
|
||||||
|
} else if value <= 0x7FF {
|
||||||
|
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
|
||||||
|
} else if value <= 0xFFFF {
|
||||||
|
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
|
||||||
|
} else {
|
||||||
|
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
|
||||||
|
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||||
|
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
|
||||||
|
}
|
||||||
|
buffer_len += width
|
||||||
|
|
||||||
|
parser.unread++
|
||||||
|
}
|
||||||
|
|
||||||
|
// On EOF, put NUL into the buffer and return.
|
||||||
|
if parser.eof {
|
||||||
|
parser.buffer[buffer_len] = 0
|
||||||
|
buffer_len++
|
||||||
|
parser.unread++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parser.buffer = parser.buffer[:buffer_len]
|
||||||
|
return true
|
||||||
|
}
|
203
Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go
generated
vendored
Normal file
203
Godeps/_workspace/src/gopkg.in/yaml.v2/resolve.go
generated
vendored
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
type resolveMapItem struct {
|
||||||
|
value interface{}
|
||||||
|
tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolveTable = make([]byte, 256)
|
||||||
|
var resolveMap = make(map[string]resolveMapItem)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
t := resolveTable
|
||||||
|
t[int('+')] = 'S' // Sign
|
||||||
|
t[int('-')] = 'S'
|
||||||
|
for _, c := range "0123456789" {
|
||||||
|
t[int(c)] = 'D' // Digit
|
||||||
|
}
|
||||||
|
for _, c := range "yYnNtTfFoO~" {
|
||||||
|
t[int(c)] = 'M' // In map
|
||||||
|
}
|
||||||
|
t[int('.')] = '.' // Float (potentially in map)
|
||||||
|
|
||||||
|
var resolveMapList = []struct {
|
||||||
|
v interface{}
|
||||||
|
tag string
|
||||||
|
l []string
|
||||||
|
}{
|
||||||
|
{true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
|
||||||
|
{true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
|
||||||
|
{true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
|
||||||
|
{false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
|
||||||
|
{false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
|
||||||
|
{false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
|
||||||
|
{nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
|
||||||
|
{math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
|
||||||
|
{math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
|
||||||
|
{math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
|
||||||
|
{math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
|
||||||
|
{"<<", yaml_MERGE_TAG, []string{"<<"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
m := resolveMap
|
||||||
|
for _, item := range resolveMapList {
|
||||||
|
for _, s := range item.l {
|
||||||
|
m[s] = resolveMapItem{item.v, item.tag}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const longTagPrefix = "tag:yaml.org,2002:"
|
||||||
|
|
||||||
|
func shortTag(tag string) string {
|
||||||
|
// TODO This can easily be made faster and produce less garbage.
|
||||||
|
if strings.HasPrefix(tag, longTagPrefix) {
|
||||||
|
return "!!" + tag[len(longTagPrefix):]
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func longTag(tag string) string {
|
||||||
|
if strings.HasPrefix(tag, "!!") {
|
||||||
|
return longTagPrefix + tag[2:]
|
||||||
|
}
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolvableTag(tag string) bool {
|
||||||
|
switch tag {
|
||||||
|
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolve(tag string, in string) (rtag string, out interface{}) {
|
||||||
|
if !resolvableTag(tag) {
|
||||||
|
return tag, in
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
switch tag {
|
||||||
|
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Any data is accepted as a !!str or !!binary.
|
||||||
|
// Otherwise, the prefix is enough of a hint about what it might be.
|
||||||
|
hint := byte('N')
|
||||||
|
if in != "" {
|
||||||
|
hint = resolveTable[in[0]]
|
||||||
|
}
|
||||||
|
if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
|
||||||
|
// Handle things we can lookup in a map.
|
||||||
|
if item, ok := resolveMap[in]; ok {
|
||||||
|
return item.tag, item.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
|
||||||
|
// are purposefully unsupported here. They're still quoted on
|
||||||
|
// the way out for compatibility with other parser, though.
|
||||||
|
|
||||||
|
switch hint {
|
||||||
|
case 'M':
|
||||||
|
// We've already checked the map above.
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
// Not in the map, so maybe a normal float.
|
||||||
|
floatv, err := strconv.ParseFloat(in, 64)
|
||||||
|
if err == nil {
|
||||||
|
return yaml_FLOAT_TAG, floatv
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'D', 'S':
|
||||||
|
// Int, float, or timestamp.
|
||||||
|
plain := strings.Replace(in, "_", "", -1)
|
||||||
|
intv, err := strconv.ParseInt(plain, 0, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return yaml_INT_TAG, int(intv)
|
||||||
|
} else {
|
||||||
|
return yaml_INT_TAG, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain, 0, 64)
|
||||||
|
if err == nil {
|
||||||
|
return yaml_INT_TAG, uintv
|
||||||
|
}
|
||||||
|
floatv, err := strconv.ParseFloat(plain, 64)
|
||||||
|
if err == nil {
|
||||||
|
return yaml_FLOAT_TAG, floatv
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(plain, "0b") {
|
||||||
|
intv, err := strconv.ParseInt(plain[2:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return yaml_INT_TAG, int(intv)
|
||||||
|
} else {
|
||||||
|
return yaml_INT_TAG, intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
return yaml_INT_TAG, uintv
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(plain, "-0b") {
|
||||||
|
intv, err := strconv.ParseInt(plain[3:], 2, 64)
|
||||||
|
if err == nil {
|
||||||
|
if intv == int64(int(intv)) {
|
||||||
|
return yaml_INT_TAG, -int(intv)
|
||||||
|
} else {
|
||||||
|
return yaml_INT_TAG, -intv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// XXX Handle timestamps here.
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tag == yaml_BINARY_TAG {
|
||||||
|
return yaml_BINARY_TAG, in
|
||||||
|
}
|
||||||
|
if utf8.ValidString(in) {
|
||||||
|
return yaml_STR_TAG, in
|
||||||
|
}
|
||||||
|
return yaml_BINARY_TAG, encodeBase64(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
||||||
|
// as appropriate for the resulting length.
|
||||||
|
func encodeBase64(s string) string {
|
||||||
|
const lineLen = 70
|
||||||
|
encLen := base64.StdEncoding.EncodedLen(len(s))
|
||||||
|
lines := encLen/lineLen + 1
|
||||||
|
buf := make([]byte, encLen*2+lines)
|
||||||
|
in := buf[0:encLen]
|
||||||
|
out := buf[encLen:]
|
||||||
|
base64.StdEncoding.Encode(in, []byte(s))
|
||||||
|
k := 0
|
||||||
|
for i := 0; i < len(in); i += lineLen {
|
||||||
|
j := i + lineLen
|
||||||
|
if j > len(in) {
|
||||||
|
j = len(in)
|
||||||
|
}
|
||||||
|
k += copy(out[k:], in[i:j])
|
||||||
|
if lines > 1 {
|
||||||
|
out[k] = '\n'
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(out[:k])
|
||||||
|
}
|
2710
Godeps/_workspace/src/gopkg.in/yaml.v2/scannerc.go
generated
vendored
Normal file
2710
Godeps/_workspace/src/gopkg.in/yaml.v2/scannerc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
104
Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go
generated
vendored
Normal file
104
Godeps/_workspace/src/gopkg.in/yaml.v2/sorter.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
type keyList []reflect.Value
|
||||||
|
|
||||||
|
func (l keyList) Len() int { return len(l) }
|
||||||
|
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||||
|
func (l keyList) Less(i, j int) bool {
|
||||||
|
a := l[i]
|
||||||
|
b := l[j]
|
||||||
|
ak := a.Kind()
|
||||||
|
bk := b.Kind()
|
||||||
|
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
|
||||||
|
a = a.Elem()
|
||||||
|
ak = a.Kind()
|
||||||
|
}
|
||||||
|
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
|
||||||
|
b = b.Elem()
|
||||||
|
bk = b.Kind()
|
||||||
|
}
|
||||||
|
af, aok := keyFloat(a)
|
||||||
|
bf, bok := keyFloat(b)
|
||||||
|
if aok && bok {
|
||||||
|
if af != bf {
|
||||||
|
return af < bf
|
||||||
|
}
|
||||||
|
if ak != bk {
|
||||||
|
return ak < bk
|
||||||
|
}
|
||||||
|
return numLess(a, b)
|
||||||
|
}
|
||||||
|
if ak != reflect.String || bk != reflect.String {
|
||||||
|
return ak < bk
|
||||||
|
}
|
||||||
|
ar, br := []rune(a.String()), []rune(b.String())
|
||||||
|
for i := 0; i < len(ar) && i < len(br); i++ {
|
||||||
|
if ar[i] == br[i] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
al := unicode.IsLetter(ar[i])
|
||||||
|
bl := unicode.IsLetter(br[i])
|
||||||
|
if al && bl {
|
||||||
|
return ar[i] < br[i]
|
||||||
|
}
|
||||||
|
if al || bl {
|
||||||
|
return bl
|
||||||
|
}
|
||||||
|
var ai, bi int
|
||||||
|
var an, bn int64
|
||||||
|
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
|
||||||
|
an = an*10 + int64(ar[ai]-'0')
|
||||||
|
}
|
||||||
|
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
|
||||||
|
bn = bn*10 + int64(br[bi]-'0')
|
||||||
|
}
|
||||||
|
if an != bn {
|
||||||
|
return an < bn
|
||||||
|
}
|
||||||
|
if ai != bi {
|
||||||
|
return ai < bi
|
||||||
|
}
|
||||||
|
return ar[i] < br[i]
|
||||||
|
}
|
||||||
|
return len(ar) < len(br)
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyFloat returns a float value for v if it is a number/bool
|
||||||
|
// and whether it is a number/bool or not.
|
||||||
|
func keyFloat(v reflect.Value) (f float64, ok bool) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return float64(v.Int()), true
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float(), true
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return float64(v.Uint()), true
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// numLess returns whether a < b.
|
||||||
|
// a and b must necessarily have the same kind.
|
||||||
|
func numLess(a, b reflect.Value) bool {
|
||||||
|
switch a.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return a.Int() < b.Int()
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return a.Float() < b.Float()
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return a.Uint() < b.Uint()
|
||||||
|
case reflect.Bool:
|
||||||
|
return !a.Bool() && b.Bool()
|
||||||
|
}
|
||||||
|
panic("not a number")
|
||||||
|
}
|
89
Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go
generated
vendored
Normal file
89
Godeps/_workspace/src/gopkg.in/yaml.v2/writerc.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
// Set the writer error and return false.
|
||||||
|
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
||||||
|
emitter.error = yaml_WRITER_ERROR
|
||||||
|
emitter.problem = problem
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush the output buffer.
|
||||||
|
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
|
||||||
|
if emitter.write_handler == nil {
|
||||||
|
panic("write handler not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the buffer is empty.
|
||||||
|
if emitter.buffer_pos == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the output encoding is UTF-8, we don't need to recode the buffer.
|
||||||
|
if emitter.encoding == yaml_UTF8_ENCODING {
|
||||||
|
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
|
||||||
|
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||||
|
}
|
||||||
|
emitter.buffer_pos = 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recode the buffer into the raw buffer.
|
||||||
|
var low, high int
|
||||||
|
if emitter.encoding == yaml_UTF16LE_ENCODING {
|
||||||
|
low, high = 0, 1
|
||||||
|
} else {
|
||||||
|
high, low = 1, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := 0
|
||||||
|
for pos < emitter.buffer_pos {
|
||||||
|
// See the "reader.c" code for more details on UTF-8 encoding. Note
|
||||||
|
// that we assume that the buffer contains a valid UTF-8 sequence.
|
||||||
|
|
||||||
|
// Read the next UTF-8 character.
|
||||||
|
octet := emitter.buffer[pos]
|
||||||
|
|
||||||
|
var w int
|
||||||
|
var value rune
|
||||||
|
switch {
|
||||||
|
case octet&0x80 == 0x00:
|
||||||
|
w, value = 1, rune(octet&0x7F)
|
||||||
|
case octet&0xE0 == 0xC0:
|
||||||
|
w, value = 2, rune(octet&0x1F)
|
||||||
|
case octet&0xF0 == 0xE0:
|
||||||
|
w, value = 3, rune(octet&0x0F)
|
||||||
|
case octet&0xF8 == 0xF0:
|
||||||
|
w, value = 4, rune(octet&0x07)
|
||||||
|
}
|
||||||
|
for k := 1; k < w; k++ {
|
||||||
|
octet = emitter.buffer[pos+k]
|
||||||
|
value = (value << 6) + (rune(octet) & 0x3F)
|
||||||
|
}
|
||||||
|
pos += w
|
||||||
|
|
||||||
|
// Write the character.
|
||||||
|
if value < 0x10000 {
|
||||||
|
var b [2]byte
|
||||||
|
b[high] = byte(value >> 8)
|
||||||
|
b[low] = byte(value & 0xFF)
|
||||||
|
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1])
|
||||||
|
} else {
|
||||||
|
// Write the character using a surrogate pair (check "reader.c").
|
||||||
|
var b [4]byte
|
||||||
|
value -= 0x10000
|
||||||
|
b[high] = byte(0xD8 + (value >> 18))
|
||||||
|
b[low] = byte((value >> 10) & 0xFF)
|
||||||
|
b[high+2] = byte(0xDC + ((value >> 8) & 0xFF))
|
||||||
|
b[low+2] = byte(value & 0xFF)
|
||||||
|
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the raw buffer.
|
||||||
|
if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil {
|
||||||
|
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||||
|
}
|
||||||
|
emitter.buffer_pos = 0
|
||||||
|
emitter.raw_buffer = emitter.raw_buffer[:0]
|
||||||
|
return true
|
||||||
|
}
|
346
Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go
generated
vendored
Normal file
346
Godeps/_workspace/src/gopkg.in/yaml.v2/yaml.go
generated
vendored
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
// Package yaml implements YAML support for the Go language.
|
||||||
|
//
|
||||||
|
// Source code and other details for the project are available at GitHub:
|
||||||
|
//
|
||||||
|
// https://github.com/go-yaml/yaml
|
||||||
|
//
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MapSlice encodes and decodes as a YAML map.
|
||||||
|
// The order of keys is preserved when encoding and decoding.
|
||||||
|
type MapSlice []MapItem
|
||||||
|
|
||||||
|
// MapItem is an item in a MapSlice.
|
||||||
|
type MapItem struct {
|
||||||
|
Key, Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Unmarshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
|
||||||
|
// method receives a function that may be called to unmarshal the original
|
||||||
|
// YAML value into a field or variable. It is safe to call the unmarshal
|
||||||
|
// function parameter more than once if necessary.
|
||||||
|
type Unmarshaler interface {
|
||||||
|
UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Marshaler interface may be implemented by types to customize their
|
||||||
|
// behavior when being marshaled into a YAML document. The returned value
|
||||||
|
// is marshaled in place of the original value implementing Marshaler.
|
||||||
|
//
|
||||||
|
// If an error is returned by MarshalYAML, the marshaling procedure stops
|
||||||
|
// and returns with the provided error.
|
||||||
|
type Marshaler interface {
|
||||||
|
MarshalYAML() (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal decodes the first document found within the in byte slice
|
||||||
|
// and assigns decoded values into the out value.
|
||||||
|
//
|
||||||
|
// Maps and pointers (to a struct, string, int, etc) are accepted as out
|
||||||
|
// values. If an internal pointer within a struct is not initialized,
|
||||||
|
// the yaml package will initialize it if necessary for unmarshalling
|
||||||
|
// the provided data. The out parameter must not be nil.
|
||||||
|
//
|
||||||
|
// The type of the decoded values should be compatible with the respective
|
||||||
|
// values in out. If one or more values cannot be decoded due to a type
|
||||||
|
// mismatches, decoding continues partially until the end of the YAML
|
||||||
|
// content, and a *yaml.TypeError is returned with details for all
|
||||||
|
// missed values.
|
||||||
|
//
|
||||||
|
// Struct fields are only unmarshalled if they are exported (have an
|
||||||
|
// upper case first letter), and are unmarshalled using the field name
|
||||||
|
// lowercased as the default key. Custom keys may be defined via the
|
||||||
|
// "yaml" name in the field tag: the content preceding the first comma
|
||||||
|
// is used as the key, and the following comma-separated options are
|
||||||
|
// used to tweak the marshalling process (see Marshal).
|
||||||
|
// Conflicting names result in a runtime error.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// type T struct {
|
||||||
|
// F int `yaml:"a,omitempty"`
|
||||||
|
// B int
|
||||||
|
// }
|
||||||
|
// var t T
|
||||||
|
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||||
|
//
|
||||||
|
// See the documentation of Marshal for the format of tags and a list of
|
||||||
|
// supported tag options.
|
||||||
|
//
|
||||||
|
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
d := newDecoder()
|
||||||
|
p := newParser(in)
|
||||||
|
defer p.destroy()
|
||||||
|
node := p.parse()
|
||||||
|
if node != nil {
|
||||||
|
v := reflect.ValueOf(out)
|
||||||
|
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
d.unmarshal(node, v)
|
||||||
|
}
|
||||||
|
if len(d.terrors) > 0 {
|
||||||
|
return &TypeError{d.terrors}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal serializes the value provided into a YAML document. The structure
|
||||||
|
// of the generated document will reflect the structure of the value itself.
|
||||||
|
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||||
|
//
|
||||||
|
// Struct fields are only unmarshalled if they are exported (have an upper case
|
||||||
|
// first letter), and are unmarshalled using the field name lowercased as the
|
||||||
|
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||||
|
// tag: the content preceding the first comma is used as the key, and the
|
||||||
|
// following comma-separated options are used to tweak the marshalling process.
|
||||||
|
// Conflicting names result in a runtime error.
|
||||||
|
//
|
||||||
|
// The field tag format accepted is:
|
||||||
|
//
|
||||||
|
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||||
|
//
|
||||||
|
// The following flags are currently supported:
|
||||||
|
//
|
||||||
|
// omitempty Only include the field if it's not set to the zero
|
||||||
|
// value for the type or to empty slices or maps.
|
||||||
|
// Does not apply to zero valued structs.
|
||||||
|
//
|
||||||
|
// flow Marshal using a flow style (useful for structs,
|
||||||
|
// sequences and maps).
|
||||||
|
//
|
||||||
|
// inline Inline the field, which must be a struct or a map,
|
||||||
|
// causing all of its fields or keys to be processed as if
|
||||||
|
// they were part of the outer struct. For maps, keys must
|
||||||
|
// not conflict with the yaml keys of other struct fields.
|
||||||
|
//
|
||||||
|
// In addition, if the key is "-", the field is ignored.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// type T struct {
|
||||||
|
// F int "a,omitempty"
|
||||||
|
// B int
|
||||||
|
// }
|
||||||
|
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||||
|
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||||
|
//
|
||||||
|
func Marshal(in interface{}) (out []byte, err error) {
|
||||||
|
defer handleErr(&err)
|
||||||
|
e := newEncoder()
|
||||||
|
defer e.destroy()
|
||||||
|
e.marshal("", reflect.ValueOf(in))
|
||||||
|
e.finish()
|
||||||
|
out = e.out
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleErr(err *error) {
|
||||||
|
if v := recover(); v != nil {
|
||||||
|
if e, ok := v.(yamlError); ok {
|
||||||
|
*err = e.err
|
||||||
|
} else {
|
||||||
|
panic(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type yamlError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func fail(err error) {
|
||||||
|
panic(yamlError{err})
|
||||||
|
}
|
||||||
|
|
||||||
|
func failf(format string, args ...interface{}) {
|
||||||
|
panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// A TypeError is returned by Unmarshal when one or more fields in
|
||||||
|
// the YAML document cannot be properly decoded into the requested
|
||||||
|
// types. When this error is returned, the value is still
|
||||||
|
// unmarshaled partially.
|
||||||
|
type TypeError struct {
|
||||||
|
Errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *TypeError) Error() string {
|
||||||
|
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Maintain a mapping of keys to structure field indexes
|
||||||
|
|
||||||
|
// The code in this section was copied from mgo/bson.
|
||||||
|
|
||||||
|
// structInfo holds details for the serialization of fields of
|
||||||
|
// a given struct.
|
||||||
|
type structInfo struct {
|
||||||
|
FieldsMap map[string]fieldInfo
|
||||||
|
FieldsList []fieldInfo
|
||||||
|
|
||||||
|
// InlineMap is the number of the field in the struct that
|
||||||
|
// contains an ,inline map, or -1 if there's none.
|
||||||
|
InlineMap int
|
||||||
|
}
|
||||||
|
|
||||||
|
type fieldInfo struct {
|
||||||
|
Key string
|
||||||
|
Num int
|
||||||
|
OmitEmpty bool
|
||||||
|
Flow bool
|
||||||
|
|
||||||
|
// Inline holds the field index if the field is part of an inlined struct.
|
||||||
|
Inline []int
|
||||||
|
}
|
||||||
|
|
||||||
|
var structMap = make(map[reflect.Type]*structInfo)
|
||||||
|
var fieldMapMutex sync.RWMutex
|
||||||
|
|
||||||
|
func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||||
|
fieldMapMutex.RLock()
|
||||||
|
sinfo, found := structMap[st]
|
||||||
|
fieldMapMutex.RUnlock()
|
||||||
|
if found {
|
||||||
|
return sinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
n := st.NumField()
|
||||||
|
fieldsMap := make(map[string]fieldInfo)
|
||||||
|
fieldsList := make([]fieldInfo, 0, n)
|
||||||
|
inlineMap := -1
|
||||||
|
for i := 0; i != n; i++ {
|
||||||
|
field := st.Field(i)
|
||||||
|
if field.PkgPath != "" {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
|
||||||
|
info := fieldInfo{Num: i}
|
||||||
|
|
||||||
|
tag := field.Tag.Get("yaml")
|
||||||
|
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
|
||||||
|
tag = string(field.Tag)
|
||||||
|
}
|
||||||
|
if tag == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
inline := false
|
||||||
|
fields := strings.Split(tag, ",")
|
||||||
|
if len(fields) > 1 {
|
||||||
|
for _, flag := range fields[1:] {
|
||||||
|
switch flag {
|
||||||
|
case "omitempty":
|
||||||
|
info.OmitEmpty = true
|
||||||
|
case "flow":
|
||||||
|
info.Flow = true
|
||||||
|
case "inline":
|
||||||
|
inline = true
|
||||||
|
default:
|
||||||
|
return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tag = fields[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if inline {
|
||||||
|
switch field.Type.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
if inlineMap >= 0 {
|
||||||
|
return nil, errors.New("Multiple ,inline maps in struct " + st.String())
|
||||||
|
}
|
||||||
|
if field.Type.Key() != reflect.TypeOf("") {
|
||||||
|
return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
|
||||||
|
}
|
||||||
|
inlineMap = info.Num
|
||||||
|
case reflect.Struct:
|
||||||
|
sinfo, err := getStructInfo(field.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, finfo := range sinfo.FieldsList {
|
||||||
|
if _, found := fieldsMap[finfo.Key]; found {
|
||||||
|
msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
if finfo.Inline == nil {
|
||||||
|
finfo.Inline = []int{i, finfo.Num}
|
||||||
|
} else {
|
||||||
|
finfo.Inline = append([]int{i}, finfo.Inline...)
|
||||||
|
}
|
||||||
|
fieldsMap[finfo.Key] = finfo
|
||||||
|
fieldsList = append(fieldsList, finfo)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
//return nil, errors.New("Option ,inline needs a struct value or map field")
|
||||||
|
return nil, errors.New("Option ,inline needs a struct value field")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != "" {
|
||||||
|
info.Key = tag
|
||||||
|
} else {
|
||||||
|
info.Key = strings.ToLower(field.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, found = fieldsMap[info.Key]; found {
|
||||||
|
msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
|
||||||
|
return nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldsList = append(fieldsList, info)
|
||||||
|
fieldsMap[info.Key] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
sinfo = &structInfo{fieldsMap, fieldsList, inlineMap}
|
||||||
|
|
||||||
|
fieldMapMutex.Lock()
|
||||||
|
structMap[st] = sinfo
|
||||||
|
fieldMapMutex.Unlock()
|
||||||
|
return sinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isZero(v reflect.Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
return len(v.String()) == 0
|
||||||
|
case reflect.Interface, reflect.Ptr:
|
||||||
|
return v.IsNil()
|
||||||
|
case reflect.Slice:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Map:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v.Int() == 0
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float() == 0
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v.Uint() == 0
|
||||||
|
case reflect.Bool:
|
||||||
|
return !v.Bool()
|
||||||
|
case reflect.Struct:
|
||||||
|
vt := v.Type()
|
||||||
|
for i := v.NumField() - 1; i >= 0; i-- {
|
||||||
|
if vt.Field(i).PkgPath != "" {
|
||||||
|
continue // Private field
|
||||||
|
}
|
||||||
|
if !isZero(v.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
716
Godeps/_workspace/src/gopkg.in/yaml.v2/yamlh.go
generated
vendored
Normal file
716
Godeps/_workspace/src/gopkg.in/yaml.v2/yamlh.go
generated
vendored
Normal file
|
@ -0,0 +1,716 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The version directive data.
|
||||||
|
type yaml_version_directive_t struct {
|
||||||
|
major int8 // The major version number.
|
||||||
|
minor int8 // The minor version number.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The tag directive data.
|
||||||
|
type yaml_tag_directive_t struct {
|
||||||
|
handle []byte // The tag handle.
|
||||||
|
prefix []byte // The tag prefix.
|
||||||
|
}
|
||||||
|
|
||||||
|
type yaml_encoding_t int
|
||||||
|
|
||||||
|
// The stream encoding.
|
||||||
|
const (
|
||||||
|
// Let the parser choose the encoding.
|
||||||
|
yaml_ANY_ENCODING yaml_encoding_t = iota
|
||||||
|
|
||||||
|
yaml_UTF8_ENCODING // The default UTF-8 encoding.
|
||||||
|
yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
|
||||||
|
yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_break_t int
|
||||||
|
|
||||||
|
// Line break types.
|
||||||
|
const (
|
||||||
|
// Let the parser choose the break type.
|
||||||
|
yaml_ANY_BREAK yaml_break_t = iota
|
||||||
|
|
||||||
|
yaml_CR_BREAK // Use CR for line breaks (Mac style).
|
||||||
|
yaml_LN_BREAK // Use LN for line breaks (Unix style).
|
||||||
|
yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_error_type_t int
|
||||||
|
|
||||||
|
// Many bad things could happen with the parser and emitter.
|
||||||
|
const (
|
||||||
|
// No error is produced.
|
||||||
|
yaml_NO_ERROR yaml_error_type_t = iota
|
||||||
|
|
||||||
|
yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
|
||||||
|
yaml_READER_ERROR // Cannot read or decode the input stream.
|
||||||
|
yaml_SCANNER_ERROR // Cannot scan the input stream.
|
||||||
|
yaml_PARSER_ERROR // Cannot parse the input stream.
|
||||||
|
yaml_COMPOSER_ERROR // Cannot compose a YAML document.
|
||||||
|
yaml_WRITER_ERROR // Cannot write to the output stream.
|
||||||
|
yaml_EMITTER_ERROR // Cannot emit a YAML stream.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The pointer position.
|
||||||
|
type yaml_mark_t struct {
|
||||||
|
index int // The position index.
|
||||||
|
line int // The position line.
|
||||||
|
column int // The position column.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node Styles
|
||||||
|
|
||||||
|
type yaml_style_t int8
|
||||||
|
|
||||||
|
type yaml_scalar_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Scalar styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
|
||||||
|
|
||||||
|
yaml_PLAIN_SCALAR_STYLE // The plain scalar style.
|
||||||
|
yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
|
||||||
|
yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
|
||||||
|
yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
|
||||||
|
yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_sequence_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Sequence styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
|
||||||
|
|
||||||
|
yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
|
||||||
|
yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_mapping_style_t yaml_style_t
|
||||||
|
|
||||||
|
// Mapping styles.
|
||||||
|
const (
|
||||||
|
// Let the emitter choose the style.
|
||||||
|
yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
|
||||||
|
|
||||||
|
yaml_BLOCK_MAPPING_STYLE // The block mapping style.
|
||||||
|
yaml_FLOW_MAPPING_STYLE // The flow mapping style.
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tokens
|
||||||
|
|
||||||
|
type yaml_token_type_t int
|
||||||
|
|
||||||
|
// Token types.
|
||||||
|
const (
|
||||||
|
// An empty token.
|
||||||
|
yaml_NO_TOKEN yaml_token_type_t = iota
|
||||||
|
|
||||||
|
yaml_STREAM_START_TOKEN // A STREAM-START token.
|
||||||
|
yaml_STREAM_END_TOKEN // A STREAM-END token.
|
||||||
|
|
||||||
|
yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
|
||||||
|
yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
|
||||||
|
yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
|
||||||
|
yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
|
||||||
|
|
||||||
|
yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
|
||||||
|
yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
|
||||||
|
yaml_BLOCK_END_TOKEN // A BLOCK-END token.
|
||||||
|
|
||||||
|
yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
|
||||||
|
yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
|
||||||
|
yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
|
||||||
|
yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
|
||||||
|
|
||||||
|
yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
|
||||||
|
yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
|
||||||
|
yaml_KEY_TOKEN // A KEY token.
|
||||||
|
yaml_VALUE_TOKEN // A VALUE token.
|
||||||
|
|
||||||
|
yaml_ALIAS_TOKEN // An ALIAS token.
|
||||||
|
yaml_ANCHOR_TOKEN // An ANCHOR token.
|
||||||
|
yaml_TAG_TOKEN // A TAG token.
|
||||||
|
yaml_SCALAR_TOKEN // A SCALAR token.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (tt yaml_token_type_t) String() string {
|
||||||
|
switch tt {
|
||||||
|
case yaml_NO_TOKEN:
|
||||||
|
return "yaml_NO_TOKEN"
|
||||||
|
case yaml_STREAM_START_TOKEN:
|
||||||
|
return "yaml_STREAM_START_TOKEN"
|
||||||
|
case yaml_STREAM_END_TOKEN:
|
||||||
|
return "yaml_STREAM_END_TOKEN"
|
||||||
|
case yaml_VERSION_DIRECTIVE_TOKEN:
|
||||||
|
return "yaml_VERSION_DIRECTIVE_TOKEN"
|
||||||
|
case yaml_TAG_DIRECTIVE_TOKEN:
|
||||||
|
return "yaml_TAG_DIRECTIVE_TOKEN"
|
||||||
|
case yaml_DOCUMENT_START_TOKEN:
|
||||||
|
return "yaml_DOCUMENT_START_TOKEN"
|
||||||
|
case yaml_DOCUMENT_END_TOKEN:
|
||||||
|
return "yaml_DOCUMENT_END_TOKEN"
|
||||||
|
case yaml_BLOCK_SEQUENCE_START_TOKEN:
|
||||||
|
return "yaml_BLOCK_SEQUENCE_START_TOKEN"
|
||||||
|
case yaml_BLOCK_MAPPING_START_TOKEN:
|
||||||
|
return "yaml_BLOCK_MAPPING_START_TOKEN"
|
||||||
|
case yaml_BLOCK_END_TOKEN:
|
||||||
|
return "yaml_BLOCK_END_TOKEN"
|
||||||
|
case yaml_FLOW_SEQUENCE_START_TOKEN:
|
||||||
|
return "yaml_FLOW_SEQUENCE_START_TOKEN"
|
||||||
|
case yaml_FLOW_SEQUENCE_END_TOKEN:
|
||||||
|
return "yaml_FLOW_SEQUENCE_END_TOKEN"
|
||||||
|
case yaml_FLOW_MAPPING_START_TOKEN:
|
||||||
|
return "yaml_FLOW_MAPPING_START_TOKEN"
|
||||||
|
case yaml_FLOW_MAPPING_END_TOKEN:
|
||||||
|
return "yaml_FLOW_MAPPING_END_TOKEN"
|
||||||
|
case yaml_BLOCK_ENTRY_TOKEN:
|
||||||
|
return "yaml_BLOCK_ENTRY_TOKEN"
|
||||||
|
case yaml_FLOW_ENTRY_TOKEN:
|
||||||
|
return "yaml_FLOW_ENTRY_TOKEN"
|
||||||
|
case yaml_KEY_TOKEN:
|
||||||
|
return "yaml_KEY_TOKEN"
|
||||||
|
case yaml_VALUE_TOKEN:
|
||||||
|
return "yaml_VALUE_TOKEN"
|
||||||
|
case yaml_ALIAS_TOKEN:
|
||||||
|
return "yaml_ALIAS_TOKEN"
|
||||||
|
case yaml_ANCHOR_TOKEN:
|
||||||
|
return "yaml_ANCHOR_TOKEN"
|
||||||
|
case yaml_TAG_TOKEN:
|
||||||
|
return "yaml_TAG_TOKEN"
|
||||||
|
case yaml_SCALAR_TOKEN:
|
||||||
|
return "yaml_SCALAR_TOKEN"
|
||||||
|
}
|
||||||
|
return "<unknown token>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// The token structure.
|
||||||
|
type yaml_token_t struct {
|
||||||
|
// The token type.
|
||||||
|
typ yaml_token_type_t
|
||||||
|
|
||||||
|
// The start/end of the token.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The stream encoding (for yaml_STREAM_START_TOKEN).
|
||||||
|
encoding yaml_encoding_t
|
||||||
|
|
||||||
|
// The alias/anchor/scalar value or tag/tag directive handle
|
||||||
|
// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
|
||||||
|
value []byte
|
||||||
|
|
||||||
|
// The tag suffix (for yaml_TAG_TOKEN).
|
||||||
|
suffix []byte
|
||||||
|
|
||||||
|
// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
|
||||||
|
prefix []byte
|
||||||
|
|
||||||
|
// The scalar style (for yaml_SCALAR_TOKEN).
|
||||||
|
style yaml_scalar_style_t
|
||||||
|
|
||||||
|
// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
|
||||||
|
major, minor int8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Events
|
||||||
|
|
||||||
|
type yaml_event_type_t int8
|
||||||
|
|
||||||
|
// Event types.
|
||||||
|
const (
|
||||||
|
// An empty event.
|
||||||
|
yaml_NO_EVENT yaml_event_type_t = iota
|
||||||
|
|
||||||
|
yaml_STREAM_START_EVENT // A STREAM-START event.
|
||||||
|
yaml_STREAM_END_EVENT // A STREAM-END event.
|
||||||
|
yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
|
||||||
|
yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
|
||||||
|
yaml_ALIAS_EVENT // An ALIAS event.
|
||||||
|
yaml_SCALAR_EVENT // A SCALAR event.
|
||||||
|
yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
|
||||||
|
yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
|
||||||
|
yaml_MAPPING_START_EVENT // A MAPPING-START event.
|
||||||
|
yaml_MAPPING_END_EVENT // A MAPPING-END event.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The event structure.
|
||||||
|
type yaml_event_t struct {
|
||||||
|
|
||||||
|
// The event type.
|
||||||
|
typ yaml_event_type_t
|
||||||
|
|
||||||
|
// The start and end of the event.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The document encoding (for yaml_STREAM_START_EVENT).
|
||||||
|
encoding yaml_encoding_t
|
||||||
|
|
||||||
|
// The version directive (for yaml_DOCUMENT_START_EVENT).
|
||||||
|
version_directive *yaml_version_directive_t
|
||||||
|
|
||||||
|
// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
|
||||||
|
tag_directives []yaml_tag_directive_t
|
||||||
|
|
||||||
|
// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
|
||||||
|
anchor []byte
|
||||||
|
|
||||||
|
// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||||
|
tag []byte
|
||||||
|
|
||||||
|
// The scalar value (for yaml_SCALAR_EVENT).
|
||||||
|
value []byte
|
||||||
|
|
||||||
|
// Is the document start/end indicator implicit, or the tag optional?
|
||||||
|
// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
|
||||||
|
implicit bool
|
||||||
|
|
||||||
|
// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
|
||||||
|
quoted_implicit bool
|
||||||
|
|
||||||
|
// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
|
||||||
|
style yaml_style_t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
|
||||||
|
func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
|
||||||
|
func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
|
||||||
|
const (
|
||||||
|
yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
|
||||||
|
yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
|
||||||
|
yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
|
||||||
|
yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
|
||||||
|
yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
|
||||||
|
yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
|
||||||
|
|
||||||
|
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
|
||||||
|
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
|
||||||
|
|
||||||
|
// Not in original libyaml.
|
||||||
|
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
|
||||||
|
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
|
||||||
|
|
||||||
|
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
|
||||||
|
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
|
||||||
|
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
|
||||||
|
)
|
||||||
|
|
||||||
|
type yaml_node_type_t int
|
||||||
|
|
||||||
|
// Node types.
|
||||||
|
const (
|
||||||
|
// An empty node.
|
||||||
|
yaml_NO_NODE yaml_node_type_t = iota
|
||||||
|
|
||||||
|
yaml_SCALAR_NODE // A scalar node.
|
||||||
|
yaml_SEQUENCE_NODE // A sequence node.
|
||||||
|
yaml_MAPPING_NODE // A mapping node.
|
||||||
|
)
|
||||||
|
|
||||||
|
// An element of a sequence node.
|
||||||
|
type yaml_node_item_t int
|
||||||
|
|
||||||
|
// An element of a mapping node.
|
||||||
|
type yaml_node_pair_t struct {
|
||||||
|
key int // The key of the element.
|
||||||
|
value int // The value of the element.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The node structure.
|
||||||
|
type yaml_node_t struct {
|
||||||
|
typ yaml_node_type_t // The node type.
|
||||||
|
tag []byte // The node tag.
|
||||||
|
|
||||||
|
// The node data.
|
||||||
|
|
||||||
|
// The scalar parameters (for yaml_SCALAR_NODE).
|
||||||
|
scalar struct {
|
||||||
|
value []byte // The scalar value.
|
||||||
|
length int // The length of the scalar value.
|
||||||
|
style yaml_scalar_style_t // The scalar style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sequence parameters (for YAML_SEQUENCE_NODE).
|
||||||
|
sequence struct {
|
||||||
|
items_data []yaml_node_item_t // The stack of sequence items.
|
||||||
|
style yaml_sequence_style_t // The sequence style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mapping parameters (for yaml_MAPPING_NODE).
|
||||||
|
mapping struct {
|
||||||
|
pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
|
||||||
|
pairs_start *yaml_node_pair_t // The beginning of the stack.
|
||||||
|
pairs_end *yaml_node_pair_t // The end of the stack.
|
||||||
|
pairs_top *yaml_node_pair_t // The top of the stack.
|
||||||
|
style yaml_mapping_style_t // The mapping style.
|
||||||
|
}
|
||||||
|
|
||||||
|
start_mark yaml_mark_t // The beginning of the node.
|
||||||
|
end_mark yaml_mark_t // The end of the node.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// The document structure.
|
||||||
|
type yaml_document_t struct {
|
||||||
|
|
||||||
|
// The document nodes.
|
||||||
|
nodes []yaml_node_t
|
||||||
|
|
||||||
|
// The version directive.
|
||||||
|
version_directive *yaml_version_directive_t
|
||||||
|
|
||||||
|
// The list of tag directives.
|
||||||
|
tag_directives_data []yaml_tag_directive_t
|
||||||
|
tag_directives_start int // The beginning of the tag directives list.
|
||||||
|
tag_directives_end int // The end of the tag directives list.
|
||||||
|
|
||||||
|
start_implicit int // Is the document start indicator implicit?
|
||||||
|
end_implicit int // Is the document end indicator implicit?
|
||||||
|
|
||||||
|
// The start/end of the document.
|
||||||
|
start_mark, end_mark yaml_mark_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// The prototype of a read handler.
|
||||||
|
//
|
||||||
|
// The read handler is called when the parser needs to read more bytes from the
|
||||||
|
// source. The handler should write not more than size bytes to the buffer.
|
||||||
|
// The number of written bytes should be set to the size_read variable.
|
||||||
|
//
|
||||||
|
// [in,out] data A pointer to an application data specified by
|
||||||
|
// yaml_parser_set_input().
|
||||||
|
// [out] buffer The buffer to write the data from the source.
|
||||||
|
// [in] size The size of the buffer.
|
||||||
|
// [out] size_read The actual number of bytes read from the source.
|
||||||
|
//
|
||||||
|
// On success, the handler should return 1. If the handler failed,
|
||||||
|
// the returned value should be 0. On EOF, the handler should set the
|
||||||
|
// size_read to 0 and return 1.
|
||||||
|
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
|
||||||
|
|
||||||
|
// This structure holds information about a potential simple key.
|
||||||
|
type yaml_simple_key_t struct {
|
||||||
|
possible bool // Is a simple key possible?
|
||||||
|
required bool // Is a simple key required?
|
||||||
|
token_number int // The number of the token.
|
||||||
|
mark yaml_mark_t // The position mark.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The states of the parser.
|
||||||
|
type yaml_parser_state_t int
|
||||||
|
|
||||||
|
const (
|
||||||
|
yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
|
||||||
|
|
||||||
|
yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
|
||||||
|
yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
|
||||||
|
yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||||
|
yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||||
|
yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
|
||||||
|
yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
|
||||||
|
yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
|
||||||
|
yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
|
||||||
|
yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
|
||||||
|
yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
|
||||||
|
yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
|
||||||
|
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||||
|
yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
|
||||||
|
yaml_PARSE_END_STATE // Expect nothing.
|
||||||
|
)
|
||||||
|
|
||||||
|
func (ps yaml_parser_state_t) String() string {
|
||||||
|
switch ps {
|
||||||
|
case yaml_PARSE_STREAM_START_STATE:
|
||||||
|
return "yaml_PARSE_STREAM_START_STATE"
|
||||||
|
case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
|
||||||
|
return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_START_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_START_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_CONTENT_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
|
||||||
|
case yaml_PARSE_DOCUMENT_END_STATE:
|
||||||
|
return "yaml_PARSE_DOCUMENT_END_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_NODE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_NODE_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_NODE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_NODE_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
|
||||||
|
case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
|
||||||
|
return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
|
||||||
|
case yaml_PARSE_END_STATE:
|
||||||
|
return "yaml_PARSE_END_STATE"
|
||||||
|
}
|
||||||
|
return "<unknown parser state>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// This structure holds aliases data.
|
||||||
|
type yaml_alias_data_t struct {
|
||||||
|
anchor []byte // The anchor.
|
||||||
|
index int // The node id.
|
||||||
|
mark yaml_mark_t // The anchor mark.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The parser structure.
|
||||||
|
//
|
||||||
|
// All members are internal. Manage the structure using the
|
||||||
|
// yaml_parser_ family of functions.
|
||||||
|
type yaml_parser_t struct {
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
|
||||||
|
error yaml_error_type_t // Error type.
|
||||||
|
|
||||||
|
problem string // Error description.
|
||||||
|
|
||||||
|
// The byte about which the problem occured.
|
||||||
|
problem_offset int
|
||||||
|
problem_value int
|
||||||
|
problem_mark yaml_mark_t
|
||||||
|
|
||||||
|
// The error context.
|
||||||
|
context string
|
||||||
|
context_mark yaml_mark_t
|
||||||
|
|
||||||
|
// Reader stuff
|
||||||
|
|
||||||
|
read_handler yaml_read_handler_t // Read handler.
|
||||||
|
|
||||||
|
input_file io.Reader // File input data.
|
||||||
|
input []byte // String input data.
|
||||||
|
input_pos int
|
||||||
|
|
||||||
|
eof bool // EOF flag
|
||||||
|
|
||||||
|
buffer []byte // The working buffer.
|
||||||
|
buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
unread int // The number of unread characters in the buffer.
|
||||||
|
|
||||||
|
raw_buffer []byte // The raw buffer.
|
||||||
|
raw_buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
encoding yaml_encoding_t // The input encoding.
|
||||||
|
|
||||||
|
offset int // The offset of the current position (in bytes).
|
||||||
|
mark yaml_mark_t // The mark of the current position.
|
||||||
|
|
||||||
|
// Scanner stuff
|
||||||
|
|
||||||
|
stream_start_produced bool // Have we started to scan the input stream?
|
||||||
|
stream_end_produced bool // Have we reached the end of the input stream?
|
||||||
|
|
||||||
|
flow_level int // The number of unclosed '[' and '{' indicators.
|
||||||
|
|
||||||
|
tokens []yaml_token_t // The tokens queue.
|
||||||
|
tokens_head int // The head of the tokens queue.
|
||||||
|
tokens_parsed int // The number of tokens fetched from the queue.
|
||||||
|
token_available bool // Does the tokens queue contain a token ready for dequeueing.
|
||||||
|
|
||||||
|
indent int // The current indentation level.
|
||||||
|
indents []int // The indentation levels stack.
|
||||||
|
|
||||||
|
simple_key_allowed bool // May a simple key occur at the current position?
|
||||||
|
simple_keys []yaml_simple_key_t // The stack of simple keys.
|
||||||
|
|
||||||
|
// Parser stuff
|
||||||
|
|
||||||
|
state yaml_parser_state_t // The current parser state.
|
||||||
|
states []yaml_parser_state_t // The parser states stack.
|
||||||
|
marks []yaml_mark_t // The stack of marks.
|
||||||
|
tag_directives []yaml_tag_directive_t // The list of TAG directives.
|
||||||
|
|
||||||
|
// Dumper stuff
|
||||||
|
|
||||||
|
aliases []yaml_alias_data_t // The alias data.
|
||||||
|
|
||||||
|
document *yaml_document_t // The currently parsed document.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emitter Definitions
|
||||||
|
|
||||||
|
// The prototype of a write handler.
|
||||||
|
//
|
||||||
|
// The write handler is called when the emitter needs to flush the accumulated
|
||||||
|
// characters to the output. The handler should write @a size bytes of the
|
||||||
|
// @a buffer to the output.
|
||||||
|
//
|
||||||
|
// @param[in,out] data A pointer to an application data specified by
|
||||||
|
// yaml_emitter_set_output().
|
||||||
|
// @param[in] buffer The buffer with bytes to be written.
|
||||||
|
// @param[in] size The size of the buffer.
|
||||||
|
//
|
||||||
|
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||||
|
// the returned value should be @c 0.
|
||||||
|
//
|
||||||
|
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||||
|
|
||||||
|
type yaml_emitter_state_t int
|
||||||
|
|
||||||
|
// The emitter states.
|
||||||
|
const (
|
||||||
|
// Expect STREAM-START.
|
||||||
|
yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
|
||||||
|
|
||||||
|
yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
|
||||||
|
yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
|
||||||
|
yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
|
||||||
|
yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
|
||||||
|
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
|
||||||
|
yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
|
||||||
|
yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
|
||||||
|
yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
|
||||||
|
yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
|
||||||
|
yaml_EMIT_END_STATE // Expect nothing.
|
||||||
|
)
|
||||||
|
|
||||||
|
// The emitter structure.
|
||||||
|
//
|
||||||
|
// All members are internal. Manage the structure using the @c yaml_emitter_
|
||||||
|
// family of functions.
|
||||||
|
type yaml_emitter_t struct {
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
|
||||||
|
error yaml_error_type_t // Error type.
|
||||||
|
problem string // Error description.
|
||||||
|
|
||||||
|
// Writer stuff
|
||||||
|
|
||||||
|
write_handler yaml_write_handler_t // Write handler.
|
||||||
|
|
||||||
|
output_buffer *[]byte // String output data.
|
||||||
|
output_file io.Writer // File output data.
|
||||||
|
|
||||||
|
buffer []byte // The working buffer.
|
||||||
|
buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
raw_buffer []byte // The raw buffer.
|
||||||
|
raw_buffer_pos int // The current position of the buffer.
|
||||||
|
|
||||||
|
encoding yaml_encoding_t // The stream encoding.
|
||||||
|
|
||||||
|
// Emitter stuff
|
||||||
|
|
||||||
|
canonical bool // If the output is in the canonical style?
|
||||||
|
best_indent int // The number of indentation spaces.
|
||||||
|
best_width int // The preferred width of the output lines.
|
||||||
|
unicode bool // Allow unescaped non-ASCII characters?
|
||||||
|
line_break yaml_break_t // The preferred line break.
|
||||||
|
|
||||||
|
state yaml_emitter_state_t // The current emitter state.
|
||||||
|
states []yaml_emitter_state_t // The stack of states.
|
||||||
|
|
||||||
|
events []yaml_event_t // The event queue.
|
||||||
|
events_head int // The head of the event queue.
|
||||||
|
|
||||||
|
indents []int // The stack of indentation levels.
|
||||||
|
|
||||||
|
tag_directives []yaml_tag_directive_t // The list of tag directives.
|
||||||
|
|
||||||
|
indent int // The current indentation level.
|
||||||
|
|
||||||
|
flow_level int // The current flow level.
|
||||||
|
|
||||||
|
root_context bool // Is it the document root context?
|
||||||
|
sequence_context bool // Is it a sequence context?
|
||||||
|
mapping_context bool // Is it a mapping context?
|
||||||
|
simple_key_context bool // Is it a simple mapping key context?
|
||||||
|
|
||||||
|
line int // The current line.
|
||||||
|
column int // The current column.
|
||||||
|
whitespace bool // If the last character was a whitespace?
|
||||||
|
indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
|
||||||
|
open_ended bool // If an explicit document end is required?
|
||||||
|
|
||||||
|
// Anchor analysis.
|
||||||
|
anchor_data struct {
|
||||||
|
anchor []byte // The anchor value.
|
||||||
|
alias bool // Is it an alias?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag analysis.
|
||||||
|
tag_data struct {
|
||||||
|
handle []byte // The tag handle.
|
||||||
|
suffix []byte // The tag suffix.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scalar analysis.
|
||||||
|
scalar_data struct {
|
||||||
|
value []byte // The scalar value.
|
||||||
|
multiline bool // Does the scalar contain line breaks?
|
||||||
|
flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
|
||||||
|
block_plain_allowed bool // Can the scalar be expressed in the block plain style?
|
||||||
|
single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
|
||||||
|
block_allowed bool // Can the scalar be expressed in the literal or folded styles?
|
||||||
|
style yaml_scalar_style_t // The output style.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dumper stuff
|
||||||
|
|
||||||
|
opened bool // If the stream was already opened?
|
||||||
|
closed bool // If the stream was already closed?
|
||||||
|
|
||||||
|
// The information associated with the document nodes.
|
||||||
|
anchors *struct {
|
||||||
|
references int // The number of references.
|
||||||
|
anchor int // The anchor id.
|
||||||
|
serialized bool // If the node has been emitted?
|
||||||
|
}
|
||||||
|
|
||||||
|
last_anchor_id int // The last assigned anchor id.
|
||||||
|
|
||||||
|
document *yaml_document_t // The currently emitted document.
|
||||||
|
}
|
173
Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go
generated
vendored
Normal file
173
Godeps/_workspace/src/gopkg.in/yaml.v2/yamlprivateh.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
package yaml
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The size of the input raw buffer.
|
||||||
|
input_raw_buffer_size = 512
|
||||||
|
|
||||||
|
// The size of the input buffer.
|
||||||
|
// It should be possible to decode the whole raw buffer.
|
||||||
|
input_buffer_size = input_raw_buffer_size * 3
|
||||||
|
|
||||||
|
// The size of the output buffer.
|
||||||
|
output_buffer_size = 128
|
||||||
|
|
||||||
|
// The size of the output raw buffer.
|
||||||
|
// It should be possible to encode the whole output buffer.
|
||||||
|
output_raw_buffer_size = (output_buffer_size*2 + 2)
|
||||||
|
|
||||||
|
// The size of other stacks and queues.
|
||||||
|
initial_stack_size = 16
|
||||||
|
initial_queue_size = 16
|
||||||
|
initial_string_size = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the character at the specified position is an alphabetical
|
||||||
|
// character, a digit, '_', or '-'.
|
||||||
|
func is_alpha(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a digit.
|
||||||
|
func is_digit(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value of a digit.
|
||||||
|
func as_digit(b []byte, i int) int {
|
||||||
|
return int(b[i]) - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a hex-digit.
|
||||||
|
func is_hex(b []byte, i int) bool {
|
||||||
|
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value of a hex-digit.
|
||||||
|
func as_hex(b []byte, i int) int {
|
||||||
|
bi := b[i]
|
||||||
|
if bi >= 'A' && bi <= 'F' {
|
||||||
|
return int(bi) - 'A' + 10
|
||||||
|
}
|
||||||
|
if bi >= 'a' && bi <= 'f' {
|
||||||
|
return int(bi) - 'a' + 10
|
||||||
|
}
|
||||||
|
return int(bi) - '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is ASCII.
|
||||||
|
func is_ascii(b []byte, i int) bool {
|
||||||
|
return b[i] <= 0x7F
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the start of the buffer can be printed unescaped.
|
||||||
|
func is_printable(b []byte, i int) bool {
|
||||||
|
return ((b[i] == 0x0A) || // . == #x0A
|
||||||
|
(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
|
||||||
|
(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
|
||||||
|
(b[i] > 0xC2 && b[i] < 0xED) ||
|
||||||
|
(b[i] == 0xED && b[i+1] < 0xA0) ||
|
||||||
|
(b[i] == 0xEE) ||
|
||||||
|
(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
|
||||||
|
!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
|
||||||
|
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is NUL.
|
||||||
|
func is_z(b []byte, i int) bool {
|
||||||
|
return b[i] == 0x00
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the beginning of the buffer is a BOM.
|
||||||
|
func is_bom(b []byte, i int) bool {
|
||||||
|
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is space.
|
||||||
|
func is_space(b []byte, i int) bool {
|
||||||
|
return b[i] == ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is tab.
|
||||||
|
func is_tab(b []byte, i int) bool {
|
||||||
|
return b[i] == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is blank (space or tab).
|
||||||
|
func is_blank(b []byte, i int) bool {
|
||||||
|
//return is_space(b, i) || is_tab(b, i)
|
||||||
|
return b[i] == ' ' || b[i] == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character at the specified position is a line break.
|
||||||
|
func is_break(b []byte, i int) bool {
|
||||||
|
return (b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
|
||||||
|
}
|
||||||
|
|
||||||
|
func is_crlf(b []byte, i int) bool {
|
||||||
|
return b[i] == '\r' && b[i+1] == '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break or NUL.
|
||||||
|
func is_breakz(b []byte, i int) bool {
|
||||||
|
//return is_break(b, i) || is_z(b, i)
|
||||||
|
return ( // is_break:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
// is_z:
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break, space, or NUL.
|
||||||
|
func is_spacez(b []byte, i int) bool {
|
||||||
|
//return is_space(b, i) || is_breakz(b, i)
|
||||||
|
return ( // is_space:
|
||||||
|
b[i] == ' ' ||
|
||||||
|
// is_breakz:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the character is a line break, space, tab, or NUL.
|
||||||
|
func is_blankz(b []byte, i int) bool {
|
||||||
|
//return is_blank(b, i) || is_breakz(b, i)
|
||||||
|
return ( // is_blank:
|
||||||
|
b[i] == ' ' || b[i] == '\t' ||
|
||||||
|
// is_breakz:
|
||||||
|
b[i] == '\r' || // CR (#xD)
|
||||||
|
b[i] == '\n' || // LF (#xA)
|
||||||
|
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||||
|
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||||
|
b[i] == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the width of the character.
|
||||||
|
func width(b byte) int {
|
||||||
|
// Don't replace these by a switch without first
|
||||||
|
// confirming that it is being inlined.
|
||||||
|
if b&0x80 == 0x00 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if b&0xE0 == 0xC0 {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
if b&0xF0 == 0xE0 {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
if b&0xF8 == 0xF0 {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
4
Makefile
4
Makefile
|
@ -19,7 +19,7 @@ dev: generate
|
||||||
|
|
||||||
# test runs the unit tests and vets the code
|
# test runs the unit tests and vets the code
|
||||||
test: generate
|
test: generate
|
||||||
TF_ACC= godep go test $(TEST) $(TESTARGS) -timeout=30s -parallel=4
|
TF_ACC= godep go test $(TEST) $(TESTARGS) -timeout=60s -parallel=4
|
||||||
|
|
||||||
# testacc runs acceptance tests
|
# testacc runs acceptance tests
|
||||||
testacc: generate
|
testacc: generate
|
||||||
|
@ -31,7 +31,7 @@ testacc: generate
|
||||||
|
|
||||||
# testrace runs the race checker
|
# testrace runs the race checker
|
||||||
testrace: generate
|
testrace: generate
|
||||||
TF_ACC= godep go test -race $(TEST) $(TESTARGS)
|
CGO_ENABLED=1 TF_ACC= godep go test -race $(TEST) $(TESTARGS)
|
||||||
|
|
||||||
cover:
|
cover:
|
||||||
./scripts/coverage.sh --html
|
./scripts/coverage.sh --html
|
||||||
|
|
|
@ -57,7 +57,7 @@ Developing Vault
|
||||||
|
|
||||||
If you wish to work on Vault itself or any of its built-in systems,
|
If you wish to work on Vault itself or any of its built-in systems,
|
||||||
you'll first need [Go](https://www.golang.org) installed on your
|
you'll first need [Go](https://www.golang.org) installed on your
|
||||||
machine (version 1.4+ is *required*).
|
machine (version 1.5+ is *required*).
|
||||||
|
|
||||||
For local dev first make sure Go is properly installed, including setting up a
|
For local dev first make sure Go is properly installed, including setting up a
|
||||||
[GOPATH](https://golang.org/doc/code.html#GOPATH). After setting up Go, you can
|
[GOPATH](https://golang.org/doc/code.html#GOPATH). After setting up Go, you can
|
||||||
|
|
|
@ -87,7 +87,7 @@ The following HTTP status codes are used throughout the API.
|
||||||
- `200` - Success with data.
|
- `200` - Success with data.
|
||||||
- `204` - Success, no data returned.
|
- `204` - Success, no data returned.
|
||||||
- `400` - Invalid request, missing or invalid data.
|
- `400` - Invalid request, missing or invalid data.
|
||||||
- `401` - Unauthorized, your authentication details are either
|
- `403` - Forbidden, your authentication details are either
|
||||||
incorrect or you don't have access to this feature.
|
incorrect or you don't have access to this feature.
|
||||||
- `404` - Invalid path. This can both mean that the path truly
|
- `404` - Invalid path. This can both mean that the path truly
|
||||||
doesn't exist or that you don't have permission to view a
|
doesn't exist or that you don't have permission to view a
|
||||||
|
|
|
@ -26,7 +26,7 @@ func (c *TokenAuth) Create(opts *TokenCreateRequest) (*Secret, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TokenAuth) LookupSelf() (*Secret, error) {
|
func (c *TokenAuth) LookupSelf() (*Secret, error) {
|
||||||
r := c.c.NewRequest("POST", "/v1/auth/token/lookup-self")
|
r := c.c.NewRequest("GET", "/v1/auth/token/lookup-self")
|
||||||
|
|
||||||
resp, err := c.c.RawRequest(r)
|
resp, err := c.c.RawRequest(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -34,6 +34,35 @@ func TestAuthTokenCreate(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthTokenLookupSelf(t *testing.T) {
|
||||||
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
|
ln, addr := http.TestServer(t, core)
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
config := DefaultConfig()
|
||||||
|
config.Address = addr
|
||||||
|
|
||||||
|
client, err := NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
client.SetToken(token)
|
||||||
|
|
||||||
|
// you should be able to lookup your own token
|
||||||
|
secret, err := client.Auth().Token().LookupSelf()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should be allowed to lookup self, err = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if secret.Data["id"] != token {
|
||||||
|
t.Errorf("Did not get back details about our own (self) token, id returned=%s", secret.Data["id"])
|
||||||
|
}
|
||||||
|
if secret.Data["display_name"] != "root" {
|
||||||
|
t.Errorf("Did not get back details about our own (self) token, display_name returned=%s", secret.Data["display_name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestAuthTokenRenew(t *testing.T) {
|
func TestAuthTokenRenew(t *testing.T) {
|
||||||
core, _, token := vault.TestCoreUnsealed(t)
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
ln, addr := http.TestServer(t, core)
|
ln, addr := http.TestServer(t, core)
|
||||||
|
|
|
@ -5,11 +5,9 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
"github.com/hashicorp/hcl"
|
"github.com/hashicorp/hcl"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
@ -66,15 +64,9 @@ func (c *SSHAgentConfig) SetTLSParameters(clientConfig *Config, certPool *x509.C
|
||||||
RootCAs: certPool,
|
RootCAs: certPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConfig.HttpClient.Transport = &http.Transport{
|
transport := cleanhttp.DefaultTransport()
|
||||||
Proxy: http.ProxyFromEnvironment,
|
transport.TLSClientConfig = tlsConfig
|
||||||
Dial: (&net.Dialer{
|
clientConfig.HttpClient.Transport = transport
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
}).Dial,
|
|
||||||
TLSClientConfig: tlsConfig,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new client for the configuration. This client will be used by the
|
// NewClient returns a new client for the configuration. This client will be used by the
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue